Black gold AX301 development board learning (3)-dynamic digital tube clock experiment

The use of the development board is AX301, and the learning materials can be found in another article of mine. The link is as follows: https://blog.csdn.net/qq_24213087/article/details/108238682 Insert picture description here
1. Introduction
to the dynamic digital tube In the previous article, we talked about the principle diagram of the digital tube and the main methods of static display in detail. Let's review the schematic diagram of our use of digital tubes.
Insert picture description here
The display of the six-in-one digital tube is a dynamic display. Due to the persistence of human vision and the afterglow effect of light-emitting diodes, the principle of this roundabout effect is the same as the effect of watching movies. The screening of a movie is just one picture after another. As long as the rate of more than 20 frames per second is guaranteed, our brain will leave a reaction time. This time is brought about by the afterglow effect. So the movies we see are dynamic and continuous. Therefore, when the dynamic scanning time of the digital tube is greater than 50HZ, although the digital tubes are not actually lit at the same time, it gives the impression that a set of stable display data will not flicker. Here is a poster of my favorite movie.
Insert picture description here

2. Clock experiment
Next, let's get back to the subject, we complete the display of the dynamic digital tube through a clock experiment. First of all, the AX301 we use is a 50MHz crystal. The minimum time delay is 20ns. So we need to divide our clock to a 1ms clock.

/* time   : 2020.9.12                                                                      
   主要功能 : 实现时钟分频功能,分别实现1ms , 20ms        
 端口定义 :  clock:  分频后的时钟
     reset:  复位信号
     clk_div1: 分频时钟,1ms
     clk_div2:  分频时钟,20ms
=============================================================================================*/
module time_div(clock, reset, clk_div1, clk_div2);
input clock, reset;
output clk_div1, clk_div2;
reg clk_div1, clk_div2;
reg [15:0] cnt1;
reg [19:0] cnt2; 
parameter MAX_TIME1 = 25_000;
parameter MAX_TIME2 = 1_000_000;
//1ms
always@(posedge clock or negedge reset)begin
 if(!reset)
 begin
  clk_div1 = 1'b0;
  cnt1 = 16'd0;
 end
 else if(cnt1 < MAX_TIME1)
 begin
  cnt1 = cnt1 + 1'd1;
 end
 else if(cnt1 == MAX_TIME1)
 begin
  cnt1 = 16'd0;
  clk_div1 = ~clk_div1;
 end
 else
 begin
  cnt1 = cnt1;
 end
end
//20ms
always@(posedge clock or negedge reset)begin
 if(!reset)
 begin
  clk_div2 = 1'b0;
  cnt2 = 20'd0;
 end
 else if(cnt2 < MAX_TIME2)
 begin
  cnt2 = cnt2 + 1'd1;
 end
 else if(cnt2 == MAX_TIME2)
 begin
  cnt2 = 20'd0;
  clk_div2 = ~clk_div2;
 end
 else
 begin
  cnt2 = cnt2;
 end
end
endmodule

After the clock division is ok, we continue to consider the counting problem of clock design. The count at the ms level is the normal decimal system, but for the second level and the grading, it is the 60 system. Therefore, we need to classify the count value per millisecond.

/* time   : 2020.9.12                                                                      
   主要功能 : 实现时钟计时功能,计时精度1ms          
 端口定义 :  clock:  分频后的时钟
     reset:  复位信号
     time_sum: 当前时间
=============================================================================================*/
module time_ms (clock, reset, time_sum);
input clock,reset;
output [23:0] time_sum;
reg [23:0] time_sum ;
reg [19:0] time_MS;
parameter MAX_TIMER = 600_000;
//计算当前时间存入time_MS
always@(posedge clock or negedge reset)begin
 if(!reset)
 begin
  time_MS = 20'd0;
 end
 else if(time_MS < MAX_TIMER)
 begin
  time_MS = time_MS + 1'd1; 
 end
 else
 begin
  time_MS = 20'd0;
 end
end
//将time_MS转变为 分_秒_毫秒 的形式存入time_sum
always@(time_MS)begin
 time_sum[23:20] = time_MS/60000;
 time_sum[19:16] = ((time_MS/1000)%60)/10;
 time_sum[15:12] = ((time_MS/1000)%60)%10;
 time_sum[11:8] = (time_MS%1000)/100;
 time_sum[7:4] = ((time_MS%1000)%100)/10;
 time_sum[3:0] = ((time_MS%1000)%100)%10;
end
endmodule

Then comes the most important part of this experiment, the screen scanning function, which realizes the control of the position selection.

/* time   : 2020.9.12                                                                      
   主要功能 : 实现位选扫屏功能,计时精度1ms,位选信号确定后,并给出当前应显示的段选信号          
 端口定义 :  clock:  分频后的时钟
     reset:  复位信号
     sel:   位选信号
     time_sum: 当前时间
     cnt:   位选标志
=============================================================================================*/
module scan(clock, reset, sel, time_sum, ctl_seg, dot);
input clock, reset;
input [23:0] time_sum;
output [5:0] sel; 
output [3:0] ctl_seg;
output dot;
reg [3:0] ctl_seg;
reg [5:0] sel = 6'b0;
reg dot;
reg [2:0] cnt = 0;
//段选
always@(posedge clock)begin
 if(cnt < 3'd5)
 begin
  cnt <= cnt + 1;
 end
 else
 begin
  cnt <= 0;
 end
end
always@(posedge clock)begin
 case (cnt)
  3'd0:  begin
      sel = 6'b111_110;
      ctl_seg = time_sum[3:0];
      dot = 1;
     end
  3'd1:  begin
      sel = 6'b111_101;
      ctl_seg = time_sum[7:4];
      dot = 1;
     end    
  3'd2:  begin
      sel = 6'b111_011;
      ctl_seg = time_sum[11:8];
      dot = 1;
     end
  3'd3:  begin
      sel = 6'b110_111;
      ctl_seg = time_sum[15:12];
      dot = 0;
     end
  3'd4:  begin
      sel = 6'b101_111;
      ctl_seg = time_sum[19:16];
      dot = 1;
     end
  3'd5:  begin
      sel = 6'b011_111;
      ctl_seg = time_sum[23:20];
      dot = 0;
     end
  default: begin
      sel = sel;
      ctl_seg = ctl_seg;
      dot = 1;
     end
 endcase
end
endmodule

The last step is to perform segment selection control on the characters displayed by each digital tube to realize the current number display

/* time   :2020.9.12                                                                      
   主要功能 :实现段选功能         
 端口定义 :  clock:  分频后的时钟
     reset:  复位信号
     seg_led:  段选信号
     cnt:   位选后当前应显示的数值标志
=============================================================================================*/
module seg_led_show(clock, reset, seg_led, ctl_seg, dot);
input clock, reset;
input [3:0] ctl_seg;
input dot;
output [7:0] seg_led;
reg [7:0] seg_led = 8'b1111_1111;
always@(ctl_seg)begin
 case (ctl_seg)
  8'd0:   seg_led = {
    
    dot,7'b1000000};  //0
  8'd1:   seg_led = {
    
    dot,7'b1111001};  //1
  8'd2:   seg_led = {
    
    dot,7'b0100100};  //2
  8'd3:   seg_led = {
    
    dot,7'b0110000};  //3
  8'd4:   seg_led = {
    
    dot,7'b0011001};  //4
  8'd5:   seg_led = {
    
    dot,7'b0010010};  //5
  8'd6:   seg_led = {
    
    dot,7'b0000010};  //6
  8'd7:   seg_led = {
    
    dot,7'b1111000};  //7
  8'd8:   seg_led = {
    
    dot,7'b0000000};  //8
  8'd9:   seg_led = {
    
    dot,7'b0010000};  //9
  default: seg_led = 8'b1111_1111;
 endcase
end
endmodule

The last is our top-level code, which realizes the connection between the various modules

/* time   : 2020.9.12                                                                      
   主要功能 : 实现时钟功能,六位数码管,依次为分、秒、毫秒。例如1.20.123,为1分钟20秒123毫秒          
 端口定义 : clock:  分频后的时钟
     reset:  复位信号
     seg_led:  段选信号
     sel:   位选信号                                                                              
=============================================================================================*/
module top(clock, reset, sel, seg_led);
input clock, reset;
output [5:0] sel;
output [7:0] seg_led; 
//reg [5:0] sel;
//reg [7:0] seg_led;
wire clk_div1, clk_div2;
wire [23:0] time_sum;
wire [4:0] ctl_seg;
wire dot;
time_div time_div(
.clock(clock),
.reset(reset),
.clk_div1(clk_div1),
.clk_div2(clk_div2)
);
time_ms time_ms(
.clock(clk_div1),
.reset(reset),
.time_sum(time_sum)
);
scan scan(
.clock(clk_div1),
.reset(reset),
.sel(sel),
.time_sum(time_sum),
.ctl_seg(ctl_seg),
.dot(dot)
);
seg_led_show seg_led_show(
.clock(clk_div1),
.reset(reset),
.seg_led(seg_led),
.ctl_seg(ctl_seg),
.dot(dot)
);
endmodule

Summarize some small knowledge points of writing code. First of all, because the writing of modules is slowly increasing, when we modify a port of one of the modules, we must pay attention to the modification of this port in other modules, and the port of the top module modify. Especially the modification of this value of bit width. A little carelessness will make you appear incomprehensible BUG. I hope that our code BUG will be less and less, and
finally put a small video to show a result of this experiment.

AX301 digital tube display clock small video

Disclaimer: This article is only suitable for learning, and its content contains excerpts and summaries from the book. Welcome everyone to add and make progress together.

Guess you like

Origin blog.csdn.net/qq_24213087/article/details/108423524