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

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

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,波形输出



相关推荐
FPGA_无线通信2 分钟前
FPGA 组合逻辑和时序逻辑
fpga开发
Js_cold1 小时前
Xilinx FPGA温度等级及选型建议
fpga开发·fpga·vivado·xilinx
从此不归路3 小时前
FPGA 结构与 CAD 设计(第5章)上
fpga开发
洋洋Young3 小时前
【Xilinx FPGA】7 Series Clocking 设计
fpga开发·xilinx fpga
156082072193 小时前
FPGA下AD采集时钟相位的调整
fpga开发
从此不归路3 小时前
FPGA 结构与 CAD 设计(第5章)下
fpga开发
Js_cold6 小时前
Xilinx FPGA Flash启动时钟频率
单片机·嵌入式硬件·fpga开发·vivado·xilinx·flash·cclk
博览鸿蒙1 天前
FPGA的学习路径和入行指南
fpga开发
ShiMetaPi1 天前
GM-3568JHF丨ARM+FPGA异构开发板应用开发教程:01 UART读写案例
arm开发·单片机·嵌入式硬件·fpga开发·fpga·rk3568
楠了个难1 天前
AXI4接口简介——ZYNQ学习笔记24
笔记·学习·fpga开发