verilog实现FIFO(2)

高位扩展法

module sync_fifo_ptr #(
parameter DEPTH = 16,
parameter WIDTH = 8
)(
input wire clk,
input wire rst_n,
input wire i_wen,
input wire [WIDTH-1:0] i_wdata,
input wire i_ren,
output reg [WIDTH-1:0] o_rdata,
output wire o_empty,
output wire o_full
);
reg [$clog2(DEPTH):0] w_addr;
reg [$clog2(DEPTH):0] r_addr;
wire [$clog2(DEPTH)-1:0] w_addr_true;
wire [$clog2(DEPTH)-1:0] r_addr_true;
wire w_addr_ptr;
wire r_addr_ptr;
assign {w_addr_ptr,w_addr_true} = w_addr;
assign {r_addr_ptr,r_addr_true} = r_addr;
reg [WIDTH-1:0] fifo_buffer[DEPTH-1:0]; //鐢ㄤ簩缁存暟缁勫疄鐜癛AM
//counter
//write
always @(posedge clk or negedge rst_n)
begin
if(rst_n == 1'b0)
begin
w_addr <= 'd0;
end
else if(i_wen && !o_full)
begin
w_addr <= w_addr + 1'b1;
fifo_buffer[w_addr_true] <= i_wdata;
end
end
//read
always @(posedge clk or negedge rst_n)
begin
if(rst_n == 1'b0)
begin
r_addr <= 'd0;
end
else if(i_ren && !o_empty)
begin
o_rdata <= fifo_buffer[r_addr_true];
r_addr <= r_addr+1'b1;
end
end
assign o_empty = (w_addr == r_addr)?1'b1:1'b0;
assign o_full = ((w_addr_true == r_addr_true) && (w_addr_ptr != r_addr_ptr))?1'b1:1'b0;
endmodule

测试

`timescale 1ns/1ns //时间单位/精度
//------------<模块及端口声明>----------------------------------------
module tb_sync_fifo_ptr();
parameter WIDTH = 8 ; //FIFO位宽
parameter DEPTH = 16 ; //FIFO深度
reg clk ;
reg rst_n ;
reg [WIDTH-1:0] data_in ;
reg rd_en ;
reg wr_en ;
wire [WIDTH-1:0] data_out;
wire empty ;
wire full ;
//------------<例化被测试模块>----------------------------------------
sync_fifo_ptr
#(
.WIDTH (WIDTH), //FIFO位宽
.DEPTH (DEPTH) //FIFO深度
)
sync_fifo_ptr_inst(
.clk (clk ),
.rst_n (rst_n ),
.i_wdata (data_in ),
.i_ren (rd_en ),
.i_wen (wr_en ),
.o_rdata (data_out ),
.o_empty (empty ),
.o_full (full )
);
//------------<设置初始测试条件>----------------------------------------
initial begin
clk = 1'b0; //初始时钟为0
rst_n <= 1'b0; //初始复位
data_in <= 'd0;
wr_en <= 1'b0;
rd_en <= 1'b0;
//重复8次写操作,让FIFO写满
repeat(8) begin
@(negedge clk)begin
rst_n <= 1'b1;
wr_en <= 1'b1;
data_in <= $random; //生成8位随机数
end
end
//重复8次读操作,让FIFO读空
repeat(8) begin
@(negedge clk)begin
wr_en <= 1'b0;
rd_en <= 1'd1;
end
end
//重复4次写操作,写入4个随机数据
repeat(4) begin
@(negedge clk)begin
wr_en <= 1'b1;
data_in <= $random; //生成8位随机数
rd_en <= 1'b0;
end
end
//持续同时对FIFO读写,写入数据为随机数据
forever begin
@(negedge clk)begin
wr_en <= 1'b1;
data_in <= $random; //生成8位随机数
rd_en <= 1'b1;
end
end
end
//------------<设置时钟>----------------------------------------------
always #10 clk = ~clk; //系统时钟周期20ns
endmodule

本文作者:大耳毛豆

本文链接:https://www.cnblogs.com/yjxmike/p/18729196

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   大耳毛豆  阅读(9)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起