暑期在家,有充足的时间,于是希望自己能在专业技能上有所长,结合自己的爱好于是选择了Verilog。记得大三开设EDA这门课的时候,自己对EDA以及Verilog完全不感兴趣,认为他就是数字电路的重复。因为这种狭隘的眼光,现在才知道当时自己有多么愚蠢没有好好学... ...
今天先讲一讲队列的实现,因为这个比较容易。有过C语言的基础,就会知道所谓的队列就是一块连续的存储个空间,遵循先进先出的规则,即first in first out.如示意图所描述
实现过程中,我们把队列看作是一个圆,用write pointer指向队首,用read pointer指向队尾,完成一次读或写操作pointer加1,这样做可以避免对空寄存器进行读操作,对满寄存器进行写操作,这里有附图片很好的说明了这个问题:
同时在硬件设计中,我们用两个FF分别记录空状态和满状态,在系统初始化式分别将其置为1和0,然后在每个时钟周期根据续读/写信号修改他们的值。这里,我们采用Verilog语言进行描述
具体Verilog 代码如下:
module fifo #( parameter B = 8, //number of bits in a word W = 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 ,编译完成后生成了网标,可以看一看:
暑假还有不到连个月,希望自己能充分利用好这段时间学点什么,不要眼高手低,不要放弃!
working harder tomorrow!