以一个16x8bit的FIFO为例。
module sync_fifo(
input clk,
input rst_n,
input wr_en,
input[7:0] wr_data,
input rd_en,
output reg[7:0] rd_data,
output full,
output empty
);
reg[3:0] wr_addr, rd_addr;
reg[7:0] ram[0:15];
reg full_reg, empty_reg;
reg[4:0] cnt;
//---------------------- 读写操作 --------------------------
always@(posedge clk)begin
if(wr_en == 1'b1)
ram[wr_addr] <= wr_data;
end
always@(posedge clk)begin
if(rd_en == 1'b1)
rd_data <= ram[rd_addr];
end
//--------------------读写RAM地址计数器---------------------
always@(posedge clk)begin
if(rst_n == 1'b0)
wr_addr <= 4'b0000;
else if(wr_en == 1'b1 && full_reg == 1'b0)
wr_addr <= wr_addr + 1'b1;
end
always@(posedge clk)begin
if(rst_n == 1'b0)
rd_addr <= 4'b0000;
else if(rd_en == 1'b1 && empty_reg == 1'b0)
rd_addr <= rd_addr + 1'b1;
end
//----------------------full和empty标志-----------------------------
always@(posedge clk)begin
if(rst_n == 1'b0)
cnt <= 5'b0000;
else begin
case({wr_en,rd_en})
2'b01:
if(cnt != 5'b00000)
cnt <= cnt - 1'b1;
2'b10:
if(cnt != 5'b10000)
cnt <= cnt + 1'b1;
default:
cnt <= cnt;
endcase
end
end
always@(cnt)begin
if(rst_n == 1'b0)
full_reg <= 1'b0;
else if(cnt == 5'b10000)
full_reg <= 1'b1;
else
full_reg <= 1'b0;
end
always@(cnt)begin
if(rst_n == 1'b0)
empty_reg <= 1'b1;
else if(cnt == 5'b00000)
empty_reg <= 1'b1;
else
empty_reg <= 1'b0;
end
assign full = full_reg;
assign empty = empty_reg;
endmodule
testbench编写:
`timescale 1ns/1ns
`define clock_period 10
module tb_sync_fifo;
reg clk;
reg rst_n;
reg rd_en,wr_en;
wire full,empty;
reg[7:0] wr_data;
wire rd_data;
integer i;
sync_fifo inst1(
.clk(clk),
.rst_n(rst_n),
.wr_en(wr_en),
.wr_data(wr_data),
.rd_en(rd_en),
.rd_data(rd_data),
.full(full),
.empty(empty)
);
initial clk = 1'b0;
always #(`clock_period/2) clk = ~clk;
initial begin
rst_n = 1'b0;
wr_en = 0;
rd_en = 0;
wr_data = 8'h00;
#(`clock_period*10+1);
rst_n = 1'b1;
#(`clock_period*10);
wr_fifo(4'b0000,8'b01100101);
#(`clock_period*10);
rd_fifo;
$stop;
end
task wr_fifo;
input[3:0] addr;
input[7:0] data;
begin
for(i = 0; i < 16; i = i + 1)begin
wr_en = 1;
wr_data = data;
#(`clock_period);
end
wr_en = 0;
end
endtask
task rd_fifo;
begin
for(i = 0; i < 16; i = i + 1)begin
rd_en = 1;
#(`clock_period);
end
rd_en = 0;
end
endtask
endmodule