同步FIFO---Verilog实现
程序员文章站
2022-06-05 13:08:34
...
module fifo_sync#(
parameter data_width = 16,
parameter data_depth = 256,
parameter addr_width = 8
)
(
input clk,
input rst,//active high
input wr_en,
input [data_width-1:0] din,
input rd_en,
output reg valid,
output reg [data_width-1:0] dout,
output empty,
output full
);
reg [addr_width-1:0] wr_addr;// 写地址
reg [addr_width-1:0] rd_addr;// 读地址
reg [addr_width :0] gap_addr;//读写地址距离
reg [data_width-1:0] fifo_ram [data_depth-1:0];
//=========================================================write fifo
genvar i;
generate
for(i = 0; i < data_depth; i = i + 1 )
begin:fifo_init
aaa@qq.com(posedge clk or posedge rst)
begin
if(rst)
fifo_ram[i] <= 'h0;
else if(wr_en && (~full))
fifo_ram[wr_addr] <= din;
else
fifo_ram[wr_addr] <= fifo_ram[wr_addr];
end
end
endgenerate
//========================================================read_fifo
aaa@qq.com(posedge clk or posedge rst)
begin
if(rst)
begin
dout <= 'h0;
valid <= 1'b0;
end
else if(rd_en && (~empty))
begin
dout <= fifo_ram[rd_addr];
valid <= 1'b1;
end
else
begin
dout <= dout;
valid <= 1'b0;
end
end
//=======================================================control addr
aaa@qq.com(posedge clk or posedge rst)
begin
if(rst)
begin
wr_addr <= 'h0;
rd_addr <= 'h0;
gap_addr <= 'h0;
end
else
case({wr_en,rd_en})
2'b00:;
2'b01:
begin
if(~empty)
begin
wr_addr <= wr_addr;
rd_addr <= rd_addr + 1;
gap_addr <= gap_addr -1 ;
end
end
2'b10:
begin
if(~full)
begin
wr_addr <= wr_addr + 1;
rd_addr <= rd_addr ;
gap_addr <= gap_addr + 1 ;
end
end
2'b11:
begin
if(full)
begin
wr_addr <= wr_addr;
rd_addr <= rd_addr + 1'b1;
gap_addr <= gap_addr -1 ;
end
else if(empty)
begin
wr_addr <= wr_addr + 1;
rd_addr <= rd_addr ;
gap_addr <= gap_addr + 1 ;
end
else
begin
wr_addr <= wr_addr + 1;
rd_addr <= rd_addr + 1;
gap_addr <= gap_addr ;
end
end
default:
begin
wr_addr <= 'h0;
rd_addr <= 'h0;
gap_addr <= 'h0;
end
endcase
end
assign empty = (gap_addr == 'h0)?1'b1:1'b0;
assign full = (rst)?1'b1:((gap_addr == (data_depth))?1'b1:1'b0);
endmodule
仿真程序如下:
module tb_fifo_sync(
);
reg rst;
reg clk;
reg [15:0] din;
reg wr_en;
reg rd_en;
wire [15:0] dout;
wire full;
wire empty;
wire valid;
always #5 clk <= ~clk;
initial begin
rst = 1;
clk = 0;
din = 0 ;
wr_en = 0;
rd_en = 0;
#20;
rst = 0;
#100;
//======================================================empty
repeat(10) @(posedge clk)
begin
din = din + 1;
wr_en = 1;
end
repeat(12) @(posedge clk)
begin
din = 0 ;
wr_en = 0;
rd_en = 1;
end
repeat(1) @(posedge clk) rd_en = 0;
//=======================================================full
repeat(260) @(posedge clk)
begin
din = din + 1;
wr_en = 1;
end
repeat(260) @(posedge clk)
begin
din = 0 ;
wr_en = 0;
rd_en = 1;
end
repeat(1) @(posedge clk) rd_en = 0;
end
fifo_sync fifo_sync_inst (
.rst(rst), // input wire rst
.clk(clk), // input wire clk
.din(din), // input wire [15 : 0] din
.wr_en(wr_en), // input wire wr_en
.rd_en(rd_en), // input wire rd_en
.dout(dout), // output wire [15 : 0] dout
.full(full), // output wire full
.empty(empty), // output wire empty
.valid(valid) // output wire valid
);
endmodule
仿真如下:
上一篇: IPC基础概念介绍