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

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

1,任务目的:

(1)学习运用状态机控制的逻辑开关,并设计出一个比较复杂的接口逻辑;

(2)在复杂设计中使用任务(task)结构,以提高程序的可读性;

(3)加深对可综合风格模块的认识。
下面例子是一个并行数据转换为串行位流的变换器,利用双向总线输出。该案例来自于EPROM读写器,电路工作的步骤是:
(1)把并行地址存入寄存器; (2)把并行数据存入寄存器; (3)连接串行单总线; (4)地址的串行输出; (5)数据的串行输出; (6)挂起串行单总线; (7)给信号源应答; (8)让信号源给出下一个操作对象; (9)结束写操作。

2,RTL代码

cpp 复制代码
`timescale 1ns / 1ps
//
// Company: 
// Engineer: 
// 
// Create Date: 2023/11/22 10:52:02
// Design Name: 
// Module Name: writing
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//

module writing(
rst_n, clk, address, data, sda, ack);

input			rst_n, 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;
parameter	addr_write	= 1;
parameter	data_write	= 2;
parameter	stop_ack	= 3;

parameter	bit0		= 1;
parameter	bit1		= 2;
parameter	bit2		= 3;
parameter	bit3		= 4;
parameter	bit4		= 5;
parameter	bit5		= 6;
parameter	bit6		= 7;
parameter	bit7		= 8;

assign		sda = link_write ? sh8out_buf[7] : 1'bz;

always@(posedge clk)	begin
	if(!rst_n)	begin	// 复位
		link_write		<= 0;		// 挂起串行总线
		sh8out_state	<= idle;
		sh8out_buf		<= 0;
		state			<= idle;
		finish_F		<= 0;		// 结束标志清零
		ack				<= 0;
		end
		
	else	
		case(state)
			idle:	begin
				link_write		<= 0;	// 断开串行单总线
				sh8out_state	<= idle;
				sh8out_buf		<= address;	// 并行地址存入寄存器
				state			<= addr_write;	// 进入下一个状态
				finish_F		<= 0;				
				ack				<= 0;
				end
			
			addr_write:		// 地址的输入
				if(finish_F == 0)	
					shift8_out	;	// 地址的串行输出
					//	?	任务
				else	begin
				
					sh8out_state	<= idle;
					sh8out_buf		<= data;	// 并行数据存入寄存器
					state			<= data_write;
					finish_F		<= 0;
					
					end
			
			data_write:		// 数据的写入
				if(finish_F	== 0)
					shift8_out	;	//	数据的串行输出
					// 任务
				else	begin
					link_write	<= 0;
					
					state		<= stop_ack;
					finish_F	<= 0;
					ack			<= 1;	// 向信号源发出应答
					end
				
			stop_ack:	begin // 向信号源发出应答结果
				ack		<= 0;
				state	<= idle;
				end
		endcase
end

task	shift8_out;	// 地址和数据的串行输出
begin
  case(sh8out_state)
	idle:	begin
		link_write		<= 1;	// 连接串行单总线,立即输出地址或数据的最高位(MSB)
		sh8out_state	<= bit7;
		end
	bit7:	begin
		link_write		<= 1;	// 连接串行单总线
		sh8out_state	<= bit6;
		sh8out_buf		<= sh8out_buf << 1;	// 输出地址或数据的次高位(bit6)
		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;	// 输出地址或数据的最低位(LSB)
		end
	bit0:	begin
		link_write		<= 0;	// 挂起串行单总线
		finish_F		<= 1;	// 建立结束标志
		end
  endcase
end
endtask

endmodule

3,RTL原理框图

4,测试代码

cpp 复制代码
`timescale 1ns / 1ps
//
// Company: 
// Engineer: 
// 
// Create Date: 2023/11/22 10:53:46
// Design Name: 
// Module Name: writing_top
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//

// 测试代码
`define	clk_cycle	50
module	writing_top;
reg		rst_n,	clk;
reg		[7:0]	data, address;
wire	ack,	sda;

always #`clk_cycle	clk = ~clk;

initial	begin
	clk 	= 0;
	rst_n	= 1;
	data	= 0;
	address	= 0;
	#(2   * `clk_cycle)		rst_n = 0;
	#(2   * `clk_cycle)		rst_n = 1;
	#(100 * `clk_cycle)		$stop;
end

always@(posedge ack)	begin
	// 接收到应答信号后,给出下一个处理对象
	data 	= data + 1;
	address	= address + 1;
end

writing u_writing(
.rst_n			(rst_n		),
.clk			(clk		),
.data			(data		),
.address		(address	),
.ack			(ack		),
.sda			(sda		)
);

endmodule

5,波形输出



相关推荐
DS小龙哥1 小时前
基于Zynq FPGA的雷龙SD NAND存储芯片性能测试
fpga开发·sd nand·雷龙·spi nand·spi nand flash·工业级tf卡·嵌入式tf卡
上理考研周导师10 小时前
第二章 虚拟仪器及其构成原理
fpga开发
FPGA技术实战12 小时前
《探索Zynq MPSoC》学习笔记(二)
fpga开发·mpsoc
bigbig猩猩1 天前
FPGA(现场可编程门阵列)的时序分析
fpga开发
Terasic友晶科技1 天前
第2篇 使用Intel FPGA Monitor Program创建基于ARM处理器的汇编或C语言工程<二>
fpga开发·汇编语言和c语言
码农阿豪1 天前
基于Zynq FPGA对雷龙SD NAND的测试
fpga开发·sd nand·spi nand·spi nand flash·工业级tf卡·嵌入式tf卡
江山如画,佳人北望1 天前
EDA技术简介
fpga开发
淘晶驰AK1 天前
电子设计竞赛准备经历分享
嵌入式硬件·fpga开发
最好有梦想~1 天前
FPGA时序分析和约束学习笔记(4、IO传输模型)
笔记·学习·fpga开发