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 中国大陆许可协议进行许可。
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步