module syn_fifo(
input sys_clk,
input rst_n,
input wr_en,
input [7:0] wr_data,
output full,
input rd_en,
output reg [7:0] rd_data,
output empty
);
reg [3:0] wr_addr;
reg [3:0] rd_addr;
reg [3:0] cnt;
parameter max_cnt = 4'd15;
reg [7:0] fifo[max_cnt:0]; //16*8(16是深度,8是位宽)的fifo
assign empty = (cnt==4'd0) ? 1'b1:1'b0;
assign full = (cnt==max_cnt) ? 1'b1:1'b0;
//写数据
integer i;
always @(posedge sys_clk or negedge rst_n) begin
if(!rst_n) begin
for(i=0;i<max_cnt+1'b1;i=i+1)
fifo[i] <= 8'd0;
end
else if(wr_en && (full==1'b0))
fifo[wr_addr] <= wr_data;
else
fifo[wr_addr] <= fifo[wr_addr];
end
//更新写地址
always @(posedge sys_clk or negedge rst_n) begin
if(!rst_n)
wr_addr <= 4'd0;
else if(wr_en && (full==1'b0))
wr_addr <= wr_addr + 1'b1;
else
wr_addr <= wr_addr;
end
//读数据
always @(posedge sys_clk or negedge rst_n) begin
if(!rst_n)
rd_data <= 8'd0;
else if(rd_en && (empty==1'b0))
rd_data <= fifo[rd_addr];
else
rd_data <= rd_data;
end
//更新读地址
always @(posedge sys_clk or negedge rst_n) begin
if(!rst_n)
rd_addr <= 4'd0;
else if(rd_en && (empty==1'b0))
rd_addr <= rd_addr + 1'b1;
else
rd_addr <= rd_addr;
end
//更新计数器
always @(posedge sys_clk or negedge rst_n) begin
if(!rst_n)
cnt <= 4'd0;
else begin
case({wr_en,rd_en})
2'b00: cnt <= cnt;
2'b01: begin
if(cnt != 4'd0)
cnt <= cnt - 1'b1;
else
cnt <= cnt;
end
2'b10: begin
if(cnt != max_cnt)
cnt <= cnt + 1'b1;
else
cnt <= cnt;
end
2'b11: cnt <= cnt;
default: ;
endcase
end
end
endmodule
fifo周周周周
最新推荐文章于 2024-08-19 14:35:57 发布