练习九 利用状态机实现比较复杂的接口设计

源代码

`timescale 1ns / 1ps
//
// Company: 
// Engineer: 
// 
// Create Date:    14:22:57 07/30/2019 
// Design Name: 
// Module Name:    writing_test 
// Project Name: 
// Target Devices: 
// Tool versions: 
// Description: 
//
// Dependencies: 
//
// Revision: 
// Revision 0.01 - File Created
// Additional Comments: 
//
//
module writing_test(
							reset,
							clk,
							address,
							data,
							sda,
							ack
    );
	input reset,clk;
	input [7:0]data,address;

	inout sda;	//串行数据的输出或输入接口
	output ack;	//模块给出的应答信号
	reg link_write;	//link_write决定何时输出
	reg [3:0]state;	//主状态的状态字
	reg [4:0]sh8out_state;	//从状态的状态字
	reg [7:0]sh8out_buf;	//输入数据缓冲
	reg finish_F;	//用以判断是否处理完一个操作对象
	reg ack;

	parameter 
		idle = 0,addr_write = 1,data_write = 2,stop_ack = 3;
	parameter
		bit0 = 1,bit1 = 2,bit2 = 3,bit3 = 4,bit4 = 5,bit5 = 6,bit6 = 7,bit7 = 8;
	assign sda = link_write ? sh8out_buf[7] : 1'bz;
	
	always @(posedge clk)
		begin
			if(!reset)
				begin
					link_write		<= 0;			//挂起串行单总线
					state				<= idle;		
					finish_F			<= 0;			//结束标志清零
					sh8out_state	<= idle;
					ack				<= 0;
					sh8out_buf		<= 0;
				end
			else
				case(state)
					idle :
							begin
								link_write		<= 0;				//断开串行单总线
								finish_F			<= 0;
								sh8out_state	<=	idle;
								ack				<= 0;
								sh8out_buf     <= address;		//并行地址存入寄存器
								state				<= addr_write;		//进入下一个状态
							end
					
					addr_write :						//地址输入
									begin
										if(finish_F	== 0)
											begin
												shift8_out;	//	地址串行输出
											end
										else
											begin
												sh8out_state 	<=	idle;
												sh8out_buf 		<= data;//并行数据存入寄存器
												state				<= data_write;
												finish_F			<= 0;
											end
										end
										
					data_write :					//数据写入
									begin
										if(finish_F	== 0)
											begin
												shift8_out;	//	数据串行输出
											end
										else
											begin
												link_write	<= 0;
												state 		<= stop_ack;
												finish_F		<= 0;
												ack 			<= 1;			//向信号源发出应答
											end	
										end
					
					stop_ack :
								begin
									ack	<= 0;
									state		<= idle;
								end
				
				endcase
		end
		
		task shift8_out;				//地址和数据的串行输出
			begin
				case(sh8out_state)
					idle :
						begin
							link_write <= 1;			//连接串行单总线,立即输出地址或数据的最高位
							sh8out_state <= bit7;
						end
					bit7:
							begin
								link_write <= 1;//连接串行单总线
								sh8out_state <= bit6;
								sh8out_buf <= sh8out_buf<<1;//输出地址或数据的次高位
							end
					bit6:
							begin
								sh8out_state <= bit5;
								sh8out_buf <= sh8out_buf<<1;
							end
					bit5:
							begin
								sh8out_state <= bit4;
								sh8out_buf <= sh8out_buf<<1;
							end			
					bit4:
							begin
								sh8out_state <= bit3;
								sh8out_buf <= sh8out_buf<<1;
							end	
					bit3:
							begin
								sh8out_state <= bit2;
								sh8out_buf <= sh8out_buf<<1;
							end		
					bit2:
							begin
								sh8out_state <= bit1;
								sh8out_buf <= sh8out_buf<<1;
							end
					bit1:
							begin
								sh8out_state <= bit0;
								sh8out_buf <= sh8out_buf<<1;//输出地址或数据的最低位
							end
					bit0:
							begin
								link_write <= 0;//挂起串行单总线
								finish_F <= 1;//建立结束标志
							end
				endcase
			end
		endtask
		
					

endmodule

测试代码

`timescale 1ns / 100ps
`define clk_cycle 50

// Company: 
// Engineer:
//
// Create Date:   15:22:14 07/30/2019
// Design Name:   writing_test
// Module Name:   D:/FPGA/project/writing_test/testbench/vtf_writing_test.v
// Project Name:  writing_test
// Target Device:  
// Tool versions:  
// Description: 
//
// Verilog Test Fixture created by ISE for module: writing_test
//
// Dependencies:
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 


module vtf_writing_test;

	// Inputs
	reg reset;
	reg clk;
	reg [7:0] address;
	reg [7:0] data;

	// Outputs
	wire ack;

	// Bidirs
	wire sda;

	// Instantiate the Unit Under Test (UUT)
	writing_test uut (
		.reset(reset), 
		.clk(clk), 
		.address(address), 
		.data(data), 
		.sda(sda), 
		.ack(ack)
	);
	always #`clk_cycle  clk = ~clk;
	initial begin
		// Initialize Inputs
		
		clk = 0;
		address = 0;
		data = 0;
		reset = 1;
		#(2*`clk_cycle)  reset = 0;
		#(2*`clk_cycle)  reset = 1;
		#(100*`clk_cycle)  $stop;
	end
	
	always @(posedge ack)
		begin
			data = data + 1;
			address = address + 1;
		end

	
      
endmodule


仿真波形

在这里插入图片描述

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值