Verilog 学习笔记之—FIFO

    暑期在家,有充足的时间,于是希望自己能在专业技能上有所长,结合自己的爱好于是选择了Verilog。记得大三开设EDA这门课的时候,自己对EDA以及Verilog完全不感兴趣,认为他就是数字电路的重复。因为这种狭隘的眼光,现在才知道当时自己有多么愚蠢没有好好学... ...

   今天先讲一讲队列的实现,因为这个比较容易。有过C语言的基础,就会知道所谓的队列就是一块连续的存储个空间,遵循先进先出的规则,即first in first out.如示意图所描述

 

Verilog <wbr>学习笔记之—FIFO

 

    实现过程中,我们把队列看作是一个圆,用write pointer指向队首,用read pointer指向队尾,完成一次读或写操作pointer加1,这样做可以避免对空寄存器进行读操作,对满寄存器进行写操作,这里有附图片很好的说明了这个问题:

Verilog <wbr>学习笔记之—FIFO
   同时在硬件设计中,我们用两个FF分别记录空状态和满状态,在系统初始化式分别将其置为1和0,然后在每个时钟周期根据续读/写信号修改他们的值。

  这里,我们采用Verilog语言进行描述

具体Verilog 代码如下:

module fifo
#(
parameter B = 8,   //number of bits in a word
          = 4   //number of address bits
)
(
input wire clk,reset,
input rd,wr,
input wire [B-1:0] w_data,
output wire empty,full,
output wire [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] <= w_data;
 //register file read operatiom
assign wr_en = wr & ~full_reg;

 

//fifo control logic
//register for read and write pointers
always @(posedge clk, posedge reset)
 if(reset)
 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 valus
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 eg)
  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 anmd 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

   我用的编辑环境为quartus ii 9.0 ,编译完成后生成了网标,可以看一看:

Verilog <wbr>学习笔记之—FIFO

    

    暑假还有不到连个月,希望自己能充分利用好这段时间学点什么,不要眼高手低,不要放弃!

    working harder tomorrow!

posted @ 2012-07-04 21:07  北同学  阅读(579)  评论(0编辑  收藏  举报