小梅哥课程学习——数码管动态扫描显示的verilog实现(C)

发布时间 2023-03-28 21:20:47作者: 无情的造轮子
  1 //动态数码管扫描,通过这种方式可以节约引脚
  2 //可以使用三八译码器来切换数码管位
  3 //要求每个数码管每20ms都要点亮一次,20/8=2.5ms
  4 //源代码1用的是组合逻辑
  5 module hex8(
  6     clk,
  7     reset_n,
  8     disp_data,
  9     sel,
 10     seg
 11     );
 12     input clk;
 13     input reset_n;
 14     input [31:0] disp_data;
 15     output reg [7:0] sel;
 16     output reg [7:0] seg;
 17     
 18 
 19     reg clk_1k;
 20     reg [14:0]div_cnt;
 21     //设置分频计数时钟
 22     always@(posedge clk or negedge reset_n)
 23     if(!reset_n)
 24         div_cnt <= 0;
 25     else if(div_cnt >= 24999)
 26         div_cnt <= 0;
 27     else
 28         div_cnt <= div_cnt + 1'b1;
 29         //定义1ms的时钟(1khz)
 30     always@(posedge clk or negedge reset_n)
 31     if(!reset_n)
 32         clk_1k <= 0;
 33     else if(div_cnt >= 24999)
 34         clk_1k <= !clk_1k;
 35     //这种门时钟在绝大多数不推荐使用
 36     reg [2:0] num_cnt;
 37     always@(posedge clk_1k or negedge reset_n)
 38     if(!reset_n)
 39         num_cnt <= 0;
 40     else
 41         num_cnt <= num_cnt + 1'b1; 
 42     
 43     //书写3—8译码器
 44     always@(*)begin
 45         case(num_cnt)
 46             0:sel <= 8'b0000_0001;
 47             1:sel <= 8'b0000_0010;
 48             2:sel <= 8'b0000_0100;
 49             3:sel <= 8'b0000_1000;
 50             4:sel <= 8'b0001_0000;
 51             5:sel <= 8'b0010_0000;
 52             6:sel <= 8'b0100_0000;
 53             7:sel <= 8'b1000_0000;
 54         endcase
 55     end
 56    
 57    reg [3:0] dis_tmp;
 58    always@(*)begin
 59         case(num_cnt)
 60             7:dis_tmp <= disp_data[31:28];
 61             6:dis_tmp <= disp_data[27:24];
 62             5:dis_tmp <= disp_data[23:20];
 63             4:dis_tmp <= disp_data[19:16];
 64             3:dis_tmp <= disp_data[15:12];
 65             2:dis_tmp <= disp_data[11:8];
 66             1:dis_tmp <= disp_data[7:4];
 67             0:dis_tmp <= disp_data[3:0];
 68         endcase
 69     end
 70     
 71     always@(*)begin
 72         case(dis_tmp)
 73             0:seg <= 8'hc0;
 74             1:seg <= 8'hf9;
 75             2:seg <= 8'ha4;
 76             3:seg <= 8'hb0;
 77             4:seg <= 8'h99;
 78             5:seg <= 8'h92;
 79             6:seg <= 8'h82;
 80             7:seg <= 8'hf8;
 81             8:seg <= 8'h80;
 82             9:seg <= 8'h90;
 83             4'ha:seg <= 8'h88;
 84             4'hb:seg <= 8'h83;
 85             4'hc:seg <= 8'hc6;
 86             4'hd:seg <= 8'ha1;
 87             4'he:seg <= 8'h86;
 88             4'hf:seg <= 8'h8e;
 89         endcase
 90     end
 91 endmodule
 92 
 93 //源代码2用的是时序逻辑
 94 module hex8_2(
 95     clk,
 96     reset_n,
 97     disp_data,
 98     sel,
 99     seg
100     );
101     input clk;
102     input reset_n;
103     input [31:0] disp_data;
104     output reg [7:0] sel;
105     output reg [7:0] seg;
106     
107 
108     reg clk_1k;
109     reg [14:0]div_cnt;
110     //设置分频计数时钟
111     always@(posedge clk or negedge reset_n)
112     if(!reset_n)
113         div_cnt <= 0;
114     else if(div_cnt >= 49999)
115         div_cnt <= 0;
116     else
117         div_cnt <= div_cnt + 1'b1;
118         //这种门控时钟在绝大多数场合不允许使用
119         //定义1ms的时钟(1khz)
120 //    always@(posedge clk or negedge reset_n)
121 //    if(!reset_n)
122 //        clk_1k <= 0;
123 //    else if(div_cnt >= 24999)
124 //        clk_1k <= !clk_1k;
125     
126     //使能时钟
127     always@(posedge clk or negedge reset_n)
128     if(!reset_n)
129         clk_1k <= 0;
130     else if(div_cnt >= 49999)
131         clk_1k <= 1;
132     else
133         clk_1k <= 0;
134         
135     reg [2:0] num_cnt;
136     always@(posedge clk or negedge reset_n)
137     if(!reset_n)
138         num_cnt <= 0;
139     else if(clk_1k)//这里面使用的就是使能时钟
140         num_cnt <= num_cnt + 1'b1; 
141     
142     //书写3—8译码器
143     always@(posedge clk)begin//将组合逻辑用时序的时钟,结果更加精确。
144         case(num_cnt)
145             0:sel <= 8'b0000_0001;
146             1:sel <= 8'b0000_0010;
147             2:sel <= 8'b0000_0100;
148             3:sel <= 8'b0000_1000;
149             4:sel <= 8'b0001_0000;
150             5:sel <= 8'b0010_0000;
151             6:sel <= 8'b0100_0000;
152             7:sel <= 8'b1000_0000;
153         endcase
154     end
155    
156    reg [3:0] dis_tmp;
157    always@(posedge clk)begin
158         case(num_cnt)
159             7:dis_tmp <= disp_data[31:28];
160             6:dis_tmp <= disp_data[27:24];
161             5:dis_tmp <= disp_data[23:20];
162             4:dis_tmp <= disp_data[19:16];
163             3:dis_tmp <= disp_data[15:12];
164             2:dis_tmp <= disp_data[11:8];
165             1:dis_tmp <= disp_data[7:4];
166             0:dis_tmp <= disp_data[3:0];
167         endcase
168     end
169     
170     always@(posedge clk)begin
171         case(dis_tmp)
172             0:seg <= 8'hc0;
173             1:seg <= 8'hf9;
174             2:seg <= 8'ha4;
175             3:seg <= 8'hb0;
176             4:seg <= 8'h99;
177             5:seg <= 8'h92;
178             6:seg <= 8'h82;
179             7:seg <= 8'hf8;
180             8:seg <= 8'h80;
181             9:seg <= 8'h90;
182             4'ha:seg <= 8'h88;
183             4'hb:seg <= 8'h83;
184             4'hc:seg <= 8'hc6;
185             4'hd:seg <= 8'ha1;
186             4'he:seg <= 8'h86;
187             4'hf:seg <= 8'h8e;
188         endcase
189     end
190 endmodule
191 
192 
193 
194 //仿真文件
195 `timescale 1ns / 1ps
196 module hex8_tb();
197     reg clk;
198     reg reset_n;
199     reg [31:0] disp_data;
200     wire [7:0] sel;
201     wire [7:0] seg;
202     hex8 hex8_inst0(
203     clk,
204     reset_n,
205     disp_data,
206     sel,
207     seg
208     );
209     initial clk = 1;
210     always #10 clk = !clk;
211     
212     initial begin
213         reset_n = 0;
214         disp_data = 32'h00000000;
215         #201;
216         reset_n = 1;
217         #2000;
218         disp_data = 32'h12345678;
219         #10000000;
220         disp_data = 32'h9abcdef0;
221         #10000000;
222         $stop;
223     
224     end
225 endmodule
226 
227 //板级实验所用的测试文件,只有AX735才能班级实验,这个是扩展板
228 
229 module hex8_test(
230     clk,
231     reset_n,
232     sel,
233     seg
234     );
235     input clk;
236     input reset_n;
237     output [7:0] sel;
238     output [7:0] seg;
239     
240     wire [31:0] disp_data;
241     
242     hex8_2 hex8_2_inst0(
243     clk,
244     reset_n,
245     disp_data,
246     sel,
247     seg
248     );
249     assign disp_data = 32'h13579bdf;
250     
251 endmodule
使用门控时钟,将门控时钟直接作为DFF的工作时钟,没有ENA的情况下忽略ENA
0
使用使能时钟的情况,DFF的工作时钟继续使用全局的高质量时钟,而将使能时钟作为DFF的使能信号使用。
2023-03-28 21:10:13