sixcircle

三十而立学FPGA之数码管

0
阅读(224)

简介

数码管,一种把多个发光二极管通过简单阵列的方式组合而成的显示器件。多个二极管阴极连在一起,通过控制阳极的高低电平来控制数码管相应LED亮灭的叫做共阴,反之共阳。每个发光二极管称之为数码管的段,连在一起的阴极或阳极称之为位。

实现框图

image.png

模块实现

1. 十进制转BCD模块

十进制(二进制)转BCD通常使用方式是移位加三的算法。具体方式如下表示(以123即8‘b01111011为例):

 image.png

说明:

count为0,将需要转换的数值赋值给设置的移位寄存器shift_reg的后八位

count每计数一次,将移位寄存器向左移1位,再判断个位十位的值是否大于等于5,如果十位或个位大于等于5,则十位或个位都加3。

移位的次数(即count的计数值),由需要转化的数的二进制位数相同。

需要避免0,因为复位count值为0,会打乱后面的逻辑。

程序实现

//移位计数
always @(posedge clk or negedge rst_n)
begin
    if(rst_n == 1'b0)
        count <= 4'd0;
    else if(count == 4'd9)
        count <= 4'd0;
    else
        count <= count + 4'd1;
end

//移位加三算法
always @(posedge clk or negedge rst_n)
begin
    if(rst_n == 1'b0)
        shift_reg = {shift_reg[19:8],data_in};
    else if(count == 4'd0)
        shift_reg = {shift_reg[19:8],data_in};
    else if(count <= 4'd9)
        if(shift_reg[11:8]>=5)
            if(shift_reg[15:12]>=5)
            begin
                shift_reg[11:8] = shift_reg[11:8] + 4'd3;
                shift_reg[15:12]= shift_reg[15:12]+ 4'd3;
            end
     else
            begin
                shift_reg[11:8] = shift_reg[11:8] + 4'd3;
                shift_reg[15:12]= shift_reg[15:12];
            end
    else
           if(shift_reg[15:12]>=5)
            begin
                shift_reg[11:8] = shift_reg[11:8];
                shift_reg[15:12]= shift_reg[15:12]+ 4'd3;
            end
     else
            begin
                shift_reg[11:8] = shift_reg[11:8];
                shift_reg[15:12]= shift_reg[15:12];
            end
    else
        shift_reg = shift_reg;       
end

2. 译码模块

以下代码以共阳极数码管为例

always @(posedge clk or negedge rst_n)
begin
if(rst_n == 1'b0)
dp_val_r <= 8'b1100_0000;
else
case (dp_index)   //dp,g,f,e,d,c,b,a
0:dp_val_r <= 8'b1100_0000;
1:dp_val_r <= 8'b1111_1001;
2:dp_val_r <= 8'b1010_0100;
3:dp_val_r <= 8'b1011_0000;
4:dp_val_r <= 8'b1001_1001;
5:dp_val_r <= 8'b1001_0010;
6:dp_val_r <= 8'b1000_0010;
7:dp_val_r <= 8'b1111_1000;
8:dp_val_r <= 8'b1000_0000;
9:dp_val_r <= 8'b1001_0000;
10:dp_val_r <= 8'b1000_1000;
11:dp_val_r <= 8'b1000_0011;
12:dp_val_r <= 8'b1100_0110;
13:dp_val_r <= 8'b1010_0001;
14:dp_val_r <= 8'b1000_0110;
15:dp_val_r <= 8'b1000_1110;
default:dp_val_r <= 8'b1100_0000;
endcase
end

3. 数码管扫描模块

扫描计时

always @(posedge clk or negedge rst_n)
begin
if(rst_n == 1'b0)
cnt <= 20'd0;
else if(start_cnt == 1'b1)
if(cnt == 20'd99999)
cnt <= 20'd0;
else
cnt <= cnt + 20'd1;
else
cnt <= 20'd0;
end

扫描实现

本实验为六位数码管

//SEL_W由数码管位数决定
always @(posedge clk or negedge rst_n)
begin
if(rst_n == 1'b0)
dp_sel_o_r <= {{(SEL_W-1){1'b0}},1'b1};
else if(cnt == 20'd99999)
dp_sel_o_r <= dp_sel_o_r << 1;
else if(dp_sel_o_r == {1'b0,{(SEL_W-1){1'b0}}})
dp_sel_o_r <= {{(SEL_W-1){1'b0}},1'b1};
else
dp_sel_o_r <= dp_sel_o_r;
end


always @(posedge clk or negedge rst_n)
if(rst_n == 1'b0)
dp_index = 4'd0;
else
begin
case (dp_sel_o_r)
6'b000000:dp_index = 4'd0;
6'b000001:dp_index = dp_data_r[3:0];
6'b000010:dp_index = dp_data_r[7:4];
6'b000100:dp_index = dp_data_r[11:8];
6'b001000:dp_index = dp_data_r[15:12];
6'b010000:dp_index = dp_data_r[19:16];
6'b100000:dp_index = dp_data_r[23:20];
default: dp_index = 4'd0;
endcase
end