Verilog 学习第八节(数码管段码显示)

共阴极数码管:低电平端接的都是0,高电平端哪里设置为1 ,哪里就亮~
共阳极数码管与之相反~
视觉暂留:
对于三位的共阴极数码管
第0.01s:让数码管0的a段亮,其他数码管全灭
Sel0为高电平,sel1和sel2为低电平
A段为低电平

第0.02s:让数码管1的b、c段亮,其他数码管全灭
Sel1为高电平,sel0和sel2为低电平
B和C段为低电平

第0.03s:让数码管2的e段亮,其他数码管全灭
Sel2为高电平,sel0和sel1为低电平
E段为低电平
数码管动态扫描
所以,通过这种方式,可以节约引脚~
Verilog 学习第八节(数码管段码显示)_第1张图片
抽象原理图:
Verilog 学习第八节(数码管段码显示)_第2张图片
在fpga设计中尽量使用使能时钟去驱动寄存器,而不是门控时钟,因为门控时钟的质量非常差
Verilog 学习第八节(数码管段码显示)_第3张图片
使用门控时钟,将门控时钟直接作为DFF的工作时钟,没有ENA的情况下忽略ENA
Verilog 学习第八节(数码管段码显示)_第4张图片

使用使能时钟的情况,DFF的工作时钟继续全局高质量时钟,而将使能时钟作为DFF的使能信号使用

在能使用时序逻辑的情况下,尽量使用时序逻辑
顶层模块:


module hex8_test(
    input Clk,
    input Reset,
    output [7:0]SEL,
    output [7:0]SEG
    );
    wire [31:0]Disp_Data;
    hex8_2 hex8_2(
    Clk,
    Reset,
    Disp_Data,
    SEL,
    SEG
    );
    assign Disp_Data=32'h12359bdf;
    
endmodule

主模块

module hex8(
    input Clk,
    input Reset,
    input [31:0]Disp_Data,
    output reg [7:0]SEL,
    output reg [7:0]SEG//seg[0]对应a,seg[1]对应b~~~~seg[7]对应h
    );
    reg clk_1k;
    reg [14:0]div_cnt;
    always@(posedge Clk or negedge Reset)begin
        if(!Reset)
            div_cnt<=0;
        else if(div_cnt>=25000-1)
            div_cnt<=0;
        else
            div_cnt<=div_cnt+1;
    end
    
    always@(posedge Clk or negedge Reset)begin
         if(!Reset)
            clk_1k<=0;
         else if(div_cnt>=25000-1)
             clk_1k<=~clk_1k;
    end
    
    reg[2:0]reg_num;
    always@(posedge clk_1k or negedge Reset)begin
         if(!Reset)
            reg_num<=0;
         else if(reg_num>=7)
            reg_num<=0;
         else
            reg_num<=reg_num+1;
    end
    
    always@(*)begin
         case(reg_num)
         0:SEL=8'b0000_0001;
         1:SEL=8'b0000_0010;
         2:SEL=8'b0000_0100;
         3:SEL=8'b0000_1000;
         4:SEL=8'b0001_0000;
         5:SEL=8'b0010_0000;
         6:SEL=8'b0100_0000;
         7:SEL=8'b1000_0000;
         endcase
    end
    
    reg[3:0] disp_temp;
    always@(*)begin
             case(reg_num)
             7:disp_temp=Disp_Data[31:28];
             6:disp_temp=Disp_Data[27:24];
             5:disp_temp=Disp_Data[23:20];
             4:disp_temp=Disp_Data[19:16];
             3:disp_temp=Disp_Data[15:12];
             2:disp_temp=Disp_Data[11:8];
             1:disp_temp=Disp_Data[7:4];
             0:disp_temp=Disp_Data[3:0];
             endcase
        end
        
     always@(*)begin
          case(disp_temp)
          0:SEG=8'hc0;
          1:SEG=8'hf9;
          2:SEG=8'ha4;
          3:SEG=8'hb0;
          4:SEG=8'h99;
          5:SEG=8'h92;
          6:SEG=8'h82;
          7:SEG=8'hf8;
          8:SEG=8'h80;
          9:SEG=8'h90;
          4'ha:SEG=8'h88;
          4'hb:SEG=8'h83;
          4'hc:SEG=8'hc6;
          4'hd:SEG=8'ha1;
          4'he:SEG=8'h86;
          4'hf:SEG=8'h8e;
          endcase
     end 
endmodule

改进后的主模块


module hex8_2(
    input Clk,
    input Reset,
    input [31:0]Disp_Data,
    output reg [7:0]SEL,
    output reg [7:0]SEG//seg[0]对应a,seg[1]对应b~~~~seg[7]对应h
    );
    reg clk_1k;
    reg [15:0]div_cnt;
    always@(posedge Clk or negedge Reset)begin
        if(!Reset)
            div_cnt<=0;
        else if(div_cnt>=50000-1)
            div_cnt<=0;
        else
            div_cnt<=div_cnt+1;
    end
    
    always@(posedge Clk or negedge Reset)begin
         if(!Reset)
            clk_1k<=0;
         else if(div_cnt>=50000-1)
            clk_1k<=1;
         else
            clk_1k<=0;
    end
    
    reg[2:0]reg_num;
    always@(posedge Clk or negedge Reset)begin
         if(!Reset)
            reg_num<=0;
         else if(clk_1k)
            reg_num<=reg_num+1;
         else
            reg_num<=reg_num;
    end
    
    always@(posedge Clk)begin
         case(reg_num)
         7:SEL=8'b0000_0001;
         6:SEL=8'b0000_0010;
         5:SEL=8'b0000_0100;
         4:SEL=8'b0000_1000;
         3:SEL=8'b0001_0000;
         2:SEL=8'b0010_0000;
         1:SEL=8'b0100_0000;
         0:SEL=8'b1000_0000;
         endcase
    end
    
    reg[3:0] disp_temp;
    always@(posedge Clk)begin
             case(reg_num)
             0:disp_temp=Disp_Data[31:28];
             1:disp_temp=Disp_Data[27:24];
             2:disp_temp=Disp_Data[23:20];
             3:disp_temp=Disp_Data[19:16];
             4:disp_temp=Disp_Data[15:12];
             5:disp_temp=Disp_Data[11:8];
             6:disp_temp=Disp_Data[7:4];
             7:disp_temp=Disp_Data[3:0];
             endcase
        end
        
     always@(posedge Clk)begin
          case(disp_temp)
          0:SEG=8'hc0;
          1:SEG=8'hf9;
          2:SEG=8'ha4;
          3:SEG=8'hb0;
          4:SEG=8'h99;
          5:SEG=8'h92;
          6:SEG=8'h82;
          7:SEG=8'hf8;
          8:SEG=8'h80;
          9:SEG=8'h90;
          4'ha:SEG=8'h88;
          4'hb:SEG=8'h83;
          4'hc:SEG=8'hc6;
          4'hd:SEG=8'ha1;
          4'he:SEG=8'h86;
          4'hf:SEG=8'h8e;
          endcase
     end 
endmodule

测试模块

`timescale 1ns / 1ps

module hex8_tb(
    );
    reg Clk;
    reg Reset;
    reg [31:0]Disp_Data;
    wire [7:0]SEL;
    wire [7:0]SEG;
    hex8 hex8(
        Clk,
        Reset,
        Disp_Data,
        SEL,
        SEG//seg[0]对应a,seg[1]对应b~~~~seg[7]对应h
        );
      initial Clk=0;
      always#10 Clk=!Clk;
      initial begin
      Reset=0;
      Disp_Data=32'h0000_0000;
      #201
      Reset=1;
      #2000
      Disp_Data=32'h1234_5678;
      #10000000
      Disp_Data=32'h9abc_def0;
      #10000000
      $stop;
      end
endmodule

时钟质量在FPGA设计中重要的原因

1:时钟延迟不确定,而且比较大
2:使得时钟的波形变差
3:驱动能力
Verilog 学习第八节(数码管段码显示)_第5张图片

你可能感兴趣的:(FPGA学习,学习,fpga开发)