文章目录
- 一、案例分析
- 二、fifo_ctrl模块设计
- 2.1 波形设计:
- 2.2 代码实现
- 2.2.1 fifo_ctrl
- 2.2.2 顶层文件top_fifo_ctrl(rx和tx模块省略)
- 2.2.3 仿真文件tb_fifo_ctrl
- 2.3波形仿真
一、案例分析
案例要求:写一个 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) begincnt_col <= 'd0;end else if (pi_flag==1'b1 && cnt_col==COL_MUX) begincnt_col<='d0;endelse if (pi_flag==1'b1) begincnt_col<=cnt_col+1'b1;end
end// cnt_row
always @(posedge clk) begin if(rst==1'b1) begincnt_row <= 'd0;endelse if (cnt_row==ROW_MUX && pi_flag==1'b1 && cnt_col==COL_MUX) begincnt_row<='d0;endelse if (pi_flag==1'b1 && cnt_col==COL_MUX) begincnt_row<=cnt_row+1'b1;end
end// wr_en1_r
assign wr_en1=wr_en1_r;
always @(posedge clk) begin if(rst==1'b1) beginwr_en1_r <= 'd0;endelse if (cnt_row=='d0) beginwr_en1_r<=pi_flag;endelse if (cnt_row>'d1 && cnt_row<ROW_MUX) beginwr_en1_r<=flag_add;end
end// wr_en2_r
assign wr_en2=wr_en2_r;
always @(posedge clk) begin if(rst==1'b1) beginwr_en2_r <= 'd0;end else if (cnt_row>'d0 && cnt_row<ROW_MUX) beginwr_en2_r<=pi_flag;endelsewr_en2_r<='d0;
end// data_in1_r
assign data_in1=data_in1_r;
always @(posedge clk) begin if(rst==1'b1) begindata_in1_r<= 'd0;end else if (cnt_row=='d0) begindata_in1_r<=rx_data;endelse if (cnt_row>'d1 && cnt_row<ROW_MUX) begindata_in1_r<=dout2;end
end// rd_en_r
assign rd_en=rd_en_r;always @(posedge clk) begin if(rst==1'b1) beginrd_en_r<= 'd0;end else if (cnt_row>'d1) beginrd_en_r<=pi_flag;endelse rd_en_r<='d0;
end// flag_add
always @(posedge clk) begin if(rst==1'b1) beginflag_add <= 'd0;end elseflag_add<=rd_en_r;
end// po_sum
always @(posedge clk) begin if(rst==1'b1) beginpo_sum <= 'd0;end else if (flag_add==1'b1) beginpo_sum<=rx_data+dout1+dout2;end
end// po_flag
always @(posedge clk) begin if(rst==1'b1) beginpo_flag <= 'd0;end elsepo_flag<=flag_add;
endfifo_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,可以存储16个8bit的数据top_fifo_ctrl inst_top_fifo_ctrl (.clk(clk), .rst(rst),.rx(rx),.tx(tx));initial beginclk=0;rst=1;rx=1;#100;rst=0;endalways #10 clk=~clk;//从文件加载数据initial begin$readmemb("./test.txt",mem);endinitial begin#200;rx_byte();endtask rx_byte;integer i;integer j;beginfor(j=0;j<86;j=j+1)beginfor (i=0;i<86;i=i+1)beginrx_bit(mem[i]);endendendendtask task rx_bit(input [7:0] data);integer i;beginfor(i=0;i<10;i=i+1) begincase (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; 仿真时endendendtask
endmodule
2.3波形仿真
仿真中可以看到:flag_add之后会立刻输出po_sum,且po_sum=dout1+dout2+rx_data,设计无误。