二谈-双FIFO流水案例
使用FIFO控制器,输入86行86列的矩阵,数据由串口传输过来,传过来的数据先一行一行用fifo缓存,然后每三行的同一列进行一次加,即第0,1,2行,第1,2,3行.…..第83,84,85行,每三行作为一组,每一组的每一列的三个数据进行一次加运算。
结果为84*86


a、串口传输过来的86x86个数据是每十个波特时间才传输一次,所以需要控制fifo的写使能每十个波特才能拉高一次。
b、因为是三行数据相加,所以可以把前面两行的数据先存到ffo里面(第0行存fifo1,第1行存fifo2),当第三行数据传输过来的时候,再把三个数据(两个fifo输出端和rx输出)相加。
c、第0,1,2行加完后,需要把第1,2,3行数据相加,这时第0,1,2行的数据已经不在了所以需要在相加的时候把后面两行(第1,2行)数据存到fifo里面,即相加的同时需要将fifo2的数据存入fifo1,pidata的数据存入fifo1。
d、最后三行相加的时候,最后一行不需要存到ffo2里面,最后两行不需要存到fifo1里面。因此要往fifo1存入的数据为第0,1,2..83行;要往fifo2存入的数据为第1,2,3...84行;需要进行加运算的次数为84x86次。
e、数据相加时需要控制每10个波特时间,fifo读出一个数据。




// -----------------------------------------------------------------------------
// Copyright (c) 2014-2025 All rights reserved
// -----------------------------------------------------------------------------
// Author : lvjitao lvjitao_o@163.com
// File : fifio_ctrl.v
// Create : 2025-10-28 09:50:49
// Revise : 2025-10-28 14:14:01
// Editor : sublime text3, tab size (4)
// -----------------------------------------------------------------------------
`timescale 1ns/1psmodule fifio_ctrl(input wire clk,input wire rst_n,input wire [7:0] rx_data,input wire pi_flag,output reg [7:0] po_sum,output reg po_flag);localparam CNT_COL_MAX = 86 - 1;
localparam CNT_ROW_MAX = 86 - 1;reg [6:0] cnt_col;
reg [6:0] cnt_row;reg wr_en1;
//delay
reg wr_en1_pre2;
reg wr_en1_pre1;reg [7:0] data_in1;reg wr_en2;
reg [7:0] data_in2;reg rd_en;// std fifo
wire [7:0] rd_dout1;
wire [7:0] rd_dout2;
reg flag_add;wire empty1, empty2;// write processalways @(posedge clk ) beginif (rst_n == 0) begin// resetcnt_col <= 1'b0;endelse if (pi_flag == 1 && cnt_col == CNT_COL_MAX) begincnt_col <= 'd0;endelse if (pi_flag == 1) begincnt_col <= cnt_col + 1'b1;endendalways @(posedge clk ) beginif (rst_n == 0) begin// resetcnt_row <= 0;endelse if (pi_flag == 1 && cnt_col == CNT_COL_MAX && cnt_row == CNT_ROW_MAX) begincnt_row <= 0;endelse if (pi_flag == 1 && cnt_col == CNT_COL_MAX) begincnt_row <= cnt_row + 1;end
endalways @(posedge clk ) beginif (rst_n == 0) begin// resetwr_en1 <= 0;endelse if (cnt_row == 'd0) beginwr_en1 <= pi_flag;endelse beginwr_en1 <= wr_en1_pre1;end
endalways @(posedge clk ) beginif (rst_n == 0) begin// resetdata_in1 <= 0;endelse if (cnt_row == 'd0 && pi_flag == 1) begindata_in1 <= rx_data;endelse begindata_in1 <= rd_dout2;end
endalways @(posedge clk) beginif (rst_n == 0) begin// resetwr_en2 <= 0;endelse if (cnt_row >= 'd0 && cnt_row < 'd85) beginwr_en2 <= pi_flag;endelse beginwr_en2 <= 0;end
end// 1~84
always @(posedge clk) beginif (rst_n == 0) begin// resetdata_in2 <= 0;endelse if (cnt_row >= 'd0 && cnt_row < 'd85) begindata_in2 <= rx_data;end
end// read precess// 2~85
always @(posedge clk) beginif (rst_n == 0) begin// resetrd_en <= 0;endelse if (cnt_row >1 && cnt_row <= 'd85) beginrd_en <= 1;endelse beginrd_en <= 0;end
endalways @(posedge clk ) beginif (rst_n ==0) begin// resetwr_en1_pre2 <= 0;endelse if (cnt_row >=2 && cnt_row <= 'd84) beginwr_en1_pre2 <= pi_flag;endelse beginwr_en1_pre2 <= 'd0;end
endalways @(posedge clk ) beginwr_en1_pre1 <= wr_en1_pre2;
endalways @(posedge clk ) beginflag_add <= rd_en;
endalways @(posedge clk ) beginif (rst_n == 0) begin// resetpo_sum <= 'd0;endelse if ( flag_add == 1'b1) beginpo_sum <= rd_dout1 + rd_dout2;end
endalways @(posedge clk ) beginpo_flag <= flag_add;
endasync1 async1_1_inst (.wr_clk(clk), // input wire wr_clk.rd_clk(clk), // input wire rd_clk.din(data_in1), // input wire [7 : 0] din.wr_en(wr_en1), // input wire wr_en.rd_en(rd_en), // input wire rd_en.dout(rd_dout1), // output wire [7 : 0] dout.full(), // output wire full.empty(empty1) // output wire empty
);async1 async1_2_inst (.wr_clk(clk), // input wire wr_clk.rd_clk(clk), // input wire rd_clk.din(data_in2), // input wire [7 : 0] din.wr_en(wr_en2), // input wire wr_en.rd_en(rd_en), // input wire rd_en.dout(rd_dout2), // output wire [7 : 0] dout.full(), // output wire full.empty(empty2) // output wire empty
);endmodule
// -----------------------------------------------------------------------------
// Copyright (c) 2014-2025 All rights reserved
// -----------------------------------------------------------------------------
// Author : lvjitao lvjitao_o@163.com
// File : top_double_fifo.v
// Create : 2025-10-28 14:05:26
// Revise : 2025-10-28 14:15:42
// Editor : sublime text3, tab size (4)
// -----------------------------------------------------------------------------
`timescale 1ns/1psmodule top_double_fifo(input wire clk,input wire rst_n,input wire rx,output wire tx);wire s_rst_n;
wire pi_flag;
wire [7:0] rx_data;
wire po_flag;
wire [7:0] po_sum;fifio_ctrl inst_fifio_ctrl(.clk (clk),.rst_n (s_rst_n),.rx_data (rx_data),.pi_flag (pi_flag),.po_flag (po_flag),.po_sum (po_sum),.po_flag (po_flag));fifio_ctrl inst_fifio_ctrl(.clk (clk),.rst_n (s_rst_n),.rx_data (rx_data),.pi_flag (pi_flag),.po_sum (po_sum),.po_flag (po_flag));uart_tx #(.MAX_BUAD_CNT(5208)) inst_uart_tx (.sclk (clk),.s_rst_n (s_rst_n),.pi_data (po_sum),.pi_flag (po_flag),.tx (tx));uart_rx #(.MAX_BUAD_CNT(MAX_BUAD_CNT)) inst_uart_rx (.sclk (clk),.s_rst_n (s_rst_n),.rx (rx),.po_flag (po_flag),.po_data (rx_data));gen_reset inst_gen_reset (.clk(clk), .rst_n(rst_n), .s_rst_n(s_rst_n));endmodule
// -----------------------------------------------------------------------------
// Copyright (c) 2014-2025 All rights reserved
// -----------------------------------------------------------------------------
// Author : lvjitao lvjitao_o@163.com
// File : tb_top_double_fifo.v
// Create : 2025-10-28 14:16:52
// Revise : 2025-10-28 14:28:24
// Editor : sublime text3, tab size (4)
// -----------------------------------------------------------------------------
`timescale 1ns/1psmodule tb_top_double_fifo();reg sclk,s_rst_n;reg [7:0] mem [7395:0];
reg rx;
wire tx;initial begin rx =1;sclk =0;s_rst_n =0;repeat(10) @(posedge sclk);s_rst_n = 1'b1;
endalways #10 sclk = ~sclk;initial begin $readmemh("./data.mif",mem);
endinitial begin repeat(100) @(posedge sclk);gen_rx_byte();
endtask gen_rx_byte;integer i;begin for(i =0;i<7396;i=i+1) begin gen_rx_bit(mem[i]);endend
endtasktask gen_rx_bit(input [7:0] data);integer i;begin for(i =0; i <10 ; i =i+1) begin case(i)0:rx = 0;1:rx = data[0];2:rx = data[1];3:rx = data[2];4:rx = data[3];5:rx = data[4];6:rx = data[5];7:rx = data[6];8:rx = data[7];9:rx = 1;endcase #104160;endend
endtasktop_double_fifo inst_top_double_fifo (.clk(sclk), .rst_n(s_rst_n), .rx(rx), .tx(tx));endmodule剩余uart部分,见往期代码。
