简介
数码管,一种把多个发光二极管通过简单阵列的方式组合而成的显示器件。多个二极管阴极连在一起,通过控制阳极的高低电平来控制数码管相应LED亮灭的叫做共阴,反之共阳。每个发光二极管称之为数码管的段,连在一起的阴极或阳极称之为位。
实现框图
![](https://static.assets-stash.eet-china.com/album/202206/12/165807scimmcyef7g8g1li.png)
模块实现
1. 十进制转BCD模块
十进制(二进制)转BCD通常使用方式是移位加三的算法。具体方式如下表示(以123即8‘b01111011为例):
![](https://static.assets-stash.eet-china.com/album/202206/12/165822mued6l67sdz9bhsp.png)
说明:
1. count为0,将需要转换的数值赋值给设置的移位寄存器shift_reg的后八位
2. count每计数一次,将移位寄存器向左移1位,再判断个位十位的值是否大于等于5,如果十位或个位大于等于5,则十位或个位都加3。
3. 移位的次数(即count的计数值),由需要转化的数的二进制位数相同。
4. 需要避免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; endcaseend复制代码
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;elsebegin 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; endcaseend复制代码
作者: 二月半, 来源:面包板社区
链接: https://mbb.eet-china.com/blog/uid-me-1862109.html
版权声明:本文为博主原创,未经本人允许,禁止转载!
yzw92 2022-6-13 06:25