二、双fifo流水线操作——verilog练习与设计

发布于:2024-05-08 ⋅ 阅读:(19) ⋅ 点赞:(0)

一、案例分析

案例要求:写一个 fifo 控制器,输入的数据是 86 行 86 列的矩阵(每个数据8bit),数据由串口传输过来,传过来的数据先一行一行用 fifo 缓存,然后每三行的同一列进行一次加,即第 0,1,2行,第 1,2,3 行……第 84,85,86 行,每三行作为一组,每一组的每一列的三个数据进行一次加运算。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

框架示意图:
这里的uart_rx模块和uart_tx模块直接使用rs232中设计好的。
在这里插入图片描述

二、fifo_ctrl模块设计

2.1 波形设计:

在这里插入图片描述

2.2 代码实现

2.2.1 fifo_ctrl

module fifo_ctrl(
    input wire clk,
    input wire rst,
    input wire [7:0] rx_data,
    input wire pi_flag,
    output reg [7:0] po_sum,
    output reg po_flag
    );

reg[9:0] cnt_col,cnt_row;
reg wr_en1_r,wr_en2_r;
wire wr_en1,wr_en2;

reg [7:0] data_in1_r;
wire [7:0] data_in1;
wire [7:0] dout1,dout2;


reg rd_en_r;
wire rd_en;

reg flag_add;



parameter COL_MUX=85;
parameter ROW_MUX=85;

// cnt_col
always @(posedge clk) begin 
    if(rst==1'b1) begin
        cnt_col <= 'd0;
    end 
    else if (pi_flag==1'b1 && cnt_col==COL_MUX) begin
         cnt_col<='d0;
    end
    else if (pi_flag==1'b1) begin
         cnt_col<=cnt_col+1'b1;
    end
end

// cnt_row
always @(posedge clk) begin 
    if(rst==1'b1) begin
        cnt_row <= 'd0;
    end
    else if (cnt_row==ROW_MUX && pi_flag==1'b1 && cnt_col==COL_MUX) begin
        cnt_row<='d0;
    end
    else if (pi_flag==1'b1 && cnt_col==COL_MUX) begin
       cnt_row<=cnt_row+1'b1;
    end
end

// wr_en1_r
assign wr_en1=wr_en1_r;
always @(posedge clk) begin 
    if(rst==1'b1) begin
        wr_en1_r <= 'd0;
    end
    else if (cnt_row=='d0) begin
        wr_en1_r<=pi_flag;
    end
    else if (cnt_row>'d1 && cnt_row<ROW_MUX) begin
        wr_en1_r<=flag_add;
    end
end

// wr_en2_r
assign wr_en2=wr_en2_r;
always @(posedge clk) begin 
    if(rst==1'b1) begin
        wr_en2_r <= 'd0;
    end 
    else if (cnt_row>'d0 && cnt_row<ROW_MUX) begin
        wr_en2_r<=pi_flag;
    end
    else
        wr_en2_r<='d0;
end

// data_in1_r
assign data_in1=data_in1_r;
always @(posedge clk) begin 
    if(rst==1'b1) begin
         data_in1_r<= 'd0;
    end 
    else if (cnt_row=='d0) begin
        data_in1_r<=rx_data;
    end
    else if (cnt_row>'d1 && cnt_row<ROW_MUX) begin
       data_in1_r<=dout2;
    end
end

// rd_en_r
assign rd_en=rd_en_r;

always @(posedge clk) begin 
    if(rst==1'b1) begin
         rd_en_r<= 'd0;
    end 
    else if (cnt_row>'d1) begin
        rd_en_r<=pi_flag;
    end
    else 
        rd_en_r<='d0;
end

// flag_add
always @(posedge clk) begin 
    if(rst==1'b1) begin
        flag_add <= 'd0;
    end 
    else
        flag_add<=rd_en_r;
end

// po_sum
always @(posedge clk) begin 
    if(rst==1'b1) begin
        po_sum <= 'd0;
    end 
    else if (flag_add==1'b1) begin
        po_sum<=rx_data+dout1+dout2;
    end
end

// po_flag
always @(posedge clk) begin 
    if(rst==1'b1) begin
        po_flag <= 'd0;
    end 
    else
        po_flag<=flag_add;
end

fifo_8x128 fifo1_8x128 (
  .clk(clk),      // input wire 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(dout1),    // output wire [7 : 0] dout
  .full(),    // output wire full
  .empty()  // output wire empty
);

fifo_8x128 fifo2_8x128 (
  .clk(clk),      // input wire clk
  .din(rx_data),      // input wire [7 : 0] din
  .wr_en(wr_en2),  // input wire wr_en
  .rd_en(rd_en),  // input wire rd_en_r
  .dout(dout2),    // output wire [7 : 0] dout
  .full(),    // output wire full
  .empty()  // output wire empty
);
endmodule

2.2.2 顶层文件top_fifo_ctrl(rx和tx模块省略)

module top_fifo_ctrl(
	input	wire 		clk,
	input	wire 		rst,
	input	wire 		rx,
	output	wire 		tx
    );

wire [7:0] rx_data;
wire pi_flag;
wire [7:0] po_sum;
wire po_flag;

	uart_rx  inst_uart_rx (
			.clk     (clk),
			.rst     (rst),
			.rx      (rx),
			.po_data (rx_data),
			.po_flag (pi_flag)
		);
	uart_tx inst_uart_tx (
			.clk     (clk),
			.rst     (rst),
			.po_data (po_sum),
			.po_flag (po_flag),
			.tx      (tx)
		);
	fifo_ctrl inst_fifo_ctrl (
			.clk     (clk),
			.rst     (rst),
			.rx_data (rx_data),
			.pi_flag (pi_flag),
			.po_sum  (po_sum),
			.po_flag (po_flag)
		);


endmodule

2.2.3 仿真文件tb_fifo_ctrl

module tb_fifo_ctrl();
	reg clk;
	reg rst;
	reg rx;
	wire tx;

	reg[7:0]  mem[85:0];  //定义一个mem,可以存储168bit的数据

	top_fifo_ctrl inst_top_fifo_ctrl (
		.clk(clk), 
		.rst(rst),
		.rx(rx),
		.tx(tx));



	initial begin
		clk=0;
		rst=1;
		rx=1;
		#100;
		rst=0;
	end

	always #10 clk=~clk;

		//从文件加载数据
	initial begin
		$readmemb("./test.txt",mem);
	end

	initial begin
		#200;
		rx_byte();
	end



task rx_byte;
		integer i;
		integer j;
		begin
			for(j=0;j<86;j=j+1)begin
				for (i=0;i<86;i=i+1)begin
					rx_bit(mem[i]);
				end
			end
		end
	endtask  

    task 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[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;
    			endcase 
    			#104160; //9600bps时
    			// #2000; 仿真时
    		end
    		
    	end

    endtask  
endmodule

2.3波形仿真

在这里插入图片描述
仿真中可以看到:flag_add之后会立刻输出po_sum,且po_sum=dout1+dout2+rx_data,设计无误。