文章目录
- 一、案例分析
- 二、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) 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,可以存储16个8bit的数据
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,设计无误。