Merge dev to main. #1
|
@ -14,7 +14,8 @@ module fifo_sync #(
|
||||||
output wire [DATA_WIDTH-1:0] dout,
|
output wire [DATA_WIDTH-1:0] dout,
|
||||||
output wire empty,
|
output wire empty,
|
||||||
output wire full,
|
output wire full,
|
||||||
output wire [$clog2(DEPTH):0] data_count
|
output wire [$clog2(DEPTH):0] fill_level,
|
||||||
|
output reg err
|
||||||
);
|
);
|
||||||
|
|
||||||
localparam ADDR_WIDTH = $clog2(DEPTH);
|
localparam ADDR_WIDTH = $clog2(DEPTH);
|
||||||
|
@ -37,15 +38,23 @@ module fifo_sync #(
|
||||||
always @(posedge clk or negedge rst_n) begin
|
always @(posedge clk or negedge rst_n) begin
|
||||||
if (!rst_n) begin
|
if (!rst_n) begin
|
||||||
rd_ptr <= 0;
|
rd_ptr <= 0;
|
||||||
end else if (rd_en && !empty) begin
|
err <= 1'b0;
|
||||||
rd_ptr <= rd_ptr + 1'b1;
|
end else begin
|
||||||
|
if (rd_en && empty) begin
|
||||||
|
err <= 1'b1;
|
||||||
|
end else begin
|
||||||
|
err <= 1'b0;
|
||||||
|
end
|
||||||
|
if (rd_en && !empty) begin
|
||||||
|
rd_ptr <= rd_ptr + 1'b1;
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
// 数据计数
|
// 数据计数
|
||||||
assign data_count = wr_ptr - rd_ptr;
|
assign fill_level = wr_ptr - rd_ptr;
|
||||||
assign empty = (wr_ptr == rd_ptr);
|
assign empty = (wr_ptr == rd_ptr);
|
||||||
assign full = (data_count == DEPTH);
|
assign full = (fill_level == DEPTH);
|
||||||
|
|
||||||
generate
|
generate
|
||||||
if (USE_RAM) begin : USE_RAM_BLOCK
|
if (USE_RAM) begin : USE_RAM_BLOCK
|
||||||
|
|
|
@ -15,7 +15,8 @@ module fifo_sync_tb;
|
||||||
wire [DATA_WIDTH-1:0] dout;
|
wire [DATA_WIDTH-1:0] dout;
|
||||||
wire empty;
|
wire empty;
|
||||||
wire full;
|
wire full;
|
||||||
wire [$clog2(DEPTH):0] data_count;
|
wire [$clog2(DEPTH):0] fill_level;
|
||||||
|
wire err;
|
||||||
|
|
||||||
// 实例化DUT
|
// 实例化DUT
|
||||||
fifo_sync #(
|
fifo_sync #(
|
||||||
|
@ -32,7 +33,8 @@ module fifo_sync_tb;
|
||||||
.dout(dout),
|
.dout(dout),
|
||||||
.empty(empty),
|
.empty(empty),
|
||||||
.full(full),
|
.full(full),
|
||||||
.data_count(data_count)
|
.fill_level(fill_level),
|
||||||
|
.err(err)
|
||||||
);
|
);
|
||||||
|
|
||||||
// 时钟生成
|
// 时钟生成
|
||||||
|
@ -81,6 +83,14 @@ module fifo_sync_tb;
|
||||||
if (!empty) $display("[TB][ERROR] FIFO未空!");
|
if (!empty) $display("[TB][ERROR] FIFO未空!");
|
||||||
else $display("[TB][INFO] FIFO已空!");
|
else $display("[TB][INFO] FIFO已空!");
|
||||||
|
|
||||||
|
// 尝试在empty时读,触发err
|
||||||
|
@(negedge clk);
|
||||||
|
rd_en = 1;
|
||||||
|
@(negedge clk);
|
||||||
|
rd_en = 0;
|
||||||
|
if (err) $display("[TB][INFO] 读空FIFO触发err信号");
|
||||||
|
else $display("[TB][ERROR] 读空FIFO未触发err!");
|
||||||
|
|
||||||
// 交错写读
|
// 交错写读
|
||||||
for (int i = 0; i < 8; i++) begin
|
for (int i = 0; i < 8; i++) begin
|
||||||
@(negedge clk);
|
@(negedge clk);
|
||||||
|
@ -100,9 +110,11 @@ module fifo_sync_tb;
|
||||||
// 监控输出
|
// 监控输出
|
||||||
always @(posedge clk) begin
|
always @(posedge clk) begin
|
||||||
if (wr_en && !full)
|
if (wr_en && !full)
|
||||||
$display("[TB][WRITE] @%0t: din=%0d, wr_ptr=%0d", $time, din, dut.wr_ptr);
|
$display("[TB][WRITE] @%0t: din=%0d, wr_ptr=%0d, fill_level=%0d", $time, din, dut.wr_ptr, fill_level);
|
||||||
if (rd_en && !empty)
|
if (rd_en && !empty)
|
||||||
$display("[TB][READ ] @%0t: dout=%0d, rd_ptr=%0d", $time, dout, dut.rd_ptr);
|
$display("[TB][READ ] @%0t: dout=%0d, rd_ptr=%0d, fill_level=%0d", $time, dout, dut.rd_ptr, fill_level);
|
||||||
|
if (err)
|
||||||
|
$display("[TB][ERR ] @%0t: 读空FIFO!", $time);
|
||||||
end
|
end
|
||||||
|
|
||||||
endmodule
|
endmodule
|
||||||
|
|
Loading…
Reference in New Issue