官方论坛
官方淘宝
官方博客
微信公众号
点击联系吴工 点击联系周老师

【案例】fpga万年历设计

发布时间:2021-06-25   作者:admin 浏览量:

案例编号:001600000070

1.功能概述

万年历是记录一定时间范围内的年历,其名称只是一种象征,表示时间跨度大。由于其功能非常常用,且极为方便人们查询使用,因此广泛应用于钟表、历书出版物电子产品电脑软件和手机应用等行业中。

与传统计时工具如钟表日历等相比,数字万年历具备精确度高、成本低廉、运行稳定、功能多样等众多优点,因此国内外许多设计人员先后进行了相关设计开发。其中,基于FPGA开发除设计简便、开发成本低、电路简洁等,更具备功能设计灵活方面的优势。只需要在软件上做简单修改即可添加不同功能,如闹钟、阴阳历对照等。

FPGA设计中,数字万年历属于小规模集成电路。从原理上来讲,是典型的数字电路,包括组合逻辑电路和时序电路。在本案例中具体功能要求如下:

本项目要求设计一个电子万年历,具体功能要求如下:

1. 上板复位后从元年1月1号开始计数,为方便上板调试,将一天的时间压缩为1秒;

2. 按键用于设置日历,按下按键0进入设置状态,再次按下按键0退出设置状态;

3. 按键1用来选择想要设置的年月日的各个位;

4. 按键2在设置状态时进行计数设置,每按一次数码管显示数字加1;

5. 平年365天(52周+1天),闰年366天(52周+2天),其中平年2月28天,闰年2月29天。

6. 闰年:每400年整一闰,或每4年且不为百年的一闰。即能被400整除,或不能被100整除但能被4整除的年份为闰年。

2.设计思路

首先根据所需要的功能,列出工程顶层的输入输出信号列表。

信号列表如下:

至简设计法

我们可以把工程划分成三个模块,分别是万年历计数模块、按键模块和数码管显示模块。

至简设计法

1. 计数模块——实现的是万年历计数功能,为方便观看,将一天时间设置为1秒;日计数器dat_cnt、月份计数器mon_cnt_h、mon_cnt_1、mon_2_h、mon_2_1分别为大月小月以及平年闰年的2月计数器、年份计数器yea_one、yea_ten、yea_hun、yea_tho分别为年份的个十百千位,由yea_cnt_tol <= yea_cnt1000 + yea_cnt100 + yea_cnt10 + yea_one得到年份。本模块还自动计算当年是否是平闰年。

信号列表如下:

至简设计法


2. 按键模块——4x4矩阵键盘,实现了矩阵键盘的扫描并使用按键消抖功能。

信号列表如下:

至简设计法

3. 数码管模块——实现将年月日的信息显示在数码管上。

信号列表如下:

至简设计法

3.程序设计

顶层模块

 1 module calendar_top(
 2     clk    ,
 3     rst_n  ,
 4     key_col,
 5     key_row,
 6     segment,
 7     seg_sel
 8     );
 9
10     parameter   SEG_NUM =     8    ;
11     parameter   SEG_W   =     8    ;
12     parameter   TIME_1S =50_000_000;
13
14     input                  clk     ;
15     input                  rst_n   ;
16     input  [3:0]           key_col ;
17
18     output [SEG_W-1:0]     segment ;
19     output [SEG_NUM-1:0]   seg_sel ;
20     output [3:0]           key_row ;
21
22     wire   [SEG_W-1:0]     segment ;
23     wire   [SEG_NUM-1:0]   seg_sel ;
24     
25     wire   [3:0]           key_num ;
26     wire                   key_vld ;
27     wire   [4*SEG_NUM-1:0] data_out;
28     wire   [SEG_NUM-1:0]   din_vld ;
29
30     assign din_vld = 8'b11111111   ;
31
32     key_scan      u_key_scan(
33                              .clk    (clk    )           ,
34                              .rst_n  (rst_n  )           ,
35                              .key_col(key_col)           ,
36                              .key_row(key_row)           ,
37                              .key_out(key_num)           ,
38                              .key_vld(key_vld)  
39                             );
40
41     seg_display   u_seg_display(
42                              .clk     (clk     )         ,
43                              .rst_n   (rst_n   )         ,
44                              .din     (data_out)         ,
45                              .din_vld (din_vld )         ,      
46                              .segment (segment )         ,
47                              .seg_sel (seg_sel )
48                         );
49
50     counter #(.TIME_1S(TIME_1S))    u_counter(
51                             .clk          (clk          ),
52                             .rst_n        (rst_n        ),
53                             .key_vld      (key_vld      ),
54                             .key_num      (key_num      ),
55                             .dout         (data_out     )
56                          );
57 endmodule
58

万年历计数模块

  1 module counter(
  2               clk     ,
  3               rst_n   ,
  4               key_vld ,
  5               key_num ,
  6               dout    
  7     );
  8
  9     
 10     parameter      DATA_W    =         32;
 11     parameter      TIME_1S   = 50_000_000;
 12
 13     input               clk              ;
 14     input               rst_n            ;
 15     input               key_vld          ;
 16     input[3:0]          key_num          ;
 17
 18     output              dout             ;
 19
 20     reg   [DATA_W-1:0]  dout             ;
 21
 22     wire                start_set        ;
 23     wire                stop_set         ;
 24     reg                 flag_set         ;
 25     reg  [25:0]         clk_cnt          ;
 26     wire                clk_cnt_add      ;
 27     wire                clk_cnt_end      ;
 28     reg  [4 :0]         dat_cnt          ;
 29     wire [4 :0]         dat_cnt_tmp      ;
 30     wire                dat_cnt_add      ;
 31     wire                dat_cnt_end      ;
 32     wire [3 :0]         dat_one          ;
 33     wire [3 :0]         dat_ten          ; 
 34     wire                mon_cnt_h        ;
 35     wire                mon_cnt_l        ;
 36     wire                mon_2_l          ;
 37     wire                mon_2_h          ;
 38     reg  [3 :0]         mon_cnt          ;
 39     wire [3 :0]         mon_cnt_tmp      ;
 40     wire                mon_cnt_add      ;
 41     wire                mon_cnt_end      ;
 42     wire [3 :0]         mon_one          ;
 43     wire [3 :0]         mon_ten          ;
 44     reg  [3 :0]         yea_one          ;
 45     wire                yea_one_add      ;
 46     wire                yea_one_end      ;
 47     reg  [3 :0]         yea_ten          ;
 48     wire                yea_ten_add      ;
 49     wire                yea_ten_end      ;
 50     reg  [3 :0]         yea_hun          ;
 51     wire                yea_hun_add      ;
 52     wire                yea_hun_end      ;
 53     reg  [3 :0]         yea_tho          ;
 54     wire                yea_tho_add      ;
 55     wire                yea_tho_end      ;
 56     reg  [13:0]         yea_cnt1000      ;
 57     reg  [10:0]         yea_cnt100       ;
 58     reg  [7 :0]         yea_cnt10        ;
 59     reg  [13:0]         yea_cnt_tol      ;
 60     reg  [6 :0]         yea_cnt_tol_100  ;
 61     wire [13:0]         yea_mult4        ;
 62     wire [13:0]         yea_mult100_tmp  ;
 63     reg  [13:0]         yea_mult100      ;
 64     wire [13:0]         yea_cnt400       ;
 65     reg  [13:0]         yea_mult400      ;
 66     wire                yea_leap         ;
 67     reg  [2 :0]         set_cnt          ;
 68     wire                set_cnt_add      ;
 69     wire                set_cnt_end      ;
 70     wire                set_dat          ;
 71     wire                set_mon          ;
 72     wire                set_yea_one      ;
 73     wire                set_yea_ten      ;
 74     wire                set_yea_hun      ;
 75     wire                set_yea_tho      ;
 76     reg  [4 :0]         set_num          ;
 77     wire                set_num_add      ;
 78     wire                set_num_end      ;
 79     reg  [4 :0]         x                ;
 80     
 81   
 82     always  @(posedge clk or negedge rst_n)begin
 83         if(rst_n==1'b0)begin
 84             flag_set <= 0;
 85         end
 86         else if(start_set)begin
 87             flag_set <= 1;
 88         end
 89         else if(stop_set)begin
 90             flag_set <= 0;
 91         end
 92     end
 93     assign start_set = flag_set==0 && key_vld==1 && key_num==0;
 94     assign stop_set  = flag_set==1 && key_vld==1 && key_num==0;
 95
 96     always @(posedge clk or negedge rst_n)begin
 97         if (!rst_n)begin
 98             clk_cnt <= 0;
 99         end
100         else if(clk_cnt_add)begin
101             if(clk_cnt_end)
102                 clk_cnt <= 0;
103             else
104                 clk_cnt <= clk_cnt + 1;
105         end
106     end
107     assign clk_cnt_add = flag_set == 0;      
108     assign clk_cnt_end = clk_cnt_add && clk_cnt == TIME_1S - 1;
109
110     always @(posedge clk or negedge rst_n)begin
111         if(!rst_n)begin
112             dat_cnt <= 0;
113         end
114         else if(dat_cnt_add)begin
115             if(dat_cnt_end)
116                 dat_cnt <= 0;
117             else
118                 dat_cnt <= dat_cnt + 1;
119         end
120         else if(set_dat)begin
121             dat_cnt <= set_num;
122         end
123     end
124     assign dat_cnt_add = clk_cnt_end;    
125     assign dat_cnt_end = dat_cnt_add && dat_cnt == x - 1;
126     
127     assign dat_cnt_tmp = dat_cnt + 1;
128
129     assign dat_ten = dat_cnt_tmp/10;
130     assign dat_one = dat_cnt_tmp%10;
131     
132     always @(posedge clk or negedge rst_n)begin
133         if(!rst_n)begin
134             mon_cnt <= 0;
135         end
136         else if(mon_cnt_add)begin
137             if(mon_cnt_end)
138                 mon_cnt <= 0;
139             else
140                 mon_cnt <= mon_cnt + 1;
141         end
142         else if(set_mon)begin
143             mon_cnt <= set_num;
144         end
145     end
146     assign mon_cnt_add = dat_cnt_end;      
147     assign mon_cnt_end = mon_cnt_add && mon_cnt == 12 - 1;      
148
149     assign mon_cnt_tmp = mon_cnt + 1;
150
151     assign mon_ten = mon_cnt_tmp/10;
152     assign mon_one = mon_cnt_tmp%10;
153     
154     always  @(*)begin
155         if(mon_cnt_h)
156             x = 31;
157         else if(mon_cnt_l)
158             x = 30;
159         else if(mon_2_h)
160             x = 29;
161         else 
162             x = 28;
163     end
164     assign mon_cnt_h = mon_cnt_tmp==1||mon_cnt_tmp==3||mon_cnt_tmp==5||mon_cnt_tmp==7||mon_cnt_tmp==8||mon_cnt_tmp==10||mon_cnt_tmp==12;
165     assign mon_cnt_l = mon_cnt_tmp==4||mon_cnt_tmp==6||mon_cnt_tmp==9||mon_cnt_tmp==11;
166     assign mon_2_h   = yea_leap==1   &&mon_cnt_tmp==2;
167     assign mon_2_l   = yea_leap==0   &&mon_cnt_tmp==2;
168
169     always @(posedge clk or negedge rst_n)begin
170         if(!rst_n)begin
171             yea_one <= 0;
172         end
173         else if(yea_one_add)begin
174             if(yea_one_end)
175                 yea_one <= 0;
176             else
177                 yea_one <= yea_one + 1;
178         end
179         else if(set_yea_one)begin
180             yea_one <= set_num;
181         end
182     end
183     assign yea_one_add = mon_cnt_end;      
184     assign yea_one_end = yea_one_add && yea_one == 10 - 1;    
185
186   
187     always @(posedge clk or negedge rst_n)begin
188         if(!rst_n)begin
189             yea_ten <= 0;
190         end
191         else if(yea_ten_add)begin
192             if(yea_ten_end)
193                 yea_ten <= 0;
194             else
195                 yea_ten <= yea_ten + 1;
196         end
197         else if(set_yea_ten)begin
198             yea_ten <= set_num;
199         end
200     end
201     assign yea_ten_add = yea_one_end;      
202     assign yea_ten_end = yea_ten_add && yea_ten == 10 - 1;      
203
204   
205     always @(posedge clk or negedge rst_n)begin
206         if(!rst_n)begin
207             yea_hun <= 0;
208         end
209         else if(yea_hun_add)begin
210             if(yea_hun_end)
211                 yea_hun <= 0;
212             else
213                 yea_hun <= yea_hun + 1;
214         end
215         else if(set_yea_hun)begin
216             yea_hun <= set_num;
217         end
218     end
219     assign yea_hun_add = yea_ten_end;      
220     assign yea_hun_end = yea_hun_add && yea_hun == 10 - 1;      
221
222     always @(posedge clk or negedge rst_n)begin
223         if(!rst_n)begin
224             yea_tho <= 0;
225         end
226         else if(yea_tho_add)begin
227             if(yea_tho_end)
228                 yea_tho <= 0;
229             else
230                 yea_tho <= yea_tho + 1;
231         end
232         else if(set_yea_tho)begin
233             yea_tho <= set_num;
234         end
235     end
236     assign yea_tho_add = yea_hun_end;      
237     assign yea_tho_end = yea_tho_add && yea_tho == 10 - 1;      
238
239     always  @(posedge clk or negedge rst_n)begin
240         if(rst_n==1'b0)begin
241             yea_cnt1000 <= 0;
242         end
243         else begin
244             yea_cnt1000 <= yea_tho*1000; 
245         end
246     end
247
248     always  @(posedge clk or negedge rst_n)begin
249         if(rst_n==1'b0)begin
250             yea_cnt100 <= 0;
251         end
252         else begin
253             yea_cnt100 <= yea_hun*100;
254         end
255     end
256
257     always  @(posedge clk or negedge rst_n)begin
258         if(rst_n==1'b0)begin
259             yea_cnt10 <= 0;
260         end
261         else begin
262             yea_cnt10 <= yea_ten*10;
263         end
264     end
265     
266     always  @(posedge clk or negedge rst_n)begin
267         if(rst_n==1'b0)begin
268             yea_cnt_tol <= 0;
269         end
270         else begin
271             yea_cnt_tol <= yea_cnt1000 + yea_cnt100 + yea_cnt10 + yea_one;
272         end
273     end
274
275     always  @(posedge clk or negedge rst_n)begin
276         if(rst_n==1'b0)begin
277             yea_cnt_tol_100 <= 0;
278         end
279         else begin
280             yea_cnt_tol_100 <=  yea_tho*10+ yea_hun;
281         end
282     end
283
284     assign yea_mult4       = {yea_cnt_tol>>2,2'b00};  
285     assign yea_mult100_tmp = yea_cnt1000 + yea_cnt100;
286     assign yea_cnt400      = {yea_cnt_tol_100>>2,2'b00};
287
288     always  @(posedge clk or negedge rst_n)begin
289         if(rst_n==1'b0)begin
290             yea_mult100 <= 0;
291         end
292         else begin
293             yea_mult100 <= yea_mult100_tmp;
294         end
295     end
296
297     always  @(posedge clk or negedge rst_n)begin
298         if(rst_n==1'b0)begin
299             yea_mult400 <= 0;
300         end
301         else begin
302             yea_mult400 <= yea_cnt400*100;
303         end
304     end
305       
306     assign yea_leap = (yea_cnt_tol==yea_mult400)||(yea_cnt_tol==yea_mult4&&yea_cnt_tol!=yea_mult100);
307     
308     always @(posedge clk or negedge rst_n)begin
309         if(!rst_n)begin
310             set_cnt <= 0;
311         end
312         else if(set_cnt_add)begin
313             if(set_cnt_end)
314                 set_cnt <= 0;
315             else
316                 set_cnt <= set_cnt + 1;
317         end
318         else if(stop_set)begin
319             set_cnt <= 0;
320         end
321     end
322     assign set_cnt_add = flag_set == 1 && key_vld == 1 && key_num == 1;      
323     assign set_cnt_end = set_cnt_add && set_cnt == 8 - 1              ;      
324
325     assign set_dat     = set_num_add && set_cnt == 1-1                ;
326     assign set_mon     = set_num_add && set_cnt == 3-1                ;
327     assign set_yea_one = set_num_add && set_cnt == 5-1                ;
328     assign set_yea_ten = set_num_add && set_cnt == 6-1                ;
329     assign set_yea_hun = set_num_add && set_cnt == 7-1                ;
330     assign set_yea_tho = set_num_add && set_cnt == 8-1                ;
331
332     reg [4:0]    y_temp                                               ;
333     wire[4:0]    y_temp2                                              ;
334
335     assign set_num_add = flag_set == 1 && key_vld == 1 && key_num == 2;    
336
337     always  @(*)begin
338         if(set_dat)
339             y_temp = dat_cnt;
340         else if(set_mon)
341             y_temp = mon_cnt;
342         else if(set_yea_one)
343             y_temp = yea_one;
344         else if(set_yea_ten)
345             y_temp = yea_ten;
346         else if(set_yea_hun)
347             y_temp = yea_hun;
348         else  
349             y_temp = yea_tho;
350
351     end
352
353     assign y_temp2 = y_temp + 1; 
354
355     always  @(*)begin
356         if(set_dat)begin
357             if(y_temp2>=x)
358                 set_num = 0;
359             else
360                 set_num = y_temp2;
361         end
362         else if(set_num)begin
363             if(y_temp2>=12)
364                 set_num = 0;
365             else
366                 set_num = y_temp2;
367         end
368         else begin
369             if(y_temp2>9)
370                 set_num = 0;
371             else
372                 set_num = y_temp2;
373         end
374     end
375
376     always  @(posedge clk or negedge rst_n)begin
377         if(rst_n==1'b0)begin
378             dout <= 0;
379         end
380         else begin
381             dout <= {yea_tho,yea_hun,yea_ten,yea_one,mon_ten,mon_one,dat_ten,dat_one};
382         end
383     end
384
385 endmodule
386

矩阵键盘扫描模块

  1 module  key_scan(
  2                  clk    ,
  3                  rst_n  ,
  4                  key_col,
  5                  key_row,
  6                  key_out,
  7                  key_vld  
  8                );
  9
 10
 11     parameter      KEY_W    =   4 ;
 12     parameter      COL      =   0 ;
 13     parameter      ROW      =   1 ;
 14     parameter      DLY      =   2 ;
 15     parameter      FIN      =   3 ;
 16     parameter      COL_CNT  =   16;
 17     parameter      TIME_20MS=   1000000;
 18
 19     input               clk    ;
 20     input               rst_n  ;
 21     input  [3:0]        key_col;
 22
 23     output              key_vld;
 24     output[3:0]         key_out;
 25     output[KEY_W-1:0]   key_row;
 26
 27     reg   [3:0]         key_out;
 28     reg   [KEY_W-1:0]   key_row;
 29     reg                 key_vld;
 30
 31     reg   [ 3:0]        key_col_ff0   ;
 32     reg   [ 3:0]        key_col_ff1   ;
 33     reg   [ 1:0]        key_col_get   ;
 34     reg                 shake_flag    ;
 35     reg                 shake_flag_ff0;
 36     reg   [ 3:0]        state_c       ;
 37     reg   [19:0]        shake_cnt     ;
 38     reg   [ 3:0]        state_n       ;
 39     reg   [ 1:0]        row_index     ;
 40     reg   [15:0]        row_cnt       ;
 41     reg   [ 2:0]        x             ;
 42
 43
 44     always  @(posedge clk or negedge rst_n)begin
 45         if(rst_n==1'b0)begin
 46             key_col_ff0 <= 4'b1111;
 47             key_col_ff1 <= 4'b1111;
 48         end
 49         else begin
 50             key_col_ff0 <= key_col    ;
 51             key_col_ff1 <= key_col_ff0;
 52         end
 53     end
 54     
 55     always  @(posedge clk or negedge rst_n)begin
 56         if(rst_n==1'b0)begin
 57             shake_cnt <= 0;
 58         end
 59         else if(add_shake_cnt)begin
 60             if(end_shake_cnt)
 61                 shake_cnt <= 0;
 62             else
 63                 shake_cnt <= shake_cnt + 1;
 64         end
 65         else begin
 66             shake_cnt <= 0;
 67         end
 68     end
 69     assign  add_shake_cnt = key_col_ff1!=4'hf && shake_flag==0;
 70     assign  end_shake_cnt = add_shake_cnt && shake_cnt==TIME_20MS-1;
 71     
 72     always  @(posedge clk or negedge rst_n)begin
 73         if(rst_n==1'b0)begin
 74             shake_flag <= 0;
 75         end
 76         else if(end_shake_cnt) begin
 77             shake_flag <= 1'b1;
 78         end
 79         else if(key_col_ff1==4'hf) begin
 80             shake_flag <= 1'b0;
 81         end
 82     end
 83     
 84     always  @(posedge clk or negedge rst_n)begin
 85         if(rst_n==1'b0)begin
 86             state_c <= COL;
 87         end
 88         else begin
 89             state_c <= state_n;
 90         end
 91     end
 92       
 93     always@(*)begin
 94         case(state_c)
 95             COL:begin
 96                 if(col2row_start)begin
 97                     state_n = ROW;
 98                 end
 99                 else begin
100                     state_n = state_c;
101                 end
102             end
103             ROW:begin
104                 if(row2dly_start)begin
105                     state_n = DLY;
106                 end
107                 else begin
108                     state_n = state_c;
109                 end
110             end
111             DLY:begin
112                 if(dly2fin_start)begin
113                     state_n = FIN;
114                 end
115                 else begin
116                     state_n = state_c;
117                 end
118             end
119             FIN:begin
120                 if(fin2col_start)begin
121                     state_n = COL;
122                 end
123                 else begin
124                     state_n = state_c;
125                 end
126             end
127             default:begin
128                 state_n = COL;
129             end
130         endcase
131     end
132     
133     assign  col2row_start = state_c==COL && end_shake_cnt;
134     assign  row2dly_start = state_c==ROW && end_row_index; 
135     assign  dly2fin_start = state_c==DLY && end_row_index; 
136     assign  fin2col_start = state_c==FIN && key_col_ff1==4'hf;
137   
138     always  @(posedge clk or negedge rst_n)begin
139         if(rst_n==1'b0)begin
140             key_row <= 4'b0;
141         end
142         else if(state_c==ROW)begin
143             key_row <= ~(1'b1 << row_index);
144         end
145         else begin
146             key_row <= 4'b0;
147         end
148     end
149     
150     always  @(posedge clk or negedge rst_n)begin
151         if(rst_n==1'b0)begin
152             row_cnt <= 0;
153         end
154         else if(add_row_cnt) begin
155             if(end_row_cnt)
156                 row_cnt <= 0;
157             else
158                 row_cnt <= row_cnt + 1;
159         end
160     end
161     assign add_row_cnt = state_c==ROW || state_c==DLY;
162     assign end_row_cnt = add_row_cnt && row_cnt==COL_CNT-1;
163     
164     always  @(posedge clk or negedge rst_n)begin
165         if(rst_n==1'b0)begin
166             row_index <= 0;
167         end
168         else if(add_row_index) begin
169             if(end_row_index)
170                 row_index <= 0;
171             else
172                 row_index <= row_index + 1;
173         end
174     end
175     assign add_row_index = end_row_cnt;
176     assign end_row_index = add_row_index && row_index==x-1;
177
178     always  @(*)begin
179         if(state_c==ROW)
180             x = 4;
181         else
182             x = 1;
183     end
184     
185     always  @(posedge clk or negedge rst_n)begin
186         if(rst_n==1'b0)begin
187             key_col_get <= 0;
188         end
189         else if(col2row_start) begin
190             if(key_col_ff1==4'b1110)
191                 key_col_get <= 0;
192             else if(key_col_ff1==4'b1101)
193                 key_col_get <= 1;
194             else if(key_col_ff1==4'b1011)
195                 key_col_get <= 2;
196             else 
197                 key_col_get <= 3;
198         end
199     end
200       
201     always  @(posedge clk or negedge rst_n)begin
202         if(rst_n==1'b0)begin
203             key_out <= 0;
204         end
205         else if(state_c==ROW && end_row_cnt)begin
206             key_out <= {row_index,key_col_get};
207         end
208         else begin
209             key_out <= 0;
210         end
211     end
212     
213     always  @(posedge clk or negedge rst_n)begin
214         if(rst_n==1'b0)begin
215             key_vld <= 1'b0;
216         end
217         else if(state_c==ROW && end_row_cnt && key_col_ff1[key_col_get]==1'b0)begin
218             key_vld <= 1'b1;
219         end
220         else begin
221             key_vld <= 1'b0;
222         end
223     end
224     
225 endmodule
226

数码管显示模块

  1 module seg_display(
  2     clk    ,
  3     rst_n  ,
  4     din    ,
  5     din_vld,
  6     segment,
  7     seg_sel
  8     );
  9
 10     `include "clogb2.v"
 11     
 12     parameter      SEG_W     =        8          ;
 13     parameter      SEG_NUM   =        8          ;
 14     parameter      DIS_NUM   =       10          ;
 15     parameter      TIME_20US =     1000          ;
 16     parameter      NUM_0 = 8'b1100_0000          ;
 17     parameter      NUM_1 = 8'b1111_1001          ;
 18     parameter      NUM_2 = 8'b1010_0100          ;
 19     parameter      NUM_3 = 8'b1011_0000          ;
 20     parameter      NUM_4 = 8'b1001_1001          ;
 21     parameter      NUM_5 = 8'b1001_0010          ;
 22     parameter      NUM_6 = 8'b1000_0010          ;
 23     parameter      NUM_7 = 8'b1111_1000          ;
 24     parameter      NUM_8 = 8'b1000_0000          ;
 25     parameter      NUM_9 = 8'b1001_0000          ;
 26     parameter      SEG_NUM_C  = clogb2(SEG_NUM)-1;
 27
 28     
 29     input                 clk      ;
 30     input                 rst_n    ;
 31     input[4*SEG_NUM-1:0]  din      ;
 32     input[SEG_NUM-1:0]    din_vld  ;
 33   
 34     output                segment  ;
 35     output                seg_sel  ;
 36     
 37     reg   [SEG_W-1:0]     segment  ;
 38     reg   [SEG_NUM-1:0]   seg_sel  ;
 39
 40     wire  [3:0]           seg_tmp  ;
 41     reg   [4*SEG_NUM-1:0] din_ff0  ;
 42     reg   [9:0]           clk_cnt  ;
 43     reg   [2:0]           sel_cnt  ;
 44     integer               i        ;  
 45     
 46     wire                clk_cnt_add;
 47     wire                clk_cnt_end;
 48     wire                sel_cnt_add;
 49     wire                sel_cnt_end;
 50
 51     always  @(posedge clk or negedge rst_n)begin
 52         if(rst_n==1'b0)begin
 53             segment <= NUM_0;
 54         end
 55         else begin
 56             case(seg_tmp)
 57                 4'd0 : segment <= NUM_0   ;
 58                 4'd1 : segment <= NUM_1   ;
 59                 4'd2 : segment <= NUM_2   ;
 60                 4'd3 : segment <= NUM_3   ;
 61                 4'd4 : segment <= NUM_4   ;
 62                 4'd5 : segment <= NUM_5   ;
 63                 4'd6 : segment <= NUM_6   ;
 64                 4'd7 : segment <= NUM_7   ;
 65                 4'd8 : segment <= NUM_8   ;
 66                 4'd9 : segment <= NUM_9   ;
 67                 default : segment <= NUM_0;
 68             endcase
 69         end
 70     end
 71
 72     assign   seg_tmp = din_ff0[(sel_cnt+1)*4-1 -:4];
 73
 74     always  @(posedge clk or negedge rst_n)begin
 75         if(rst_n==1'b0)begin
 76             din_ff0 <= 0;
 77         end
 78         else begin
 79             for(i=0;i<SEG_NUM;i=i+1)begin
 80                 if(din_vld[i]==1'b1)begin
 81                     din_ff0[(i+1)*4-1 -:4] <= din[(i+1)*4-1 -:4];
 82                 end
 83                 else begin
 84                     din_ff0[(i+1)*4-1 -:4] <= din_ff0[(i+1)*4-1 -:4];
 85                 end
 86             end
 87         end
 88     end 
 89     
 90     always @(posedge clk or negedge rst_n)begin
 91         if (!rst_n)begin
 92             clk_cnt <= 0;
 93         end
 94         else if(clk_cnt_add)begin
 95             if(clk_cnt_end)
 96                 clk_cnt <= 0;
 97             else
 98                 clk_cnt <= clk_cnt + 1;
 99         end
100     end
101     assign clk_cnt_add = 1;      
102     assign clk_cnt_end = clk_cnt_add && clk_cnt == TIME_20US - 1;          
103
104     always @(posedge clk or negedge rst_n)begin
105         if (!rst_n)begin
106             sel_cnt <= 0;
107         end
108         else if(sel_cnt_add)begin
109             if(sel_cnt_end)
110                 sel_cnt <= 0;
111             else
112                 sel_cnt <= sel_cnt + 1;
113         end
114     end
115     assign sel_cnt_add = clk_cnt_end;    
116     assign sel_cnt_end = sel_cnt_add && sel_cnt == SEG_NUM - 1;
117
118     always  @(posedge clk or negedge rst_n)begin
119         if(rst_n==1'b0)begin
120             seg_sel <= {SEG_NUM{1'b1}};
121         end
122         else begin
123             seg_sel <= ~(1'b1 << sel_cnt);
124         end
125     end
126
127 endmodule
128

技术交流群:54453837 

明德扬官网:old.mdy-edu.com

   拓展阅读