Aprendizaje de la placa de desarrollo AX301 de oro negro (3) -Experimento de reloj de tubo digital dinámico

El uso de la placa de desarrollo es AX301, y los materiales de aprendizaje se pueden encontrar en otro artículo mío. El enlace es el siguiente: https://blog.csdn.net/qq_24213087/article/details/108238682 Inserte la descripción de la imagen aquí
1. Introducción
al tubo digital dinámico En el artículo anterior, hablamos sobre el diagrama de principio del tubo digital y los principales métodos de estática. mostrar en detalle. Repasemos el diagrama esquemático de nuestro uso de tubos digitales.
Inserte la descripción de la imagen aquí
La pantalla del tubo digital seis en uno es una pantalla dinámica. Debido a la persistencia de la visión humana y al efecto de resplandor de los diodos emisores de luz, el principio de este efecto indirecto es el mismo que el de mirar películas. La proyección de una película es una imagen tras otra. Siempre que se garantice la velocidad de más de 20 fotogramas por segundo, nuestro cerebro dejará un tiempo de reacción. Este tiempo es provocado por el efecto de resplandor. Entonces, las películas que vemos son dinámicas y continuas. Por lo tanto, cuando el tiempo de exploración dinámica del tubo digital es superior a 50 HZ, aunque los tubos digitales no están realmente iluminados al mismo tiempo, da la impresión de un conjunto estable de datos de visualización sin parpadeo. Aquí hay un póster de mi película favorita.
Inserte la descripción de la imagen aquí

2. Experimento del reloj
A continuación, volvamos al tema, completamos la visualización del tubo digital dinámico mediante un experimento del reloj. En primer lugar, el AX301 que utilizamos es un cristal de 50 MHz. El retardo mínimo es de 20 ns. Entonces necesitamos dividir nuestro reloj en un reloj de 1 ms.

/* 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

Una vez que la división del reloj está bien, continuamos considerando el problema de conteo del diseño del reloj. El conteo en el nivel de ms es el sistema decimal normal, pero para el segundo nivel y la calificación, es el sistema de 60. Por lo tanto, necesitamos clasificar el valor de conteo por milisegundo.

/* 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

Luego viene la parte más importante de este experimento, la función de escaneo de pantalla, que realiza el control de la selección de posición.

/* 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

El último paso es realizar el control de selección de segmento en los caracteres mostrados por cada tubo digital para realizar la visualización del número actual

/* 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

El último es nuestro código de nivel superior, que realiza la conexión entre los distintos módulos

/* 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

Resumir algunos pequeños puntos de conocimiento de la escritura de código. En primer lugar, debido a que la escritura de módulos está aumentando lentamente, cuando modificamos un puerto de uno de los módulos, debemos prestar atención a la modificación de este puerto en otros módulos, y el puerto del módulo superior modificar. Especialmente la modificación de este valor de ancho de bit. Un poco de descuido te hará parecer ERROR incomprensible. Espero que nuestro código ERROR sea cada vez menor, y
finalmente pongo un pequeño video para mostrar un resultado de este experimento.

Reloj de pantalla de tubo digital AX301 pequeño video

Descargo de responsabilidad: este artículo solo es apto para el aprendizaje, y su contenido incluye extractos y resúmenes del libro. Bienvenidos a todos para que agreguen y progresen juntos.

Supongo que te gusta

Origin blog.csdn.net/qq_24213087/article/details/108423524
Recomendado
Clasificación