同步fifo的实现:
// 同步fifo的实现
module sy_fifo(
input wire clk,
input wire rst_n,
input wire wr_en, // 写信号
input wire[7:0] data_in, // 输入
input wire rd_en, // 读信号
output wire full, // 写满
output reg [7:0] data_out, // 输出
output wire empty // 空
);
localparam deepth = 256; // 深度 2^8 = 256, 二进制计数需要8bit
localparam width = 8; // 宽度
reg [width-1:0] mem [deepth-1:0]; // 一个名为mem的存储器,该存储器有deepth个width位的寄存器
reg [8:0] count; // 二进制计数需要8bit
reg [7:0] rd_addr; // 读计数
reg [7:0] wr_addr; // 写计数
wire wr; // 可写
wire rd; // 可读
assign wr = (wr_en) && (~full); // 不满且写信号,可写
assign rd = (rd_en) && (~empty); // 不空且读信号,可读
//wr_addr ctrl 写信号下 写计数
always @(posedge clk or negedge rst_n) begin
if(!rst_n)
wr_addr <= 8'd0;
else if(wr)
wr_addr <= wr_addr + 1'b1;
else
wr_addr <= wr_addr;
end
//wr_data; 写信号下 写进fifo
always @(posedge clk) begin
if(wr)
mem[wr_addr] <= data_in; // 计数作为地址,输入写入men
else
mem[wr_addr] <= mem[wr_addr]; // 某地址下存储器数据不变
end
//rd_addr ctrl // 读信号下 读计数
always @(posedge clk or negedge rst_n) begin
if(!rst_n)
rd_addr <= 8'd0;
else if(rd)
rd_addr <= rd_addr +1'b1;
else
rd_addr <= rd_addr;
end
// rd data; // 读信号下 读出数据
always @(posedge clk or negedge rst_n) begin
if(!rst_n)
data_out <= 8'd0;
else if(rd)
data_out <= mem[rd_addr]; // 读信号,读计数作为地址,依次读出
else
data_out <= data_out; // 没有读信号,维持数据输出,不继续读出
end
// count 满计数
always @(posedge clk or negedge rst_n) begin
if(!rst_n)
count <= 8'd0;
else if(rd && ~wr && (count >=1)) // 读信号且没写信号,满计数-1
count <= count - 1'd1;
else if(wr && ~rd &&(count <=255)) // 写信号没读信号,满计数+1
count <= count + 1'd1;
else
count <= count; // 同时读写时,满计数不变
end
//full empty 空满状态判断
assign empty = (count == 8'd0) ? 1'b1:1'b0; // 满计数=0 空
assign full = (count == 9'd256) ? 1'b1:1'b0; // 满计数=256 满
endmodule
//-------------------------------------------
// -----------testbench----------------
`timescale 1ns/1ps
`define clock_period 20
module sy_fifo_tb;
reg clk;
reg rst_n;
reg wr_en;
reg rd_en;
reg [7:0] data_in;
wire [7:0] data_out;
wire full;
wire empty;
initial clk = 1'b1;
always #(`clock_period/2) clk = ~clk;
integer i;
initial begin
wr_en = 0; data_in =0; rst_n = 0; rd_en =0;
#100;
rst_n =1;
#100;
for (i =0; i<256; i=i+1)begin
@(posedge clk)
data_in = {$random}%256; // 随机数 -256~256
wr_en = 1'b1;
if(i==128) // 写到一半内存,开始读
rd_en =1;
end
#30;
wr_en =0;
end
// 例化
sy_fifo sy_fifo_inst(
.clk(clk),
.rst_n(rst_n),
.wr_en(wr_en),
.data_in(data_in),
.rd_en(rd_en),
.full(full),
.data_out(data_out),
.empty(empty)
);
endmodule
i=128,下个clk,rd拉高,下个clk,开始读出。写入并读出时,满信号count不变。
count = 256 满状态,不再写入