在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 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
##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的时序图设计,要搞清楚数据流的流向问题,所利用的条件,才能设计出合理的时序。