0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

基于循环队列的FIFO缓存实现

Hack电子 来源:Hack电子 2023-09-11 10:12 次阅读

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

d5f8bce2-5047-11ee-a25d-92fbcf53809c.png

图1 FIFO缓存的概念框图

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

基于循环队列的实现

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

d6063bd8-5047-11ee-a25d-92fbcf53809c.jpg

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

FIFO缓存通常包括两个标志信号,full和empty,相应地来指示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
modulefifo
#(
parameterB=8, // number of bits in a word
W=3 // number of address bits
)
(
// global clock and aysn reset
inputclk,
inputrst_n,
// fifo interface
// fifo control signnal
inputrd,
inputwr,
// fifo status signal
outputempty,
outputfull,
// 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;
regfull_reg, empty_reg, full_next, empty_next;
wirewr_en;
// body
// register file write operation
always@(posedgeclk)
if(wr_en)
array_reg[w_ptr_reg] <= w_data;
// register file read operation
assignr_data = array_reg[r_ptr_reg];
// write enabled only when FIFO is not full
assignwr_en = wr & ~full_reg;
// fifo control logic
// register for read and write pointers
always@(posedgeclk, negedgerst_n)
if(!rst_n)
begin
w_ptr_reg <= 0;
r_ptr_reg <= 0;
full_reg <= 1'b0;
empty_reg <= 1'b1;
end
else
begin
w_ptr_reg <= w_ptr_next;
r_ptr_reg <= r_ptr_next;
full_reg <= full_next;
empty_reg <= empty_next;
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
assignfull = full_reg;
assignempty = 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
`timescale1ns/1ns
modulefifo_tb;
localparam T=20; // clock period
// global clock and asyn reset
regclk, rst_n;
// fifo interface
regrd, wr;
wireempty, 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;
@(posedgerst_n); // wait to deassert rst_n
@(negedgeclk); // wait for a clock
// 1 write
wr=1; w_data=8'h11;
@(negedgeclk); // wait to assert wr
wr=0;
@(negedgeclk); // wait to deassert wr
// 3 writes
wr=1;
repeat(3)
begin
w_data=w_data+8'h11;
@(negedgeclk);
end
wr=0;
@(negedgeclk);
// 1 read
rd=1;
@(negedgeclk); // wait to assert rd
rd=0;
@(negedgeclk) // wait to deassert rd
// 4 writes
wr=1;
repeat(4)
begin
w_data=w_data+8'h11;
@(negedgeclk);
end
wr=0;
@(negedgeclk);
// 1 write; full
wr=1; w_data=8'hAA;
@(negedgeclk);
wr=0;
@(negedgeclk);
// 2 reads
rd=1;
repeat(2) @(negedgeclk);
rd=0;
@(negedgeclk);
// 5 reads
rd=1;
repeat(5) @(negedgeclk);
rd=0;
@(negedgeclk);
// 1 read; empty
rd=1;
@(negedgeclk);
rd=0;
@(negedgeclk);
$stop;
end
endmodule

d6272ca8-5047-11ee-a25d-92fbcf53809c.png

图3 RTL级仿真波形

审核编辑:汤梓红

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 寄存器
    +关注

    关注

    31

    文章

    5308

    浏览量

    119980
  • fifo
    +关注

    关注

    3

    文章

    387

    浏览量

    43535
  • Verilog
    +关注

    关注

    28

    文章

    1343

    浏览量

    109973
  • 缓存
    +关注

    关注

    1

    文章

    232

    浏览量

    26645
  • RTL
    RTL
    +关注

    关注

    1

    文章

    385

    浏览量

    59693

原文标题:Verilog设计FIFO

文章出处:【微信号:Hack电子,微信公众号:Hack电子】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    FIFO队列原理简述

    FIFO队列机制中最简单的,每个接口上只有一个FIFO队列,表面上看FIFO队列并没有提供什么
    发表于 07-10 09:22 1633次阅读

    一种简单的、真实的基于循环序列的FIFO缓存设计

    FIFO缓存是介于两个子系统之间的弹性存储器,其概念图如图1所示。它有两个控制信号,wr和rd,用于读操作和写操作
    发表于 09-11 09:12 518次阅读
    一种简单的、真实的基于<b class='flag-5'>循环</b>序列的<b class='flag-5'>FIFO</b><b class='flag-5'>缓存</b>设计

    labview能实现循环队列吗?

    救助:请问高手:labview能实现循环队列吗?
    发表于 08-13 15:02

    基于队列函数实现并行循环间传输数据

    数据经过入队列和出队列两个函数过程得到传递,本程序使用队列函数,实现两个并行循环间的数据传递。循环
    发表于 04-23 09:40

    队列FIFO——支持网络QoS的重要芯片

    摘要:在IP网络中支持QoS是近年来研究的热点,而IDT公司推出的新型存储器件——多队列FIFO能够支持QoS的应用。因其具有单器件下支持可配置的多个队列,并具有可
    发表于 03-11 13:22 1147次阅读
    多<b class='flag-5'>队列</b><b class='flag-5'>FIFO</b>——支持网络QoS的重要芯片

    FIFO队列原理简述 拥塞避免原理

    拥塞管理是指网络在发生拥塞时,如何进行管理和控制。FIFO队列不对报文进行分类,按报文到达接口的先后顺序让报文进入队列,采用尽力而为的转发模式,PQ队列是针对关键业务应用设计的。
    发表于 02-23 08:35 1w次阅读
    <b class='flag-5'>FIFO</b><b class='flag-5'>队列</b>原理简述 拥塞避免原理

    数据处理时为什么要从DMA缓存空间中获取?

    1、初始化时开启串口的空闲中断,并且初始化为循环DMA。2、触发空闲中断时,更新索引,这个索引表示当前写入索引值,用于上层判断缓存空间已写入的数据(鱼鹰前面写了关于循环FIFO的笔记,
    的头像 发表于 06-24 11:28 3849次阅读

    基于多级队列的云服务并发量分级缓存机制

    基于多级队列的云服务并发量分级缓存机制
    发表于 06-24 11:35 15次下载

    队列实现数据循环外显示源码下载

    队列实现数据循环外显示源码下载
    发表于 11-26 09:21 4次下载

    FPGA学习-基于FIFO的行缓存结构

    在FPGA中对图像的一行数据进行缓存时,可以采用FIFO这一结构,如上图所示,新一行图像数据流入到FIFO1中,FIFO1中会对图像数据进行缓存
    的头像 发表于 05-10 09:59 3797次阅读

    Gowin先进先出队列(FIFO)用户指南

    电子发烧友网站提供《Gowin先进先出队列(FIFO)用户指南.pdf》资料免费下载
    发表于 09-15 09:57 0次下载
    Gowin先进先出<b class='flag-5'>队列</b>(<b class='flag-5'>FIFO</b>)用户指南

    Gowin先进先出队列(FIFO HS)用户指南

    电子发烧友网站提供《Gowin先进先出队列(FIFO HS)用户指南 .pdf》资料免费下载
    发表于 09-15 09:55 1次下载
    Gowin先进先出<b class='flag-5'>队列</b>(<b class='flag-5'>FIFO</b> HS)用户指南

    嵌入式环形队列和消息队列实现

    嵌入式环形队列和消息队列实现数据缓存和通信的常见数据结构,广泛应用于嵌入式系统中的通信协议和领域。
    的头像 发表于 04-14 11:52 1513次阅读

    嵌入式环形队列和消息队列是如何去实现的?

    嵌入式环形队列和消息队列实现数据缓存和通信的常见数据结构,广泛应用于嵌入式系统中的通信协议和领域。
    发表于 05-20 14:55 1093次阅读

    嵌入式环形队列与消息队列实现原理

    嵌入式环形队列,也称为环形缓冲区或循环队列,是一种先进先出(FIFO)的数据结构,用于在固定大小的存储区域中高效地存储和访问数据。其主要特点包括固定大小的数组和两个指针(头指针和尾指针
    的头像 发表于 09-02 15:29 323次阅读