本帖最后由 Zhao_kar 于 2024-1-28 22:56 编辑
【Tang Primer25K Dock】五——数码管的硬件设计+基本测试
备注:
- 先声明一下,近期因为期末等等原因,没有来得及更新,实在很抱歉
- 然后这两天会把所有的测试工程和经验作为帖子发表,然后之前说的那个数码管+按键的测试,因为最终项目我是直接在原先工程基础上改的。所以按键的测试放在最后的项目里面
- 本节主要演示一下自己画的板子,然后加上基础的测试,下一节直接就是最后的数字时钟的过程
- 后面有一个I2S的测试,我会在数字时钟的下一个帖子更新
- 本节分两个部分,第一个是1-9的计数显示,也就是基础测试,第二个就是一个1、2、3、4、5、6在六个数码管上的显示,然后提供三个按键,分别执行左移、右移、闪烁的功能
- 然后之前说的软核,我还没来得及搞,不过有博主做了,下周结束后我看看一周能不能移植成功吧
一、数码管的硬件设计
- 原理图如下
- 首先我们用的数字时钟,考虑到秒针,所以六位,其中我们采用传统的设计,而不是本次测评pmod的那种设计,他的设计是一个共阳极一个共阴极,但是我们统一的是六个共阳极,然后为了方便,我们把六个数码管的位选信号都单独拉出来,同时七位数值的跟DP是和原先的设计是一样的
- 然后电阻基本上都是限流用的,至于三极管,因为直接用引脚驱动的数码管,数码管的亮度会比较低,而用三极管来驱动会有效的解决数码管的亮度问题。
- 具体三极管原理就不多说了,这个原理框图设计很简单,布局布线就不做参考了,最后的成品如下图2、3
- 本来打算做排母的,然后我焊接的时候身边没有合适的7pin的排母了,换了比较麻烦的排针。
二、基础的计数测试
1、首先第一个代码的变动,我们要参考共阳极数码管的数字,而不是原先pmod的那个设计的译码值,那个数码管的pmod因为设计问题是不一样的,这个参考下图
2、详细的代码内容(带注释)
module digital_cnt
#(
parameter CNT_1HZ=28'd24_999_999//50M分1s
)
(
input clk,
input rst,
//output[7:0]led,
output reg [6:0]seg_n,
output [5:0]sel
);
/***************parameter*************/
//具体数据参考上图
localparam P_0 = 7'b1000000 ;
localparam P_1 = 7'b1111001 ;
localparam P_2 = 7'b0100100 ;
localparam P_3 = 7'b0110000 ;
localparam P_4 = 7'b0011001 ;
localparam P_5 = 7'b0010010 ;
localparam P_6 = 7'b0000010 ;
localparam P_7 = 7'b1111000 ;
localparam P_8 = 7'b0000000 ;
localparam P_9 = 7'b0010000 ;
localparam P_X = 7'b1111111 ;
/***************reg*******************/
reg [27:0] cnt_1hz;
reg clk_1hz=1'b0;
//分1s时钟
always @(posedge clk or negedge rst)
if (rst == 1'b0) begin
cnt_1hz <= 28'd0;
end else if (cnt_1hz == CNT_1HZ) begin
cnt_1hz <= 28'd0;
clk_1hz = ~clk_1hz;
end else begin
cnt_1hz <= cnt_1hz + 1'b1;
end
reg [27:0] cnt_100hz;
reg clk_100hz=1'b0;
//数码管计数0-9
reg [3:0] data_temp;
wire [3:0] data;//值
//reg sel_temp;
assign data=data_temp;
always@(posedge clk_1hz or negedge rst)
if(rst==1'b0)
data_temp<=4'b0000;
else if(data_temp==4'b1001)begin//如果等于9
data_temp<=4'b0000;
//sel_temp <= ~sel_temp;
end else
data_temp<=data_temp+1'b1;
//数码管数据选择
always @ (data)
case(data)
4'b0000: seg_n <= P_0;
4'b0001: seg_n <= P_1;
4'b0010: seg_n <= P_2;
4'b0011: seg_n <= P_3;
4'b0100: seg_n <= P_4;
4'b0101: seg_n <= P_5;
4'b0110: seg_n <= P_6;
4'b0111: seg_n <= P_7;
4'b1000: seg_n <= P_8;
4'b1001: seg_n <= P_9;
default: seg_n <= P_X;
endcase
//默认位选信号全部是0,也就是都亮
assign sel = 6'b000000;
endmodule
3、视频演示
三、六位数码管的移位、闪烁操作
1、代码,主要就是加了一个ctrl信号去进行左移右移的操作,详见代码后半部分
`timescale 1ns / 1ps
module math_123456
#(
parameter CNT_MAX1=20'd499_999,//100hz
parameter CNT_MAX2=28'd49_999_999,//1hz
parameter zero = 7'b100_0000,
parameter one=7'b111_1001,
parameter two=7'b010_0100,
parameter three=7'b011_0000,
parameter four=7'b001_1001,
parameter five=7'b001_0010,
parameter six=7'b000_0010,
parameter seven=7'b111_1000,
parameter eight=7'b000_0000,
parameter night=7'b001_0000
)
(
input sys_clk,
input sys_rst_n,
input [2:0] sw,//开关输入,1,2,4三个开关选择不同功能
output reg [5:0]wei,//位选
output reg [6:0]seg//译码
);
reg [27:0]cnt_1hz;//计数1hz
reg [19:0]cnt_100hz;//计数2,100hz,实操是80hz
wire clk_100hz;//分频100hz
reg clk_1hz=1'b0;//分频1hz
reg [2:0] count6;//位选计数
reg [23:0] dis_data=24'h123456;//数值
reg [3:0] data;//中间值
reg [2:0] sw_s;//中间值
reg [5:0] data_ctrl=6'b000000;//用于闪烁
always @(*)//组合逻辑,对sw的
sw_s=sw;
//100hz分频
always@(posedge sys_clk or negedge sys_rst_n)
if(sys_rst_n==1'b0)
cnt_100hz<=20'd0;
else if(cnt_100hz == CNT_MAX1)
// else if(cnt_100hz == 10)//仿真值
cnt_100hz<=20'd0;
else
cnt_100hz <=cnt_100hz+1'b1;
assign clk_100hz=(cnt_100hz<250000)?0:1;//100hz
//assign clk_100hz=(cnt_100hz<5)?0:1;//仿真
//1hz分频
always@(posedge sys_clk or negedge sys_rst_n)
if(sys_rst_n==1'b0)
cnt_1hz<=28'd0;
else if(cnt_1hz == CNT_MAX2)
// else if(cnt_1hz == 999)//仿真值
begin
cnt_1hz<=28'd0;
clk_1hz=~clk_1hz;
end
else
cnt_1hz<=cnt_1hz+1'b1;
//上述是两种不同的分频方式
//计数器(其实就是控制四个位选信号按照计数器的时间来计数)
always @(posedge clk_100hz or negedge sys_rst_n)
begin
if(sys_rst_n==1'b0)
count6<=3'b000;
else if(count6 == 3'b101)
count6<=3'b000;
else
count6<=count6+1;
end
//数码管的四个位选
always@(count6)
case(count6)
/*这里用了一个或运算,用于对后续的开关操作*/
3'b000:begin wei=6'b011111|data_ctrl; data=dis_data[23:20];end
3'b001:begin wei=6'b101111|data_ctrl; data=dis_data[19:16];end
3'b010:begin wei=6'b110111|data_ctrl; data=dis_data[15:12];end
3'b011:begin wei=6'b111011|data_ctrl; data=dis_data[11:8];end
3'b100:begin wei=6'b111101|data_ctrl; data=dis_data[7:4];end
3'b101:begin wei=6'b111110|data_ctrl; data=dis_data[3:0];end
default:begin wei=6'b111111; data=4'd0;end
endcase
//数码管输出值
always@(data)
case(data)
0: seg=zero;
1: seg=one;
2: seg=two;
3: seg=three;
4: seg=four;
5: seg=five;
6: seg=six;
7: seg=seven;
8: seg=eight;
9: seg=night;
default: seg=7'b000_0000;
endcase
//移位和闪烁部分
always@(posedge clk_1hz)
case(sw_s)
1: dis_data <={dis_data[19:0],dis_data[23:20]};//左移
2: dis_data <={dis_data[3:0],dis_data[23:4]};//右移
4: data_ctrl<=~data_ctrl;//闪烁(1s闪一次)
default:dis_data <=dis_data;//不变
endcase
endmodule
2、视频演示
移动