SDRAM小项目——命令解析模块

简单介绍:

在FPGA中实现命令解析模块,命令解析模块的用来把pc端传入FPGA中的数据分解为所需要的数据和触发命令,虽然代码不多,但是却十分重要。

SDRAM的整体结构如下,可以看出,命令解析模块cmd_decode负责解析uart_rx中的信息

SDRAM小项目——命令解析模块_第1张图片

分析:

命令解析模块主要分离触发信号和需要写入数据data,uart发送端发送数据55时后表示之后的四组数据应该写入,发送aa则表示读命令,开始读数据。

uart_flag表示数据到来。

命令解析模块计数器rec_num变化时相对于uart_data延迟一个周期,这是因为rec_num为条件,确保其他变量的数据稳定性。

cmd_reg为55表示写数据,aa表示读数据,都在rec_num等于0的时候开始变化。

SDRAM小项目——命令解析模块_第2张图片

命令解析模块代码:

module cmd_decode(
		input		sclk,
		input		srst,
		//from uart
		input 		uart_flag,
		input	[7:0]	uart_data,
		//
		output wire		wr_trig,
		output	wire	rd_trig,
		output	wire	wfifo_wr_en,
		output wire [7:0] wfifo_data	
);

//==========================================================
//=======	define parameter and internal signal	========
//==========================================================
localparam			REC_MUN_END =  4;

reg		[3:0]		rec_num;
reg		[7:0]		cmd_reg;

//==========================================================
//====================	main	code	====================
//==========================================================

always@(posedge sclk or negedge srst) begin
		if(srst == 1'b0)
			rec_num <= 'd0;
		else if(uart_flag == 1'b1 && uart_data == 8'haa &&rec_num == 'd0)
			rec_num <= 'd0;           //不自加
		else if(rec_num == REC_MUN_END && uart_flag == 1'b1)
			rec_num <= 'd0;
		else if(uart_flag == 1'b1)
			rec_num <= rec_num +1'b1;
end

always@(posedge sclk or negedge srst )begin
		if(srst == 1'b0)
			cmd_reg <= 'd0;
		else if(uart_flag == 1'b1 && rec_num == 'd0)
			cmd_reg = uart_data ;
end

/*  always@(posedge sclk or negedge srst )begin
		if(srst == 1'b0)
			wr_trig <= 'd0;
		else if(rec_num == REC_MUN_END && uart_flag == 1'b1)
			wr_trig <= 1'b1;
		else 
			wr_trig <= 1'b0;
end

always@(posedge sclk or negedge srst )begin
		if(srst == 1'b0)
			rd_trig <= 'd0;
		else if(rec_num == 'd0 && cmd_reg == 8'haa)
			rd_trig <= 1'b1;
		else 
			rd_trig <= 1'b0;
end

always@(posedge sclk or negedge srst )begin
		if(srst == 1'b0)
			wfifo_wr_en <= 'd0;
		else if(uart_flag == 1'b1 && rec_num != 'd0)
			wfifo_wr_en <= 1'b1; 
end */

assign wr_trig  = (rec_num == REC_MUN_END )? uart_flag : 1'b0;
assign rd_trig = (rec_num == 'd0 && uart_data == 8'haa)? uart_flag : 1'b0;
assign wfifo_wr_en  = (rec_num >= 1'd1) ? uart_flag :1'b0;
assign wfifo_data = uart_data ;

endmodule

测试代码:

`timescale 1ns/1ns

module tb_cmd_decode;

reg 		sclk;
reg 		srst; 
reg 		uart_flag;
reg  		[7:0]uart_data;

wire		wr_trig	    ;
wire		rd_trig	    ;
wire		wfifo_wr_en ;
wire	[7:0]	wfifo_data	;


initial begin
		sclk =1;
		srst = 0;
		#100
		srst = 1;
end

always #5 sclk   = ~sclk;

initial begin
		uart_flag <= 0;
		uart_data  <= 0;
		#200
		uart_flag <= 1;
		uart_data <= 8'h55;
		#10
		uart_flag <= 0;
		
		#200
		uart_flag <= 1;
		uart_data <= 8'h12;
		#10
		uart_flag <= 0;
		
		#200
		uart_flag <= 1;
		uart_data <= 8'h34;
		#10
		uart_flag <= 0;
		
		#200
		uart_flag <= 1;
		uart_data <= 8'h56;
		#10
		uart_flag <= 0;
		
		#200
		uart_flag <= 1;
		uart_data <= 8'h78;
		#10
		uart_flag <= 0;
		
		#200
		uart_flag <= 1;
		uart_data <= 8'haa;
		#10
		uart_flag <= 0;
end

cmd_decode  cmd_decode_inst(
		.sclk					(sclk),
		.srst					(srst),
		.uart_flag				(uart_flag),
		.uart_data				(uart_data),
		.wr_trig				(wr_trig),
		.rd_trig				(rd_trig),
		.wfifo_wr_en			(wfifo_wr_en),
		.wfifo_data	            (wfifo_data)
);

endmodule

modelsim脚本:

##create work library
vlib work

vlog		"./tb_cmd_decode.v"
vlog		"./cmd_decode.v"

vsim	-voptargs=+acc work.tb_cmd_decode

# Set the window types
view wave
view structure
view signals

add wave -divider {tb_cmd_decode}
add wave tb_cmd_decode/*
add wave -divider {cmd_decode}
add wave tb_cmd_decode/cmd_decode_inst/*

run 10us

问题:

1.为什么wr_flag信号要在第四个数据发送的时候拉高,而不是在四个数据发送结束的时候拉高(视频上讲的是发送写trig信号的时候要把FIFO中的数据拿出来,所以不是在发送55的时候就拉高)

收获:

1.对于fpga的时序图设计,要搞清楚数据流的流向问题,所利用的条件,才能设计出合理的时序。

你可能感兴趣的:(fpga开发)