您的位置 首页 产品

FPGA的FIFO完成进程

FPGA的FIFO实现过程-FIFO队列有两个位置指示指针。一个是写指针,指向队列的第一个存储单元。一个读指针,指向队列的最后一个存储单元。当有写命令的时候,数据写入写指针指向的存储单元,然后指针加一。当有读命令的时候,读指针加一,在读出读指针指向的存储单元的数据。这里读命令,指针要加一,是定义读数据,是读出读指针的下一个存储单元的数据。

FIFO行列是一种数据缓冲器,用于数据的缓存。他是一种先入先出的存储器,即最早写入的数据,最早读。FIFO的参数有数据深度和数据宽度。数据宽度是指存储数据的宽度。深度是指存储器能够存储多少个数据。

FIFO行列有两个标志位。一个满和一个空标志位。别离表明FIFO是数据写满,仍是数据读空。在数据写满状况下,数据写入是不允许的,因而在这个状况下,写入的数据无效。而数据读空状况下,数据读取是不允许的,因而在这个状况下,读取的数据无效。

FIFO行列有两个方位指示指针。一个是写指针,指向行列的第一个存储单元。一个读指针,指向行列的最终一个存储单元。当有写指令的时分,数据写入写指针指向的存储单元,然后指针加一。当有读指令的时分,读指针加一,在读出读指针指向的存储单元的数据。这儿读指令,指针要加一,是界说读数据,是读出读指针的下一个存储单元的数据。

FPGA的FIFO完成进程

当写指针和读指针的指向存储单元相一起,这时分依据之前是读指令仍是写指令来判别行列是空,仍是满。在读指令,两个指针值相一起分,则行列空。在写指令,两个指针值相同,则行列满。

今后就开端写代码完成上诉FIFO行列,并进行仿真。

以下,是完成数据宽度为8.深度为2^4的深度的FIFO。。读/写时钟是同一个。

module fifo_cus

#(

parameter N = 8, //数据宽度

parameter M = 4 //fifo的地址宽度

)

//对行列的参数设置。主张这样写,便于今后代码的移植。

//假如今后要完成数据宽度为16,深度为2^8的FIFO。只需改N =16 M=8即可

(

input clk, //输入时钟

input rst_n, //输入复位信号

input wr, //输入写使能

input[N-1:0] w_data, //输入输入

input rd, //输入读使能

output empty, //输出fifo空标志

output full, //输出fifo满标志

output[N-1:0] r_data //输出读取的数据

);

//寄存器组,用来充任FIFO行列

reg [N-1:0] array_reg [2**M – 1:0];

//界说写指针,指示当时写的方位,下一个状况写的方位,写方位的下一个方位

reg [M-1:0] w_ptr_reg, w_ptr_next,w_ptr_succ;

//界说读指针,指示当时读的方位,下一个状况读的方位,读方位的下一个方位

reg [M-1:0] r_ptr_reg, r_ptr_next,r_ptr_succ;

//界说FIFO满和空的信号

reg full_reg, full_next;

reg empty_reg, empty_next;

wire wr_en;

//数据的写入,在数据的上升沿的时分,有写使能信号,将数据写入。而

always@( posedge clk ) begin

if( wr_en )

array_reg[w_ptr_reg] <= w_data;

else

array_reg[w_ptr_reg] <= array_reg[w_ptr_reg];

end

// 数据的读取。数据读取是一直在读取的,不过读取的是之前的值。

assign r_data = array_reg[r_ptr_reg];

assign wr_en = wr & ~full_reg;

/*状况跳转

在复位信号有用,读/写指针都指向0地址。此刻行列状况为空。

在复位不有用,且在时钟的上升沿,读/写指针的值,行列空,满状况的值又下一状况决议。不然坚持 */

always@( posedge clk ) begin

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

end

//下一个状况的断定

always@ * begin

w_ptr_next = w_ptr_reg;

r_ptr_next = r_ptr_reg;

full_next = full_reg;

empty_next = empty;

w_ptr_succ = w_ptr_reg + 1'b1;

r_ptr_succ = r_ptr_reg + 1'b1;

case( {wr,rd} )

/*读指令:在读指令下,假如行列不为空,讲当时读指针的下一个指针赋值给读指针的下一个状况,一起将行列的满标志置0。

然后判别读指针的下一个指针是否和写指针的值相同。相同的话,阐明,行列为空。不然不为空。 */

2'b01:

begin

if( ~empty_reg )

begin

r_ptr_next = r_ptr_succ;

full_next = 0;

if( r_ptr_succ == w_ptr_reg )

empty_next = 1'b1;

else

empty_next = 1'b0;

end

end

/*写指令:在写指令下,假如行列不为满,将当时写指针的下一个指针赋值给读指针的下一个状况,一起将行列的空标志置0。

然后判别写指针的下一个指针是否和读指针的值相同。相同的话,阐明,行列为满。不然不为满。

*/

2'b10:

begin

if( ~full_reg )

begin

w_ptr_next = w_ptr_succ;

empty_next= 0;

if( w_ptr_succ == r_ptr_reg )

full_next = 1'b1;

else

full_next = 1'b0;

end

end

/*读写指令:在读写指令下, 直接改动对应指针的下一个状况值。

*/

2'b11:

begin

w_ptr_next = w_ptr_succ;

r_ptr_next = r_ptr_succ;

endcase

end

// 满/空输出信号的赋值。

assign full = full_reg;

assign empty = empty_reg;

endmodule

好了,总算搞定FIFO的代码了。下面来仿真看看成果。

以下剖析仿真的成果:

写数据:

从下图仿真,可看出。在最开端的时分,行列是空的状况。读指针和写指针都是0。在写使能状况下,在每个时钟的上升沿(蓝色线),数据写入行列array_reg中。一起,写指针加一。而读指针是不变的。

FPGA的FIFO完成进程

从下图发现,在行列满状况下,即便写使能,FIFO也不接受写数据。仍旧坚持本来的值。

FPGA的FIFO完成进程

读数据

从下图中看出,最开端,数据读出是有值的。为初始化的读指针指向的存储单元的值。这儿为4。

当有读指令时分,在时钟的上升沿(蓝色线),读指针加一。读取的数据随之改动。

FPGA的FIFO完成进程

在数据读完后,即行列为空状况下。此刻对数据的读取是无效的。从图中可看出,读完后,读指针为0.回到存储器的第一个地址。而此刻读出的值是无效的。

FPGA的FIFO完成进程

读写指令:

在一起读一起写的时分。从下图,可看出,成果有问题了。在行列为空的状况下,此刻读取的值,应为此刻写的数据才对了。可是从图中,可看出,读取的值不是当时写的数据的值。而是之前存储在FIFO中的值。这样的话,读取的值就不是正确的值了。

FPGA的FIFO完成进程

从上图仿真成果,可知。程序在读写指令时分,编写得不正确。形成成果不对。

回来程序剖析。程序不对的当地在于读写指令的时分,处理 得不正确。在空的状况下,数据写入是先写入,然后写指针加一。而读取指令是,指针先加一,然后再读取。而读和写指针的值相同的。这样形成,读取的FIFO的存储单元的值,为写的存储单元的下一个存储单元的值。因而形成读取不正确。

改正的程序如下:

2'b11:

begin

if( ~full_reg && ~empty_reg )

begin

w_ptr_next = w_ptr_succ;

r_ptr_next = r_ptr_succ;

end

else if( full_reg ) //在满的状况,不允许写

begin

r_ptr_next = r_ptr_succ;

full_next = 0;

end

else if( empty_reg ) //在空的状况,不允许写

begin

w_ptr_next = w_ptr_succ;

empty_next = 0;

end

end

只需要规则以下:在满的状况,不允许写,在空的状况下,不允许读。这样就能够了。

然后再进行仿真:

这儿只看读写指令的图。从下图中,可看出,此刻读取的数据,为刚刚写的数据。这样就正确了。

FPGA的FIFO完成进程

这样,就完成了FPGA的FIFO了。经过这样一个简略的操练,可看出,仿真,是很重要的,能发现程序中的问题。

以上仿真没有掩盖到一切状况,有爱好的,能够自己仿真看看仿真图,验证程序写得是否正确。

声明:本文内容来自网络转载或用户投稿,文章版权归原作者和原出处所有。文中观点,不代表本站立场。若有侵权请联系本站删除(kf@86ic.com)https://www.86ic.net/xinpin/chanpin/341120.html

为您推荐

联系我们

联系我们

在线咨询: QQ交谈

邮箱: kf@86ic.com

关注微信
微信扫一扫关注我们

微信扫一扫关注我们

返回顶部