题目
用verilog实现一个同步FIFO,深度16,数据位宽8bit
分析
由于同步FIFO的读写两端时钟是同步的,所以不需要异步考虑。同步FIFO中需要设计的部分是读指针,写指针,空满状态,读数据和写数据和ram的数据流通。
代码
modual Syn_fifo
#(
parameter DATA_WIDTH = 8,
parameter ADDR_WIDTH = 4,
parameter RAM_DEPTH = (1 << ADDR_WIDTH)
)
(
input clk,
input rstn,
input [DATA_WIDTH-1:0] din,
input wr_en,
input rd_en,
output reg [DATA_WIDTH-1:0] dout,
output empty,
output full
)
reg [ADDR_WIDTH-1:0] wr_cnt;
reg [ADDR_WIDTH-1:0] rd_cnt;
reg [ADDR_WIDTH-1:0] status_cnt;
reg [DATA_WIDHT-1:0] ram_data;
assign empty = status_cnt == (RAM_DEPTH-1) ? 1'b1 : 1'b0;
assign full = status_cnt == 0 ? 1'b1 : 1'b0;
reg rd_en_dly;
always @(posedge clk)begin //此处为了ram的数据到FIFO输出的一拍延时
if(!rstn)
rd_en_dly <= 0;
else
rd_en_dly <= rd_en;
end
always @(posedge clk)begin
if(!rstn)
wr_cnt <= 0;
else if(wr_cnt==RAM_DEPTH-1)
wr_cnt <= 0;
else if(wr_en)
wr_cnt <= wr_cnt + 1;
end
always @(posedge clk)begin
if(!rstn)
rd_cnt <= 0;
else if(rd_cnt==RAM_DEPTH-1)
rd_cnt <= 0;
else if(rd_en)
rd_cnt <= rd_cnt + 1;
end
always @(posedge clk)begin
if(!rstn)
dout <= 0;
else if(rd_en_dly)
dout <= ram_data;
end
always @(posedge clk)begin
if(!rstn)
status_cnt <= 0;
else if(rd_en && !wr_en && (status_cnt != 0))
status_cnt <= status_cnt - 1;
else if(!rd_en && wr_en && (status_cnt != RAM_DEPTH-1))
status_cnt <= status_cnt + 1;
end
integer i;
reg [DATA_WIDTH-1:0] register [RAM_DEPTH-1:0];
always @(posedge clk)begin
if(!rstn)begin
for(i=0;i<RAM_DEPTH;i=i+1)
register[i] <= 0;
end
else if(wr_en)
register[i] <= din;
end
always @(posedge clk)begin
if(!rstn)
data_ram <= 0;
else if(rd_en)
data_ram <= register[rd_cnt];
end
endmodule