用Verilog实现一个同步FIFO,深度16,数据位宽8bit
module Sy_FIFO#(
parameter DATA_WIDTH = 8,
parameter ADDR_WIDTH = 4,
parameter RAM_DEPTH = (1 << ADDR_WIDTH)
)
(
input clk,
input rst_n,
input [DATA_WIDTH-1:0] data_in,
input wr_en,
input rd_en,
output reg [DATA_WIDTH-1:0] data_out,
output empty,
output full
);
wire [ADDR_WIDTH-1:0] wr_cnt;
wire [ADDR_WIDTH-1:0] rd_cnt;
reg [ADDR_WIDTH-1:0] status_cnt;
reg [DATA_WIDTH-1:0] data_ram;
reg rd_en_r;
always @(posedge clk or negedge rst_n) begin
if(!rst_n)
rd_en_r <= 0;
else
rd_en_r <= rd_en;
end
reg [ADDR_WIDTH:0] wr_cnt_next;
reg [ADDR_WIDTH:0] rd_cnt_next;
always @(posedge clk or negedge rst_n) begin
if(!rst_n)
wr_cnt_next <= 0;
else begin
if(wr_en && (full == 0))
wr_cnt_next <= wr_cnt_next + 1'b1;
else
wr_cnt_next <= wr_cnt_next;
end
end
always @(posedge clk or negedge rst_n) begin
if(!rst_n)
rd_cnt_next <= 0;
else begin
if(rd_en && (empty == 0))
rd_cnt_next <= rd_cnt_next + 1'b1;
else
rd_cnt_next <= rd_cnt_next;
end
end
always @(posedge clk or negedge rst_n) begin
if(!rst_n)
data_out <= 0;
else begin
if(rd_en_r)
data_out <= data_ram;
end
end
assign full = (rd_cnt_next == ({~wr_cnt_next[ADDR_WIDTH],wr_cnt_next[ADDR_WIDTH-1:0]}))?1'b1:1'b0;
assign empty = (rd_cnt_next == wr_cnt_next)?1'b1:1'b0;
assign wr_cnt = wr_cnt_next[ADDR_WIDTH-1:0];
assign rd_cnt = rd_cnt_next[ADDR_WIDTH-1:0];
integer i;
reg [DATA_WIDTH-1:0] register[RAM_DEPTH-1:0];
always @(posedge clk or negedge rst_n) begin
if(!rst_n)
for(i=0;i<RAM_DEPTH;i=i+1)
register[i] <= 8'd15;
else begin
if(wr_en && (full == 0))
register[wr_cnt] <= data_in;
end
end
always @(posedge clk or negedge rst_n) begin
if(!rst_n)
data_ram <= 8'bz;
else begin
if(rd_en && (empty == 0))
data_ram <= register[rd_cnt];
else
data_ram <= 8'bz;
end
end
endmodule
测试代码
`timescale 1ns / 1ps
module tb_SyFiFo;
reg clk;
reg rst_n;
reg [7:0] data_in;
reg wr_en;
reg rd_en;
wire [7:0] data_out;
wire empty;
wire full;
reg ena;
reg enb;
Sy_FIFO uut (
.clk(clk),
.rst_n(rst_n),
.data_in(data_in),
.wr_en(wr_en),
.rd_en(rd_en),
.data_out(data_out),
.empty(empty),
.full(full)
);
always #5 clk = ~clk;
initial begin
clk = 0;
rst_n = 0;
data_in = 0;
wr_en = 0;
rd_en = 0;
enb = 0;
ena = 0;
#100 rst_n = 1;
#95 wr_en = 1;
ena = 1;
#400 ena = 0;
wr_en = 0;
#200 enb = 1;
#10 rd_en = 1;
#400 enb = 0;
#10 rd_en = 0;
#95 wr_en = 1;
ena = 1;
#400 ena = 0;
wr_en = 0;
#200 enb = 1;
#10 rd_en = 1;
#400 enb = 0;
#10 rd_en = 0;
end
always @(posedge clk )begin
if(!rst_n)
data_in <= 8'd2;
else
if(ena)
data_in <= data_in + 2'd2;
else
data_in <= data_in;
end
endmodule
![在这里插入图片描述](https://img-blog.csdnimg.cn/20210627125120546.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2xpdHRsZV9veA==,size_16,color_FFFFFF,t_70)