同步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 output
14                             
15   reg [15:0] mem [0:31]  ;   //define the memory                          
16   always @ (posedge clock )
17         if(!reset)
18                 begin
19                         ou_data  <=  16'dx ;
20                 end 
21         else 
22                 begin 
23                         case ({wr_en, rd_en})
24                             2'b00  :  ou_data       <=  16'dx ; 
25                             2'b01  :  ou_data       <=  mem[add_head] ;
26                             2'b10  :  mem[add_end] <=  in_data ;
27                             2'b11  :  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 <=   5'd0  ;
20                         end_temp  <=   5'd0  ;
21                         add_head  <=   5'd0  ;
22                         add_end   <=   5'd0  ; 
23                 end 
24                         
25         else 
26                 begin 
27                         case ({wr_en, rd_en})
28                                 2'b00  :   begin 
29                                                         head_temp  <=  add_head  ;
30                                                         end_temp   <=  add_end   ;
31                                               end 
32                                 2'b01  :   begin 
33                                                         end_temp  <=   add_end ; 
34                                                         add_head  <=   add_head + 5'd1 ;
35                                               end    
36                                 2'b10  :   begin 
37                                                         head_temp <=   add_head ; 
38                                                         add_end   <=   add_end  + 5'd1 ;
39                                               end 
40                                 2'b11  :   begin
41                                                         add_head  <=  add_head  +  5'd1  ; 
42                                                         add_end   <=  add_end   +  5'd1  ;
43                                               end 
44                         endcase 
45                 end 
46         
47 //--------标志产生块-------------------                            
48   always @ (posedge clock)
49         if(!reset)
50                 begin 
51                         wr_full   <=   1'd0  ; 
52                         rd_empty  <=   1'd0  ; 
53                 end 
54         else
55                 begin 
56                         case ({wr_en , rd_en})
57                                 2'b00 :  begin   
58                                                     rd_empty  <=  1'd0 ; 
59                                                     wr_full   <=  1'd0 ;
60                                         end 
61                                 2'b01 :  begin 
62                                                     wr_full  <=  1'd0 ; //写标志复位
63                                                     if ((add_head +  5'd1) == head_temp)
64                                                             rd_empty  <=  1'd1 ; //只有切换到写使能才复位
65                                         end 
66                                 2'b10 :  begin 
67                                                     rd_empty  <=  1'd0 ; //读标志复位
68                                                     if ((add_end +  5'd1) == end_temp)
69                                                             wr_full  <=  1'd1 ; //只有切换到读使能才复位    
70                                         end 
71                                 2'b11 : begin
72                                                     rd_empty  <=  1'd0 ; 
73                                                     wr_full   <=  1'd0 ;
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 =1'd0 ;   reset = 1'd0  ;   wr_en <= 1'd0 ;  rd_en  <= 1'd0 ;
33             in_data = 16'd0 ; 
34             #20 reset = 1'd1 ; wr_en <= 1'd1 ; 
35           for (i=0;i<40;i=i+1) // 故意溢出
36                 #20 in_data  <=  in_data + 16'd1 ; 
37                 
38             rd_en  <=  1'd1 ; wr_en <= 1'd0 ;
39             #(40*20 ) // 让读空标志位触发
40             $stop   ; 
41             
42     end 
43 
44 endmodule 
原文地址:https://www.cnblogs.com/sepeng/p/4024662.html