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

一、案例分析

案例要求:写一个 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,设计无误。

  • 7
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
异步FIFO是一种常见的数字电路设计,用来实现数据在不同时钟域之间的传输。Verilog是一种硬件描述语言,用于设计和模拟数字逻辑电路。下面是一个异步FIFOVerilog源码和相应的测试台代码的示例: Verilog异步FIFO源码: ```verilog module AsyncFIFO ( input wire clk_wr, input wire reset, input wire enable, input wire data_in, output wire full, output wire empty, output reg data_out ); parameter WIDTH = 8; // 数据位宽 parameter DEPTH = 16; // FIFO深度 reg [WIDTH-1:0] memory[0:DEPTH-1]; reg [WIDTH-1:0] read_pointer, write_pointer; always @(posedge clk_wr or posedge reset) begin if (reset) begin read_pointer <= 0; write_pointer <= 0; data_out <= 0; end else if (enable) begin if (~full) begin memory[write_pointer] <= data_in; write_pointer <= write_pointer + 1; end if (~empty) begin data_out <= memory[read_pointer]; read_pointer <= read_pointer + 1; end end end assign full = (write_pointer - read_pointer) == DEPTH; assign empty = (write_pointer == read_pointer); endmodule ``` Verilog异步FIFO测试台代码: ```verilog module AsyncFIFOTest; reg clk_wr; reg reset; reg enable; reg data_in; wire full; wire empty; wire data_out; AsyncFIFO dut ( .clk_wr(clk_wr), .reset(reset), .enable(enable), .data_in(data_in), .full(full), .empty(empty), .data_out(data_out) ); initial begin clk_wr = 0; reset = 1; enable = 0; data_in = 0; #2 reset = 0; // 写入测试数据 #2 enable = 1; #2 data_in = 1; #2; #2 data_in = 2; #2; #2 data_in = 3; #2 enable = 0; // 读取测试数据 #2 enable = 1; #2 enable = 0; // 检查输出数据 $display("data_out: %d", data_out); #2; $display("empty: %b", empty); $finish; end always begin #1 clk_wr = ~clk_wr; end endmodule ``` 以上是一个简单的8位宽、16深度的异步FIFO模块和相应的测试台代码。测试台首先初始化FIFO,然后写入数据1、2、3,最后读取数据并检查输出数据和空状态。 这是一个只包含基本功能的示例,实际应用中可能还需要添加写入满和读取空的异常处理等功能。同时,测试台代码也可以根据具体需求进行修改和扩展以进行更全面的测试。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值