首页 > 代码库 > 同步fifo的verilogHDL设计实例

同步fifo的verilogHDL设计实例

原创

设计一个fifo,输入16bit,输出16bit的data,寻址宽度5bit,有空满标志。

 top 层如下所示:

 1 /* 2 date :  2014/10/14 3 version : modelsim 10.1e-altera  4 design  : pengxiaoen  5 function : 同步fifo设计 6 */ 7 module test2 ( 8                     clock , 9                     reset,10                     in_data ,11                     12                     ou_data ,13                     wr_full ,14                     rd_empty ,15                     wr_en ,16                     rd_en 17                     );18                     19                     20 input  clock ,reset ; 21 input  [15:0] in_data ; // 写入的数据22 input         wr_en  ; //写使能23 input         rd_en  ; //读使能24 25 output  [15:0] ou_data ; // 读出的数据26 output         wr_full ;  //写满标志27 output         rd_empty ;  //读空标志28  29 wire [4:0]  add_head; //ram地址头,当读使能有效+1 30 wire [4:0]  add_end ; //ram地址尾,当写使能有效+1 31 32 //---------ram 模块,用来存储数据和输出数据--------------------------33 data_memory  U1_mem(  34                             .clock (clock),35                             .reset (reset),36                             .wr_en  (wr_en),  37                             .rd_en  (rd_en),38                             .add_head (add_head) ,39                             .add_end (add_end),40                             .in_data (in_data),41                             .ou_data (ou_data)42                             );43 44 //------------地址产生器 + 标志产生器---------------------------------                            45 fifo_control U2_cont(46                             .clock (clock),47                             .reset (reset),48                             .wr_en (wr_en),49                             .rd_en (rd_en),50                             .wr_full (wr_full),51                             .rd_empty (rd_empty),52                             .add_head (add_head),53                             .add_end (add_end)54                             );                            55         56 57 endmodule 

 

 1 module  data_memory ( 2                             clock ,reset , 3                             wr_en  ,  rd_en  , 4                             add_head ,add_end , 5                             in_data ,ou_data  6                             ); 7   input           clock ,reset ; // system clock and system reset   8   input           wr_en  ;     // write enable  9   input           rd_en ;      // read enable 10   input   [4:0]   add_head ;  // memory address head 11   input   [4:0]   add_end ;   // memory address end 12   input     [15:0]in_data ;   // data input to memory 13   output    reg[15:0]ou_data ;   // data output14                             15   reg [15:0] mem [0:31]  ;   //define the memory                          16   always @ (posedge clock )17         if(!reset)18                 begin19                         ou_data  <=  16dx ;20                 end 21         else 22                 begin 23                         case ({wr_en, rd_en})24                             2b00  :  ou_data       <=  16dx ; 25                             2b01  :  ou_data       <=  mem[add_head] ;26                             2b10  :  mem[add_end] <=  in_data ;27                             2b11  :  begin 28                                                 ou_data       <=  mem[add_end] ;29                                                 mem[add_head] <=  in_data ;30                                          end 31                         endcase 32                 end 33     34 endmodule 

 

 1 module fifo_control ( 2                             clock ,reset , 3                             wr_en ,rd_en , 4                             wr_full ,rd_empty, 5                             add_head,add_end  6                             ); 7   input            clock ,reset ;   // system clock and system reset  8   input            wr_en ;          // write enable  9   input            rd_en  ;         // read  enable 10   output reg       wr_full ;        // fifo full flag                             11   output reg       rd_empty ;       // fifo empty 12   output reg [4:0] add_head  ,add_end ; 13     14  reg  [4:0] head_temp , end_temp ;     15  //------地址产生块,依据读写使能进行相应地址递增,并保存原始的位置信息-----------------------16   always @ (posedge clock)17         if(!reset)18                 begin 19                         head_temp <=   5d0  ;20                         end_temp  <=   5d0  ;21                         add_head  <=   5d0  ;22                         add_end   <=   5d0  ; 23                 end 24                         25         else 26                 begin 27                         case ({wr_en, rd_en})28                                 2b00  :   begin 29                                                         head_temp  <=  add_head  ;30                                                         end_temp   <=  add_end   ;31                                               end 32                                 2b01  :   begin 33                                                         end_temp  <=   add_end ; 34                                                         add_head  <=   add_head + 5d1 ;35                                               end    36                                 2b10  :   begin 37                                                         head_temp <=   add_head ; 38                                                         add_end   <=   add_end  + 5d1 ;39                                               end 40                                 2b11  :   begin41                                                         add_head  <=  add_head  +  5d1  ; 42                                                         add_end   <=  add_end   +  5d1  ;43                                               end 44                         endcase 45                 end 46         47 //--------标志产生块-------------------                            48   always @ (posedge clock)49         if(!reset)50                 begin 51                         wr_full   <=   1d0  ; 52                         rd_empty  <=   1d0  ; 53                 end 54         else55                 begin 56                         case ({wr_en , rd_en})57                                 2b00 :  begin   58                                                     rd_empty  <=  1d0 ; 59                                                     wr_full   <=  1d0 ;60                                         end 61                                 2b01 :  begin 62                                                     wr_full  <=  1d0 ; //写标志复位63                                                     if ((add_head +  5d1) == head_temp)64                                                             rd_empty  <=  1d1 ; //只有切换到写使能才复位65                                         end 66                                 2b10 :  begin 67                                                     rd_empty  <=  1d0 ; //读标志复位68                                                     if ((add_end +  5d1) == end_temp)69                                                             wr_full  <=  1d1 ; //只有切换到读使能才复位    70                                         end 71                                 2b11 : begin72                                                     rd_empty  <=  1d0 ; 73                                                     wr_full   <=  1d0 ;74                                         end 75                         endcase 76                 end 77 78                             79 endmodule

 

下面附上测试代码

 1 `timescale  1ns/1ps  2  3 module test2_tb ;  4 reg clock ,reset ;  5 reg [15:0] in_data ;  6 reg        wr_en ;  7 reg        rd_en ;  8  9 wire [15:0] ou_data ; 10 wire        wr_full ; 11 wire        rd_empty ; 12 13 14 test2  U_top (15                     .clock (clock),16                     .reset (reset),17                     .in_data (in_data),18                     19                     .ou_data (ou_data),20                     .wr_full (wr_full),21                     .rd_empty (rd_empty),22                     .wr_en (wr_en),23                     .rd_en (rd_en)24                     );25             26 integer i ; 27             28 always #10  clock = ~clock ; 29 30 initial 31     begin 32             clock =1d0 ;   reset = 1d0  ;   wr_en <= 1d0 ;  rd_en  <= 1d0 ;33             in_data = http://www.mamicode.com/16d0 ; 34             #20 reset = 1d1 ; wr_en <= 1d1 ; 35           for (i=0;i<40;i=i+1) // 故意溢出36                 #20 in_data  <=  in_data + 16d1 ; 37                 38             rd_en  <=  1d1 ; wr_en <= 1d0 ;39             #(40*20 ) // 让读空标志位触发40             $stop   ; 41             42     end 43 44 endmodule 

 

同步fifo的verilogHDL设计实例