教程中有如下描述3.3.5 MSG_FIFO 模块MSG_FIFO MSG_FIFO_INST ( .clk(MSG_FIFO_CLK), // input wire clk .din(MSG_FIFO_WRDATA), // input wire [7 : 0] din .wr_en(MSG_FIFO_WREN), // input wire wr_en .rd_en(MSG_FIFO_RDEN), // input wire rd_en .dout(MSG_FIFO_RDDATA),// output wire [7 : 0] dout .full(MSG_FIFO_FULL), // output wire full .empty(empty), // output wire empty .data_count(MSG_FIFO_USEDW) // output wire [4 : 0] data_count );
|
MSG_FIFO 模块的作用是设计了一个消息的缓存,所有读写请求都会先保存在这消息队列里面然后再 按照先后顺序出列。M_S 模块会对 MSG_FIFO里面的消息进行处理。 MSG_FIFO_CLK :MSG_FIFO 的时钟信号 这里就是系统本模块的系统时钟和 MIG 控制器时钟一致。 MSG_FIFO_WRDATA:长度为 8 代表同时可以一次性存储 8 个不同信号 MSG_FIFO_WREN:写消息使能,当读 image_data_gen 和 vga_lcd_driver 模块的场信号过来的时候会 使能写 MSG_FIFO,把消息的状态进入 MSG_FIFO MSG_FIFO_RDDATA:读消息使能,M_S 状态机会逐条取出 MSG_FIFO 队列中的消息。 MSG_FIFO_FULL:消息满信号,不应该让此信号满,如果满必然发出消息溢出
在结合以下状态机,消息FIFO什么时候复位呢?只有当消息FIFO里面有数据,也就是发生了读VS 信号,或者写VS信号,FIFO才会有数据。先取出消息FIFO的数据,这样可以判断出来FIFO里面的数据是写VS同步,还是读VS同步,然后再去复位写FIFO 或者读FIFO M_S_MSG_FIFO0://--FIFO有数据就读取--// begin M_S <=({MSG_FIFO_FULL,MSG_FIFO_USEDW}!=5'd0)?M_S_MSG_FIFO1:M_S_IDLE; MSG_FIFO_RDEN <=({MSG_FIFO_FULL,MSG_FIFO_USEDW}!=5'd0); CH0_FIFO_RST <=1'd0; CH6_FIFO_RST <=1'd0; rst_FIFO_cnt <=8'd0; count_rden <=8'd0; count_wren <=8'd0; end
M_S_MSG_FIFO1://--延迟1个时钟--// begin M_S <=M_S_MSG_FIFO2; MSG_FIFO_RDEN <=1'd0; end
M_S_MSG_FIFO2://--相对地址处理--// begin M_S <=M_S_RST_FIFO0; //三缓存设计 if(MSG_FIFO_RDDATA[7])begin if(CH0_Fbuf == 2) begin CH0_Fbuf <= 0; end else begin CH0_Fbuf <= CH0_Fbuf + 1'b1; end CH0_PTR <= 21'd0; end
if(MSG_FIFO_RDDATA[6])begin if(CH0_Fbuf == 0) begin CH6_Fbuf <= 2; end else begin CH6_Fbuf <= CH0_Fbuf - 1'b1; end CH6_PTR <= 21'd0; end
end
//------------------------读取FIFO的控制信号-------------------------// M_S_RST_FIFO0: begin M_S <=(rst_FIFO_cnt>=8'd60)?M_S_IDLE:M_S; CH6_FIFO_RST <=(rst_FIFO_cnt<=8'd20)&&MSG_FIFO_RDDATA[6]; CH0_FIFO_RST <=(rst_FIFO_cnt<=8'd20)&&MSG_FIFO_RDDATA[7]; rst_FIFO_cnt <=rst_FIFO_cnt+8'd1; end
//-------------------------状态机空闲状态--------------------------// M_S_IDLE: begin count_rden <=8'd0; count_wren <=8'd0; casex ({//-读写通道仲裁-// CH0_REQ&&1'd1,//ch0_输入信道 1'b0,//ch1_预留信道 1'b0,//ch2_预留信道 1'b0,//ch3_预留信道 1'b0,//ch4_预留信道 1'b0,//ch5_预留信道 CH6_REQ&&1'd1//ch6_输出信道 }) 7'b1??????: //-Sensor写数据-// begin M_S <=M_S_WR; end 7'b0000001: //-vga读数据-// begin M_S <=M_S_RD; end default: begin M_S <=M_S_MSG_FIFO0; end endcase end //-------------------------sdram读状态--------------------------// M_S_RD: //--读取数据--// begin CH6_PTR <= app_rdy ?(CH6_PTR+4'd8) : CH6_PTR ;//每次写入的数据地址 M_S <= app_rdy&&(count_rden==RD_BURST_LEN-1'b1)?M_S_MSG_FIFO0:M_S; //释放本次写权限 count_rden <= app_rdy ? count_rden+1'd1:count_rden;//count_rden用来标记一次burst的数据量 end //-------------------------sdram写状态--------------------------// M_S_WR://--写入数据--// begin CH0_PTR <= app_rdy&&app_wdf_rdy? (CH0_PTR+4'd8) : CH0_PTR ;//每次写入的数据地址 M_S <=app_rdy&&app_wdf_rdy&&(count_wren==WR_BURST_LEN-1'b1)?M_S_MSG_FIFO0:M_S;//释放本次写权限 count_wren <=app_rdy&&app_wdf_rdy ? count_wren+1'd1:count_wren;//count_wren用来标记一次burst的数据量 end default: begin M_S <=M_S_MSG_FIFO0; count_rden <=8'd0; count_wren <=8'd0; end endcase |