简单介绍:
在FPGA中实现命令解析模块,命令解析模块的用来把pc端传入FPGA中的数据分解为所需要的数据和触发命令,虽然代码不多,但是却十分重要。
SDRAM的整体结构如下,可以看出,命令解析模块cmd_decode负责解析uart_rx中的信息
分析:
命令解析模块主要分离触发信号和需要写入数据data,uart发送端发送数据55时后表示之后的四组数据应该写入,发送aa则表示读命令,开始读数据。
uart_flag表示数据到来。
命令解析模块计数器rec_num变化时相对于uart_data延迟一个周期,这是因为rec_num为条件,确保其他变量的数据稳定性。
cmd_reg为55表示写数据,aa表示读数据,都在rec_num等于0的时候开始变化。
命令解析模块代码:
module cmd_decode(input sclk,input srst,//from uartinput 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) beginif(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;
endalways@(posedge sclk or negedge srst )beginif(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 )beginif(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;
endalways@(posedge sclk or negedge srst )beginif(srst == 1'b0)rd_trig <= 'd0;else if(rec_num == 'd0 && cmd_reg == 8'haa)rd_trig <= 1'b1;else rd_trig <= 1'b0;
endalways@(posedge sclk or negedge srst )beginif(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/1nsmodule 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 beginsclk =1;srst = 0;#100srst = 1;
endalways #5 sclk = ~sclk;initial beginuart_flag <= 0;uart_data <= 0;#200uart_flag <= 1;uart_data <= 8'h55;#10uart_flag <= 0;#200uart_flag <= 1;uart_data <= 8'h12;#10uart_flag <= 0;#200uart_flag <= 1;uart_data <= 8'h34;#10uart_flag <= 0;#200uart_flag <= 1;uart_data <= 8'h56;#10uart_flag <= 0;#200uart_flag <= 1;uart_data <= 8'h78;#10uart_flag <= 0;#200uart_flag <= 1;uart_data <= 8'haa;#10uart_flag <= 0;
endcmd_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 workvlog "./tb_cmd_decode.v"
vlog "./cmd_decode.v"vsim -voptargs=+acc work.tb_cmd_decode# Set the window types
view wave
view structure
view signalsadd 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的时序图设计,要搞清楚数据流的流向问题,所利用的条件,才能设计出合理的时序。