24-数码管动态显示03

发布时间 2024-01-04 12:50:45作者: Icer_Newer

数码管动态显示

二进制码转变为BCD码

  • 动态显示驱动模块,是将传入的待显示的十进制数据,转换为位选和段选信号,传入的数据data是由数据产生模块产生的
  • 二进制表示的十进制数需要转变为BCD码表示的十进制数,从而产生位选和段选信号
  • BCD码是使用四位二进制数表示二进制数
  • BCD码分为有权码(8421码\5421码\2421码)和无权码(余三码\余三循环码\格雷码)
  • 8421码是最常使用的BCD码

BCD码产生段选信号和位选信号的优势?

  • 十进制数234,使用二进制数表示1110_1010,使用8421码进行表示0010_0011_0100),在第一个显示周期内显示个位,在第二个显示周期内显示第二个十位数码管...扫描频率足够快的时候,可以认为是同时显示,所以要分别得到个\十\百\千\万....值,使用BCD码进行表示可以直观的得到其中的个\十\百\千\万位

二进制码转换为BCD码

  • 首先进行补0操作,六位数码管显示的最大值是999_999,转变为6 bit BCD码,所以补24个0
  • 判断运算和移位操作,首先判断每一位BCD码,如果每一位BCD码<=4,保持数值不变,如果每一位BCD码>4,那么就将BCD码+3
  • 判断运算结束之后,不管是否进行加三操作,都需要将数据左移一位
  • 当移位计算到原数据的二进制数的值为0的时候,可以得到相应的BCD码
  • 移位次数=原来数据的二进制码的位宽

系统框图

波形图

  • 二进制向BCD码转换是通过判断运算和移位操作实现的
  • 移位操作的次数和数据的二进制长度有关,需要一个移位计数器cnt_shift [4:0],实际上移位20次即可,计数器的最大值是19,但是增加两个状态,一个是初始补零的状态,一个是最后提取数位的状态
  • 在进行移位操作的时候需要中间变量记录中间数据data_shift[43:0],并且要从中间数据中提取出相应的数据位(个/时/百/...)的数据
  • 判断运算在移位之前进行,并且每次cnt_shift值的更新都是在判断运算和移位操作之后进行的,所以需要一个标志信号(shift_flag),表示移位操作,同时可以作为cnt_shift值更新的信号,
  • 判断运算和移位操作是在一个周期内完成的
  • shift_flag信号,复位信号有效的时候,初始值位0,时钟信号无效的时候,在时钟上升沿不断对其进行取反,相当于对时钟进行二分频
  • shift_flag为高电平的时候,进行移位操作,cnt_shift进行加1计数,shift_flag为低电平的时候进行判断运算
  • cnt_shift计数到最大值并且shift_flag信号为高电平的时候,进行清0
  • 输出信号是个/十/百/千...位

RTL

```verilog
module  bcd_8421
(
    input   wire            sys_clk     ,   //系统时钟,频率50MHz
    input   wire            sys_rst_n   ,   //复位信号,低电平有效
    input   wire    [19:0]  data        ,   //输入需要转换的数据

    output  reg     [3:0]   unit        ,   //个位BCD码
    output  reg     [3:0]   ten         ,   //十位BCD码
    output  reg     [3:0]   hun         ,   //百位BCD码
    output  reg     [3:0]   tho         ,   //千位BCD码
    output  reg     [3:0]   t_tho       ,   //万位BCD码
    output  reg     [3:0]   h_hun           //十万位BCD码
);

//********************************************************************//
//******************** Parameter And Internal Signal *****************//
//********************************************************************//

//reg   define
reg     [4:0]   cnt_shift   ;   //移位判断计数器
reg     [43:0]  data_shift  ;   //移位判断数据寄存器
reg             shift_flag  ;   //移位判断标志信号

//********************************************************************//
//***************************** Main Code ****************************//
//********************************************************************//

//cnt_shift:从0到21循环计数
always@(posedge sys_clk or negedge sys_rst_n)
    if(sys_rst_n == 1'b0)
        cnt_shift   <=  5'd0;
    else    if((cnt_shift == 5'd21) && (shift_flag == 1'b1))
        cnt_shift   <=  5'd0;
    else    if(shift_flag == 1'b1)
        cnt_shift   <=  cnt_shift + 1'b1;
    else
        cnt_shift   <=  cnt_shift;
       
//data_shift:计数器为0时赋初值,计数器为1~20时进行移位判断操作
always@(posedge sys_clk or negedge sys_rst_n)
    if(sys_rst_n == 1'b0)
        data_shift  <=  44'b0;
    else    if(cnt_shift == 5'd0)
        data_shift  <=  {24'b0,data};
    else    if((cnt_shift <= 20) && (shift_flag == 1'b0))
        begin
            data_shift[23:20]   <=  (data_shift[23:20] > 4) ? (data_shift[23:20] + 2'd3) : (data_shift[23:20]);
            data_shift[27:24]   <=  (data_shift[27:24] > 4) ? (data_shift[27:24] + 2'd3) : (data_shift[27:24]);
            data_shift[31:28]   <=  (data_shift[31:28] > 4) ? (data_shift[31:28] + 2'd3) : (data_shift[31:28]);
            data_shift[35:32]   <=  (data_shift[35:32] > 4) ? (data_shift[35:32] + 2'd3) : (data_shift[35:32]);
            data_shift[39:36]   <=  (data_shift[39:36] > 4) ? (data_shift[39:36] + 2'd3) : (data_shift[39:36]);
            data_shift[43:40]   <=  (data_shift[43:40] > 4) ? (data_shift[43:40] + 2'd3) : (data_shift[43:40]);
        end
    else    if((cnt_shift <= 20) && (shift_flag == 1'b1))
        data_shift  <=  data_shift << 1;
    else
        data_shift  <=  data_shift;

//shift_flag:移位判断标志信号,用于控制移位判断的先后顺序
always@(posedge sys_clk or negedge sys_rst_n)
    if(sys_rst_n == 1'b0)
        shift_flag  <=  1'b0;
    else
        shift_flag  <=  ~shift_flag;

//当计数器等于20时,移位判断操作完成,对各个位数的BCD码进行赋值
always@(posedge sys_clk or negedge sys_rst_n)
    if(sys_rst_n == 1'b0)
        begin
            unit    <=  4'b0;
            ten     <=  4'b0;
            hun     <=  4'b0;
            tho     <=  4'b0;
            t_tho   <=  4'b0;
            h_hun   <=  4'b0;
        end
    else    if(cnt_shift == 5'd21)
        begin
            unit    <=  data_shift[23:20];
            ten     <=  data_shift[27:24];
            hun     <=  data_shift[31:28];
            tho     <=  data_shift[35:32];
            t_tho   <=  data_shift[39:36];
            h_hun   <=  data_shift[43:40];
        end

endmodule