欢迎来到亿配芯城! | 免费注册
你的位置:EEPROM带电可擦可编程IC存储器芯片大全-亿配芯城 > 芯片资讯 > 一种简单的、真实的基于循环序列的FIFO缓存设计
一种简单的、真实的基于循环序列的FIFO缓存设计
发布日期:2024-01-05 06:49     点击次数:106

内容

FIFO缓存是介于两个子系统之间的弹性存储器,其概念图如图1所示。它有两个控制信号,wr和rd,用于读操作和写操作。当wr被插入时,输入的数据被写入缓存,此时读操作被忽视。FIFO缓存的head一般情况下总是有效的,因此可在任意时间被读取。rd信号实际上就像“remove”信号;当其被插入的时候,FIFO缓存的第一个项(即head)被移除,下一个项变为可用项。

 f330f0a0-5037-11ee-a25d-92fbcf53809c.png

图1 FIFO缓存的概念框图

在许多应用中,FIFO缓存是一种临界组件,其实现的优化相当复杂。在本节中,我们介绍一种简单的、真实的基于循环序列设计的FIFO缓存。更有效的、基于指定器件实现的FIFO缓存可在Altera或Xilinx的相关手册中找到。

基于循环队列的实现

一种实现FIFO缓存的方法是给寄存器文件添加一个控制电路。寄存器文件通过两个指针像循环队列一样来排列寄存器。写指针(write poniter)指向队列的头(head);读指针(read poniter)指向队列的尾(tail)。每次读操作或写操作,指针都会前进一个位置。8-字循环队列的操作如图2所示。

f34c8a0e-5037-11ee-a25d-92fbcf53809c.jpg

图2 基于循环队列的FIFO缓存

FIFO缓存通常包括两个标志信号,full和empty,EEPROM带电可擦可编程存储器芯片大全相应地来指示FIFO满(即不可写)或FIFO空(即不可读)。这两种情况发生在读指针和写指针相等的时候,如图2(a)、(f)和(i)所示的情况。控制器最难的设计任务是获取一种分辨这两种情形的机制。一种方案是使用触发器来跟踪empty和full标志。当系统被初始化时,触发器被设置为1和0;然后在每一个时钟周期根据wr和rd的值来修改。

代码 FIFO缓存

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 module fifo #(   parameter B=8, // number of bits in a word             W=3  // number of address bits ) (   // global clock and aysn reset   input clk,   input rst_n, EEPROM带电可擦可编程存储器芯片大全   // fifo interface   //  fifo control signnal   input rd, ATMEGA系列ATMEL芯片COM   input wr, 电子元器件PDF资料大全   //  fifo status signal   output empty, CMOS图像传感器集成电路芯片   output full,芯片交易网IC交易网   // fifo data bus   input [B-1:0] w_data,   output [B-1:0] r_data ); // signal declaration reg [B-1:0] array_reg [2**W-1:0];  // register array reg [W-1:0] w_ptr_reg, w_ptr_next, w_ptr_succ; reg [W-1:0] r_ptr_reg, r_ptr_next, r_ptr_succ; reg full_reg, empty_reg, full_next, empty_next; wire wr_en; // body // register file write operation always @(posedge clk)   if (wr_en)     array_reg[w_ptr_reg] // register file read operation assign r_data = array_reg[r_ptr_reg]; // write enabled only when FIFO is not full assign wr_en = wr & ~full_reg; // fifo control logic // register for read and write pointers always @(posedge clk, negedge rst_n)   if (!rst_n)   begin     w_ptr_reg     r_ptr_reg     full_reg     empty_reg   end   else   begin     w_ptr_reg     r_ptr_reg     full_reg     empty_reg   end // next-state logic for read and write pointers always @* begin   // successive pointer values   w_ptr_succ = w_ptr_reg + 1;   r_ptr_succ = r_ptr_reg + 1;   // default: keep old values   w_ptr_next = w_ptr_reg;   r_ptr_next = r_ptr_reg;   full_next = full_reg;   empty_next = empty_reg;   case ({wr, rd})     // 2'b00:  no op     2'b01: // read       if (~empty_reg) // not empty       begin         r_ptr_next = r_ptr_succ;         full_next = 1'b0;         if (r_ptr_succ==w_ptr_reg)           empty_next = 1'b1;       end     2'b10: // write     if (~full_reg) // not full     begin       w_ptr_next = w_ptr_succ;       empty_next = 1'b0;       if (w_ptr_succ==r_ptr_reg)         full_next = 1'b1;     end     2'b11: // write and read     begin       w_ptr_next = w_ptr_succ;       r_ptr_next = r_ptr_succ;     end   endcase end // output assign full = full_reg; assign empty = empty_reg; endmodule

代码被分为寄存器文件和FIFO控制器两部分。控制器由两个指针和两个标志触发器组成,它们的次态逻辑会检测wr和rd信号,以采取相应的动作。举例说,在“10”条件下,即暗示只发生写操作。先检查标志触发器,以确保缓存不为满。如果满足条件,我们将写指针前进一位,并清除空标志。再多存储一个字(偏移地址为1所对应的数据)可能使得FIFO缓存满,即新的写指针赶上了读指针,我们使用w_ptr_succ==r_ptr_reg表达式来描述这一情况。

根据图2,我写了下面的testbench,其RTL仿真结果与图2一致。

代码 FIFO缓存的testbench

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 `timescale 1ns/1ns module fifo_tb; localparam T=20; // clock period // global clock and asyn reset reg clk, rst_n; // fifo interface reg rd, wr; wire empty, full; reg [7:0] w_data; wire [7:0] r_data; // fifo instantiation fifo #(.B(8), .W(3)) fifo_inst (   .clk(clk), .rst_n(rst_n),   .rd(rd), .wr(wr),   .empty(empty), .full(full),   .w_data(w_data), .r_data(r_data) ); // clcok always begin   clk = 1'b0;   #(T/2);   clk = 1'b1;   #(T/2); end // reset initial begin   rst_n = 1'b0;   #(T/2)   rst_n = 1'b1; end // stimulus body initial begin   // initial input; empty   rd=0; wr=0; w_data=8'h00;   @(posedge rst_n); // wait to deassert rst_n   @(negedge clk); // wait for a clock   // 1 write   wr=1; w_data=8'h11;   @(negedge clk); // wait to assert wr   wr=0;   @(negedge clk); // wait to deassert wr   // 3 writes   wr=1;   repeat(3)   begin     w_data=w_data+8'h11;     @(negedge clk);   end   wr=0;   @(negedge clk);   // 1 read   rd=1;   @(negedge clk); // wait to assert rd   rd=0;   @(negedge clk) // wait to deassert rd   // 4 writes   wr=1;   repeat(4)   begin     w_data=w_data+8'h11;     @(negedge clk);   end   wr=0;   @(negedge clk);   // 1 write; full   wr=1; w_data=8'hAA;   @(negedge clk);   wr=0;   @(negedge clk);   // 2 reads   rd=1;   repeat(2) @(negedge clk);   rd=0;   @(negedge clk);   // 5 reads   rd=1;   repeat(5) @(negedge clk);   rd=0;   @(negedge clk);   // 1 read; empty   rd=1;   @(negedge clk);   rd=0;   @(negedge clk);   $stop; end endmodule

f372375e-5037-11ee-a25d-92fbcf53809c.png

图3 RTL级仿真波形

审核编辑:刘清