FPGA project : FIFO_SUM

拓展训练:

5X5矩阵,按列相邻三个求和。

仍然是以数据流的形式传入数据(rs232),并以数据流的形式传出数据。

分析:

1,其实这个使用两个深度为2的fifo就可以实现了。

并且不再需要行计数器。

每一行,对应列,相关信号变化是一样的,也就是说和行数没有关系。

2,其实这个行与列计数器,就像状态机。只不过用他俩表示矩阵比用状态机表示更方便更直观。

所以我愿称之为“矩阵式状态机”!

3,第一列的数据传给FIFO1,第二列的数据传给fifo2,第三列的数据到来后,fifo的读使能拉高(fifo1和2公用一个读使能信号)。然后读出数据,然后求和标志信号拉高,然后得到和的结果;

在读使能拉高后,fifo2的写使能拉高,然后把第三列的数据写进fifo2;

在fifo2的写使能拉高后,fifo1的写使能拉高,然后把fifo2此时读出的数据写进fifo1(就是对fifo2读出的数采样)至于为什么fifo1的写使能拉高是在fifo2写使能拉高后。我在这里放上一张图片,上面有更直观的是说明:

代码:

只需要改动fifo_sum模块部分代码即可。如下:

module fifo_sum(
    input       wire            sys_clk     ,
    input       wire            sys_rst_n   ,
    input       wire    [7:0]   data_in     ,
    input       wire            data_flag   ,

    output      reg     [7:0]   po_data     ,
    output      reg             po_data_falg
);
    /*************修改成5行5列矩阵,按列求相邻三列的和****************/
    // parameter 
    parameter 	XLINE_SUM = 3 ,
                MAX_LINE  = 5 , // 本实验跟行计数器没有关系。
                MAX_COL   = 5 ;

    // reg signal define
    reg		[7:0]	cnt_line 	;
    reg  	[7:0]	cnt_col  	;
    reg   			rdreq_r    	; // fifo1 fifo2 公用一个读使能。
    reg    			wrreq1_r 	;
    reg     [7:0]	dataF1_in_r ;
    reg    			wrreq2_r    ;
    reg     [7:0]	dataF2_in_r ;
    reg     [7:0]	data_in_reg1;
    reg     [7:0]	data_in_reg2;
    reg   			flag_sum_r  ;

    // 例化连线
    wire   			rdreq       ;
    wire    [7:0]	dataF1_in   ;
    wire  			wrreq1 		;
    wire			empty1 		;
    wire  			full1  		;
    wire    [7:0]   dataF1_out  ;
    wire  	[2:0]	usedw1 		;
    wire    [7:0]	dataF2_in   ;
    wire  			wrreq2 		;
    wire			empty2 		;
    wire  			full2  		;
    wire    [7:0]   dataF2_out  ;
    wire  	[2:0]	usedw2 		;
/*************************************************************/
    // reg [7:0] cnt_line
    always @(posedge sys_clk or negedge sys_rst_n) begin
        if(~sys_rst_n)
            cnt_line <= 8'd0 ;
        else if(data_flag && cnt_col == MAX_COL - 1 && cnt_line == MAX_LINE - 1)
            cnt_line <= 8'd0 ;
        else if(data_flag && cnt_col == MAX_COL - 1)
            cnt_line <= cnt_line + 1'b1 ;
        else 
            cnt_line <= cnt_line ;
    end
    // reg [7:0] cnt_col
    always @(posedge sys_clk or negedge sys_rst_n) begin
        if(~sys_rst_n)
            cnt_col <= 8'd0 ;
        else if(data_flag && cnt_col == MAX_COL - 1)
            cnt_col <= 8'd0 ;
        else if(data_flag)
            cnt_col <= cnt_col + 1'b1 ;
        else 
            cnt_col <= cnt_col ;
    end
    // reg   			rdreq_r    	; // fifo1 fifo2 公用一个读使能。
    always @(posedge sys_clk or negedge sys_rst_n) begin
        if(~sys_rst_n)
            rdreq_r <= 1'b0 ;
        else if(cnt_col >= MAX_COL - XLINE_SUM)
            rdreq_r <= data_flag ;
        else 
            rdreq_r <= 1'b0 ;
    end
    // reg    			wrreq1_r 	;
    always @(posedge sys_clk or negedge sys_rst_n) begin
        if(~sys_rst_n)
            wrreq1_r <= 1'b0 ;
        else if(cnt_col == 0)
            wrreq1_r <= data_flag ;
        else if(cnt_col >= 3) // 改成大于等于3更具有普适性。
            wrreq1_r <= wrreq2_r ;
        else 
            wrreq1_r <= 1'b0 ;
    end
    // reg     [7:0]	dataF1_in_r ;
    always @(posedge sys_clk or negedge sys_rst_n) begin
        if(~sys_rst_n)
            dataF1_in_r <= 8'd0 ;
        else if(cnt_col == 0)
            dataF1_in_r <= data_in ;
        else if(cnt_col >= 3)
            dataF1_in_r <= dataF2_out ;
        else 
            dataF1_in_r <= dataF1_in_r ;
    end
    // reg    			wrreq2_r    ;
    always @(posedge sys_clk or negedge sys_rst_n) begin
        if(~sys_rst_n)
            wrreq2_r <= 1'b0 ;
        else if(cnt_col == 1)
            wrreq2_r <= data_flag ;
        else if(cnt_col >= 2 && cnt_col <= MAX_COL - 2)
            wrreq2_r <= rdreq_r ;
    end
    // reg     [7:0]	dataF2_in_r ;
    always @(posedge sys_clk or negedge sys_rst_n) begin
        if(~sys_rst_n)
            dataF2_in_r <= 8'd0 ;
        else if(cnt_col == 1)
            dataF2_in_r <= data_in ;
        else if(cnt_col >= 2 && cnt_col <= MAX_COL - 2)
            dataF2_in_r <= data_in_reg1 ;
        else 
            dataF2_in_r <= dataF2_in_r ;
    end
    // reg flag_sum_r ;
    always @(posedge sys_clk or negedge sys_rst_n) begin
        if(~sys_rst_n) 
            flag_sum_r <= 1'b0 ;
        else
            flag_sum_r <= rdreq_r ;
    end
/**********************************************************/
    // reg     [7:0]   po_data      ;
    always @(posedge sys_clk or negedge sys_rst_n) begin
        if(~sys_rst_n)
            po_data <= 8'd0 ;
        else if(flag_sum_r) 
            po_data <= dataF1_out + dataF2_out + data_in_reg2 ;
        else 
            po_data <= po_data ;
    end
    // reg             po_data_falg ;
    always @(posedge sys_clk or negedge sys_rst_n) begin
        if(~sys_rst_n)
            po_data_falg <= 1'b0 ;
        else if(flag_sum_r) 
            po_data_falg <=1'b1 ;
        else 
            po_data_falg <= 1'b0 ;
    end
    // reg     [7:0]	data_in_reg1;
    // reg     [7:0]	data_in_reg2;
    always @(posedge sys_clk or negedge sys_rst_n) begin
        if(~sys_rst_n) begin
            data_in_reg1 <= 8'd0 ;
            data_in_reg2 <= 8'd0 ;
        end else begin
            data_in_reg1 <= data_in      ;
            data_in_reg2 <= data_in_reg1 ;
        end
    end
/*************************************************************/
    assign	dataF1_in	= dataF1_in_r ;
    assign	wrreq1		= wrreq1_r	  ;
    assign	rdreq		= rdreq_r     ;
    assign	dataF2_in	= dataF2_in_r ;
    assign	wrreq2		= wrreq2_r	  ;

fifo_8x8 fifo_8x8_inst1( // 我测试了一下这个fifo 写满了之后读写信号同时拉高,要写的数据不会被写进去。除非有余量才能同时拉高,并且写入数据。
    .clock				( sys_clk    ) ,
    .data				( dataF1_in  ) ,
    .rdreq				( rdreq      ) ,
    .wrreq				( wrreq1     ) ,
    .empty				( empty1     ) ,
    .full				( full1      ) ,
    .q					( dataF1_out ) ,
    .usedw				( usedw1 	 )
);
fifo_8x8 fifo_8x8_inst2(  
    .clock				( sys_clk    ) ,
    .data				( dataF2_in  ) ,
    .rdreq				( rdreq      ) ,
    .wrreq				( wrreq2     ) ,
    .empty				( empty2     ) ,
    .full				( full2      ) ,
    .q					( dataF2_out ) ,
    .usedw				( usedw2 	 )
);

endmodule

仿真模块代码:

`timescale 1ns/1ns
module test_top();
    reg             sys_clk   ;
    reg             sys_rst_n ;
    reg             rx        ;

    wire            tx        ;
// Instantiation
top top_inst(
    .sys_clk            ( sys_clk   ) ,
    .sys_rst_n          ( sys_rst_n ) ,
    .rx                 ( rx        ) ,

    .tx                 ( tx        )          
);
    parameter CYCLE = 20 ;
    defparam  top_inst.uart_rx_inst.CLK_UART = 50_000_0 ;
    defparam  top_inst.uart_tx_inst.CLK_UART = 50_000_0 ;
    defparam  top_inst.uart_tx_inst.SUB_1K   = 10       ;
    
    task rx_bit ;
    input   [7:0]   data ;
    integer i ;
    for (i = 0;i <= 9 ;i = i  + 1 ) begin
        case (i)
            0: rx <= 1'b0 ;
            1: rx <= data[i - 1];
            2: rx <= data[i - 1];
            3: rx <= data[i - 1];
            4: rx <= data[i - 1];
            5: rx <= data[i - 1];
            6: rx <= data[i - 1];
            7: rx <= data[i - 1];
            8: rx <= data[i - 1];
            9: rx <= 1'b1 ;
            default: rx <= 1'b1 ;
        endcase
        #(CYCLE * 52) ;
    end
    endtask

    initial begin
        sys_clk    = 1'b1 ;
        sys_rst_n <= 1'b0 ;
        rx        <= 1'b1 ;
        #( CYCLE * 10 )   ;
        sys_rst_n <= 1'b1 ;
        #( 210 )          ;
        sys_rst_n <= 1'b0 ;
        #( 10 )           ;
        #( CYCLE * 10 )   ;
        sys_rst_n <= 1'b1 ;
        #( CYCLE * 100  ) ;

        rx_bit(8'd1) ;
        rx_bit(8'd1) ;
        rx_bit(8'd1) ;
        rx_bit(8'd1) ;
        rx_bit(8'd1) ;

        rx_bit(8'd2) ;
        rx_bit(8'd2) ;
        rx_bit(8'd2) ;
        rx_bit(8'd2) ;
        rx_bit(8'd2) ;

        rx_bit(8'd3) ;
        rx_bit(8'd3) ;
        rx_bit(8'd3) ;
        rx_bit(8'd3) ;
        rx_bit(8'd3) ;

        rx_bit(8'd4) ;
        rx_bit(8'd4) ;
        rx_bit(8'd4) ;
        rx_bit(8'd4) ;
        rx_bit(8'd4) ;
        
        rx_bit(8'd5) ;
        rx_bit(8'd5) ;
        rx_bit(8'd5) ;
        rx_bit(8'd5) ;
        rx_bit(8'd5) ;
        
        

        
        rx_bit(8'd1) ;
        rx_bit(8'd1) ;
        rx_bit(8'd1) ;
        rx_bit(8'd1) ;
        rx_bit(8'd1) ;

        rx_bit(8'd1) ;
        rx_bit(8'd1) ;
        rx_bit(8'd1) ;
        rx_bit(8'd1) ;
        rx_bit(8'd1) ;

        rx_bit(8'd1) ;
        rx_bit(8'd1) ;
        rx_bit(8'd1) ;
        rx_bit(8'd1) ;
        rx_bit(8'd1) ;

        rx_bit(8'd1) ;
        rx_bit(8'd1) ;
        rx_bit(8'd1) ;
        rx_bit(8'd1) ;
        rx_bit(8'd1) ;

        rx_bit(8'd1) ;
        rx_bit(8'd1) ;
        rx_bit(8'd1) ;
        rx_bit(8'd1) ;
        rx_bit(8'd1) ;
        $stop        ;
    end

    always #( CYCLE / 2 ) sys_clk = ~sys_clk ;

endmodule

 仿真图:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值