本练习的目的是使用计数器。
Part I 用T触发器实现16-bit的计数器
参照图 1所示的4-bit的同步计数器,实现一个16-bit 的计数器。
代码16-bit counter
 1 //top-level file
 2  module part1(KEY0,SW,HEX3,HEX2,HEX1,HEX0);
 3 input KEY0;       //时钟脉冲
 4  input [1:0]SW;    //使能&复位
 5  output [6:0]HEX3,HEX2,HEX1,HEX0; //输出显示
 6  wire [15:0]q;     //16-bit计数输出
 7    
 8   counter_16(SW[1],KEY0,SW[0],q);
 9   
10   seg7_lut H0(q[3:0],HEX0);
11   seg7_lut H1(q[7:4],HEX1);
12   seg7_lut H2(q[11:8],HEX2);
13   seg7_lut H3(q[15:12],HEX3);
14   
15  endmodule
 1 //由T触发器构建的16-bit计数器
 2  module counter_16(en,clk,clr,Q);
 3 input en,clk,clr;
 4 wire [15:0]q;
 5 output [15:0]Q;  
 6       t_ff u0(en,clk,clr,q[0]);
 7       t_ff u1(en&q[0],clk,clr,q[1]);
 8       t_ff u2(en&q[0]&q[1],clk,clr,q[2]);
 9       t_ff u3(en&q[0]&q[1]&q[2],clk,clr,q[3]);
10       t_ff u4(en&q[0]&q[1]&q[2]&q[3],clk,clr,q[4]);
11       t_ff u5(en&q[0]&q[1]&q[2]&q[3]&q[4],clk,clr,q[5]);
12       t_ff u6(en&q[0]&q[1]&q[2]&q[3]&q[4]&q[5],clk,clr,q[6]);
13       t_ff u7(en&q[0]&q[1]&q[2]&q[3]&q[4]&q[5]&q[6],clk,clr,q[7]);
14       t_ff u8(en&q[0]&q[1]&q[2]&q[3]&q[4]&q[5]&q[6]&q[7],clk,clr,q[8]);
15       t_ff u9(en&q[0]&q[1]&q[2]&q[3]&q[4]&q[5]&q[6]&q[7]&q[8],
16               clk,clr,q[9]);
17       t_ff u10(en&q[0]&q[1]&q[2]&q[3]&q[4]&q[5]&q[6]&q[7]&q[8]&q[9],
18               clk,clr,q[10]);  
19       t_ff u11(en&q[0]&q[1]&q[2]&q[3]&q[4]&q[5]&q[6]&q[7]&q[8]&q[9]&q[10],
20               clk,clr,q[11]);   
21       t_ff u12(en&q[0]&q[1]&q[2]&q[3]&q[4]&q[5]&q[6]&q[7]&q[8]&q[9]&q[10]&q[11],
22               clk,clr,q[12]);   
23       t_ff u13(en&q[0]&q[1]&q[2]&q[3]&q[4]&q[5]&q[6]&q[7]&q[8]&q[9]&q[10]&q[11]&q[12],
24               clk,clr,q[13]);  
25       t_ff u14(en&q[0]&q[1]&q[2]&q[3]&q[4]&q[5]&q[6]&q[7]&q[8]&q[9]&q[10]&q[11]&q[12]&q[13],
26               clk,clr,q[14]);     
27       t_ff u15(en&q[0]&q[1]&q[2]&q[3]&q[4]&q[5]&q[6]&q[7]&q[8]&q[9]&q[10]&q[11]&q[12]&q[13]&q[14],
28               clk,clr,q[15]); 
29               
30 assign Q=q;        
31                                                         
32  endmodule
 1 //T flip flop
 2  module t_ff(t,clk,rst_n,q);
 3 input t,clk,rst_n;
 4 outputreg q;
 5   
 6 always @(posedge clk)
 7 begin
 8 if(!rst_n)
 9       q<=0;
10 else 
11 begin
12 if(t==1'b1)
13          q<=~q;
14 else 
15         q<=q;
16 end    
17 end
18   
19  endmodule
图2 Fmax值
图3 占用的LE数量
Part II 用赋值语句实现16-bit计数器
代码
 1 //counter-16bit
 2  module part2(clk,rst_n,q);
 3 input clk,rst_n;
 4 outputreg [15:0]q;
 5   
 6 always @(posedge clk)
 7 begin 
 8 if(!rst_n)
 9       q<=1'b0;
10  else 
11 begin
12 if(q==65535)
13         q<=0;
14 else
15         q<=q+1;
16 end
17 end
18   
19  endmodule
图4 16-bit计数器的RTL视图
图5 Fmax值
图6 16-bit计数器占用的LE
Part III 用LPM实现16-bit计数器
代码
1 //Top-level file
2  module counter_lpm(en,clk,clr,q);
3 input en,clk,clr;
4 output  [15:0]q;
5   
6   megcounter counter_16bit(.clock(clk),.cnt_en(en),.sclr(clr),
7                            .q(q)
8                            );
9 endmodule
 1 // synopsys translate_off
 2 `timescale 1 ps /1 ps
 3 // synopsys translate_on
 4 module megcounter (
 5     clock,
 6     cnt_en,
 7     sclr,
 8     q);
 9 
10 input      clock;
11 input      cnt_en;
12 input      sclr;
13 output    [15:0]  q;
14 
15 wire [15:0] sub_wire0;
16 wire [15:0] q = sub_wire0[15:0];
17 
18     lpm_counter    lpm_counter_component (
19                 .sclr (sclr),
20                 .clock (clock),
21                 .cnt_en (cnt_en),
22                 .q (sub_wire0),
23                 .aclr (1'b0),
24                 .aload (1'b0),
25                 .aset (1'b0),
26                 .cin (1'b1),
27                 .clk_en (1'b1),
28                 .cout (),
29                 .data ({16{1'b0}}),
30                 .eq (),
31                 .sload (1'b0),
32                 .sset (1'b0),
33                 .updown (1'b1));
34 defparam
35         lpm_counter_component.lpm_direction ="UP",
36         lpm_counter_component.lpm_port_updown ="PORT_UNUSED",
37         lpm_counter_component.lpm_type ="LPM_COUNTER",
38         lpm_counter_component.lpm_width =16;
39 
40 
41 endmodule
图7 用LPM实现16-bit计数器所占用的LE
Part IV 循环显示0-9
在HEX0上循环显示0-9,每秒刷新一次。
代码
  1 //top-level file
  2 module seg_number(
  3 output [6:0]HEX0,
  4 input CLOCK_50,
  5 input [0:0]KEY
  6                   );
  7                   
  8 wire clk_1hz;
  9 reg [3:0]cnt;
 10                   
 11                   div u0(
 12                          .o_clk(clk_1hz),
 13                          .i_clk(CLOCK_50),
 14                          .rst_n(KEY)
 15                          );
 16                          
 17 always @(posedge clk_1hz ornegedge KEY)
 18 begin
 19 if(!KEY)
 20                            cnt<=4'b0;
 21 else 
 22 begin
 23 if(cnt==4'd9)
 24                              cnt<=4'b0;
 25 else
 26                              cnt<=cnt+1'b1;
 27 end
 28 end
 29                   
 30                   seg7_lut u1(
 31                               .oseg(HEX0),
 32                               .idig(cnt[3:0])
 33                               );
 34 endmodule
 35 
 36 //divider
 37 module div(
 38 outputreg o_clk,
 39 input      rst_n,
 40 input      i_clk
 41            );
 42            
 43 parameter N=50_000_000;
 44 parameter M=24_999_999;
 45            
 46 reg [25:0]cnt;
 47            
 48 always @(posedge i_clk ornegedge rst_n)
 49 begin
 50 if(!rst_n)
 51                cnt<=26'b0;
 52 else
 53 begin
 54 if(cnt==N-1)
 55                    cnt<=26'b0;
 56 else
 57                    cnt<=cnt+26'b1;
 58 end
 59 end
 60 always @(posedge i_clk ornegedge rst_n)
 61 begin
 62 if(!rst_n)
 63                o_clk<=0;
 64 else
 65 begin
 66 if(cnt<=M)
 67                o_clk<=1;
 68 else
 69                o_clk<=0;
 70 end
 71 end
 72            
 73 endmodule
 74 
 75 //seg7_lut
 76 module seg7_lut (
 77 outputreg [6:0] oseg,
 78 input      [3:0] idig
 79 );
 80 always @ (idig)
 81 begin
 82 case (idig)
 83 4'h1: oseg = 7'b1111001; // ---t---
 84 4'h2: oseg = 7'b0100100;  // |    |
 85 4'h3: oseg = 7'b0110000;  // lt    rt
 86 4'h4: oseg = 7'b0011001;  // |    |
 87 4'h5: oseg = 7'b0010010;  // ---m---
 88 4'h6: oseg = 7'b0000010;  // |    |
 89 4'h7: oseg = 7'b1111000;  // lb    rb
 90 4'h8: oseg = 7'b0000000;  // |    |
 91 4'h9: oseg = 7'b0011000;  // ---b---
 92 4'ha: oseg = 7'b0001000;
 93 4'hb: oseg = 7'b0000011;
 94 4'hc: oseg = 7'b1000110;
 95 4'hd: oseg = 7'b0100001;
 96 4'he: oseg = 7'b0000110;
 97 4'hf: oseg = 7'b0001110;
 98 default: oseg =7'b1000000;
 99 endcase
100 end
101 endmodule
Part V 循环显示HELLO
在HEX7-HEX0上循环显示HELLO,如图8所示。
图8 8个7segment上循环显示HELLO
代码
top-level file
 1 //top-level file
 2 module hello(HEX7,HEX6,HEX5,HEX4,
 3              HEX3,HEX2,HEX1,HEX0,
 4              CLOCK_50,KEY);
 5 input CLOCK_50;
 6 input [0:0]KEY;
 7 output [6:0]HEX7,HEX6,HEX5,HEX4,HEX3,HEX2,
 8               HEX1,HEX0;
 9               
10 wire clk_1hz;
11 reg [3:0]cnt;
12   
13   div u0(.o_clk(clk_1hz),
14          .rst_n(KEY),
15          .i_clk(CLOCK_50)
16          );
17          
18 always @(posedge clk_1hz ornegedge KEY)
19 begin
20 if(!KEY)
21       cnt<=4'b0;
22 else 
23 begin
24 if(cnt==4'b0111)
25         cnt<=4'b0;
26 else
27         cnt<=cnt+1'b1;
28 end
29 end
30   
31   seg7_h0 h0(.oseg(HEX0),
32              .idig(cnt)
33              );
34   seg7_h1 h1(.oseg(HEX1),
35              .idig(cnt)
36              );
37   seg7_h2 h2(.oseg(HEX2),
38              .idig(cnt)
39              );
40   seg7_h3 h3(.oseg(HEX3),
41              .idig(cnt)
42              );
43   seg7_h4 h4(.oseg(HEX4),
44              .idig(cnt)
45              );
46   seg7_h5 h5(.oseg(HEX5),
47              .idig(cnt)
48              );
49   seg7_h6 h6(.oseg(HEX6),
50              .idig(cnt)
51              );
52   seg7_h7 h7(.oseg(HEX7),
53              .idig(cnt)
54              ); 
55 endmodule

分频器
 1 //divider
 2 module div(
 3 outputreg o_clk,
 4 input      rst_n,
 5 input      i_clk
 6            );
 7            
 8 parameter N=50_000_000;
 9 parameter M=24_999_999;
10            
11 reg [25:0]cnt;
12            
13 always @(posedge i_clk ornegedge rst_n)
14 begin
15 if(!rst_n)
16                cnt<=26'b0;
17 else
18 begin
19 if(cnt==N-1)
20                    cnt<=26'b0;
21 else
22                    cnt<=cnt+26'b1;
23 end
24 end
25 always @(posedge i_clk ornegedge rst_n)
26 begin
27 if(!rst_n)
28                o_clk<=0;
29 else
30 begin
31 if(cnt<=M)
32                o_clk<=1;
33 else
34                o_clk<=0;
35 end
36 end
37            
38 endmodule

译码0
 1 //seg7_lut
 2 module seg7_h0
 3  (
 4 outputreg [6:0] oseg,
 5 input      [3:0] idig
 6 );
 7 always @ (idig)
 8 begin
 9 case (idig)
10 4'h0: oseg = 7'b1000000; //O
11 //4'h1: oseg = 7'b1111001; 
12 //4'h2: oseg = 7'b0100100;  
13 //4'h3: oseg = 7'b0110000;  
14 4'h4: oseg = 7'b0001001;  //H 
15 4'h5: oseg = 7'b0000110;  //E 
16 4'h6: oseg = 7'b1000111;  //L  
17 4'h7: oseg = 7'b1000111;  //L 
18 
19 default: oseg =7'b1111111;
20 endcase
21 end
22 endmodule

译码1
 1 //seg7_lut
 2 module seg7_h1
 3  (
 4 outputreg [6:0] oseg,
 5 input      [3:0] idig
 6 );
 7 always @ (idig)
 8 begin
 9 case (idig)
10 4'h1: oseg = 7'b1000000; //O
11 //4'h4: oseg = 7'b1111001; 
12 //4'h2: oseg = 7'b0100100;  
13 //4'h3: oseg = 7'b0110000;  
14 4'h5: oseg = 7'b0001001;  //H 
15 4'h6: oseg = 7'b0000110;  //E 
16 4'h7: oseg = 7'b1000111;  //L  
17 4'h0: oseg = 7'b1000111;  //L 
18 
19 default: oseg =7'b1111111;
20 endcase
21 end
22 endmodule
共8个译码模块(略6)
解法2
1 module part5(CLOCK_50,HEX7,HEX6,HEX5,HEX4,HEX3,HEX2,HEX1,HEX0);
  2     input CLOCK_50;
  3     output reg [6:0] HEX7,HEX6,HEX5,HEX4,HEX3,HEX2,HEX1,HEX0;
  4     
  5     parameter blank=7'b1_111_111,
  6                 H=7'b0_001_001,
  7                 E=7'b0_000_110,
  8                 L=7'b1_000_111,
  9                 O=7'b1_000_000;
 10                 
 11     wire clk_1hz;
 12     wire [3:0] cnt;
 13     
 14     div u0(CLOCK_50,clk_1hz,1'b1);
 15     counter8 u1(clk_1hz,1'b1,cnt);
 16     
 17     always @(cnt)
 18     case(cnt)
 19         4'd0:begin
 20                 HEX7=blank;
 21                 HEX6=blank;
 22                 HEX5=blank;
 23                 HEX4=H;
 24                 HEX3=E;
 25                 HEX2=L;
 26                 HEX1=L;
 27                 HEX0=O;
 28             end
 29         4'd1:begin
 30                 HEX0=blank;
 31                 HEX7=blank;
 32                 HEX6=blank;
 33                 HEX5=H;
 34                 HEX4=E;
 35                 HEX3=L;
 36                 HEX2=L;
 37                 HEX1=O;
 38             end    
 39         4'd2:begin
 40                 HEX1=blank;
 41                 HEX0=blank;
 42                 HEX7=blank;
 43                 HEX6=H;
 44                 HEX5=E;
 45                 HEX4=L;
 46                 HEX3=L;
 47                 HEX2=O;
 48             end    
 49         4'd3:begin
 50                 HEX2=blank;
 51                 HEX1=blank;
 52                 HEX0=blank;
 53                 HEX7=H;
 54                 HEX6=E;
 55                 HEX5=L;
 56                 HEX4=L;
 57                 HEX3=O;
 58             end    
 59         4'd4:begin
 60                 HEX3=blank;
 61                 HEX2=blank;
 62                 HEX1=blank;
 63                 HEX0=H;
 64                 HEX7=E;
 65                 HEX6=L;
 66                 HEX5=L;
 67                 HEX4=O;
 68             end    
 69         4'd5:begin
 70                 HEX4=blank;
 71                 HEX3=blank;
 72                 HEX2=blank;
 73                 HEX1=H;
 74                 HEX0=E;
 75                 HEX7=L;
 76                 HEX6=L;
 77                 HEX5=O;
 78             end    
 79         4'd6:begin
 80                 HEX5=blank;
 81                 HEX4=blank;
 82                 HEX3=blank;
 83                 HEX2=H;
 84                 HEX1=E;
 85                 HEX0=L;
 86                 HEX7=L;
 87                 HEX6=O;
 88             end            
 89         4'd7:begin
 90                 HEX6=blank;
 91                 HEX5=blank;
 92                 HEX4=blank;
 93                 HEX3=H;
 94                 HEX2=E;
 95                 HEX1=L;
 96                 HEX0=L;
 97                 HEX7=O;
 98             end    
 99     endcase
100     
101 endmodule        
102其实还可以利用字型码加1的方法。
Conclusion
Part1 有助于理解计数器的具体实现,Part4是Part5的基础,单个7segment循环显示操作成功,多个
自然不难。:)
Reference
《Using library modules in Verilog Designs 》










