第22讲:数码管静态显示
数码管是一种半导体发光器件,其基本单元是发光二极管。
低电平点亮,高电平熄灭
模块设计
组合如下:
seg_static波形图绘制:
seg_static.v
`timescale 1ns/1ns module seg_static ( input wire sys_clk , //系统时钟,频率50MHz input wire sys_rst_n , //复位信号,低电平有效 output reg [5:0] sel , //数码管位选信号 output reg [7:0] seg //数码管段选信号 ); //parameter define parameter CNT_WAIT_MAX = 25'd24_999_999; //计数器最大值(0.5s) //十六进制数显示编码 parameter SEG_0 = 8'b1100_0000, SEG_1 = 8'b1111_1001, SEG_2 = 8'b1010_0100, SEG_3 = 8'b1011_0000, SEG_4 = 8'b1001_1001, SEG_5 = 8'b1001_0010, SEG_6 = 8'b1000_0010, SEG_7 = 8'b1111_1000, SEG_8 = 8'b1000_0000, SEG_9 = 8'b1001_0000, SEG_A = 8'b1000_1000, SEG_B = 8'b1000_0011, SEG_C = 8'b1100_0110, SEG_D = 8'b1010_0001, SEG_E = 8'b1000_0110, SEG_F = 8'b1000_1110; parameter IDLE = 8'b1111_1111; //不显示状态 //reg define reg add_flag ; //数码管数值+1标志信号 reg [24:0] cnt_wait ; //时钟分频计数器 reg [3:0] num ; //数码管显示的十六进制数 //cnt_wait:0.5秒计数 always@(posedge sys_clk or negedge sys_rst_n) if(sys_rst_n == 1'b0) cnt_wait <= 25'd0; else if(cnt_wait == CNT_WAIT_MAX) cnt_wait <= 25'd0; else cnt_wait <= cnt_wait + 1'b1; //add_flag:0.5s拉高一个标志信号 always@(posedge sys_clk or negedge sys_rst_n) if(sys_rst_n == 1'b0) add_flag <= 1'b0; else if(cnt_wait == CNT_WAIT_MAX) add_flag <= 1'b1; else add_flag <= 1'b0; //num:从 4'h0 加到 4'hf 循环 always@(posedge sys_clk or negedge sys_rst_n) if(sys_rst_n == 1'b0) num <= 4'd0; else if(add_flag == 1'b1) num <= num + 1'b1; else num <= num; //sel:选中六个数码管 always@(posedge sys_clk or negedge sys_rst_n) if(sys_rst_n == 1'b0) sel <= 6'b000000; else sel <= 6'b111111; //给要显示的值编码 always@(posedge sys_clk or negedge sys_rst_n) if(sys_rst_n == 1'b0) seg <= IDLE; else case(num) 4'd0: seg <= SEG_0; 4'd1: seg <= SEG_1; 4'd2: seg <= SEG_2; 4'd3: seg <= SEG_3; 4'd4: seg <= SEG_4; 4'd5: seg <= SEG_5; 4'd6: seg <= SEG_6; 4'd7: seg <= SEG_7; 4'd8: seg <= SEG_8; 4'd9: seg <= SEG_9; 4'd10: seg <= SEG_A; 4'd11: seg <= SEG_B; 4'd12: seg <= SEG_C; 4'd13: seg <= SEG_D; 4'd14: seg <= SEG_E; 4'd15: seg <= SEG_F; default:seg <= IDLE ; //闲置状态,不显示 endcase endmodule
hc595_ctrl模块
hc595_ctrl.v
`timescale 1ns/1ns module hc595_ctrl ( input wire sys_clk , //系统时钟,频率50MHz input wire sys_rst_n , //复位信号,低有效 input wire [5:0] sel , //数码管位选信号 input wire [7:0] seg , //数码管段选信号 output reg stcp , //数据存储器时钟 output reg shcp , //移位寄存器时钟 output reg ds , //串行数据输入 output wire oe //使能信号,低有效 ); //reg define reg [1:0] cnt_4 ; //分频计数器 reg [3:0] cnt_bit ; //传输位数计数器 //wire define wire [13:0] data ; //数码管信号寄存 //将数码管信号寄存 assign data = {seg[0],seg[1],seg[2],seg[3],seg[4],seg[5],seg[6],seg[7],sel}; //将复位取反后赋值给其即可 assign oe = ~sys_rst_n; //分频计数器:0~3循环计数 always@(posedge sys_clk or negedge sys_rst_n) if(sys_rst_n == 1'b0) cnt_4 <= 2'd0; else if(cnt_4 == 2'd3) cnt_4 <= 2'd0; else cnt_4 <= cnt_4 + 1'b1; //cnt_bit:每输入一位数据加一 always@(posedge sys_clk or negedge sys_rst_n) if(sys_rst_n == 1'b0) cnt_bit <= 4'd0; else if(cnt_4 == 2'd3 && cnt_bit == 4'd13) cnt_bit <= 4'd0; else if(cnt_4 == 2'd3) cnt_bit <= cnt_bit + 1'b1; else cnt_bit <= cnt_bit; //stcp:14个信号传输完成之后产生一个上升沿 always@(posedge sys_clk or negedge sys_rst_n) if(sys_rst_n == 1'b0) stcp <= 1'b0; else if(cnt_bit == 4'd13 && cnt_4 == 2'd3) stcp <= 1'b1; else stcp <= 1'b0; //shcp:产生四分频移位时钟 always@(posedge sys_clk or negedge sys_rst_n) if(sys_rst_n == 1'b0) shcp <= 1'b0; else if(cnt_4 >= 4'd2) shcp <= 1'b1; else shcp <= 1'b0; //ds:将寄存器里存储的数码管信号输入即 always@(posedge sys_clk or negedge sys_rst_n) if(sys_rst_n == 1'b0) ds <= 1'b0; else if(cnt_4 == 2'd0) ds <= data[cnt_bit]; else ds <= ds; endmodule
seg_595_static.v
`timescale 1ns/1ns module seg_595_static ( input wire sys_clk , //系统时钟,频率50MHz input wire sys_rst_n , //复位信号,低有效 output wire stcp , //输出数据存储寄时钟 output wire shcp , //移位寄存器的时钟输入 output wire ds , //串行数据输入 output wire oe //输出使能信号 ); //wire define wire [5:0] sel; wire [7:0] seg; //---------- seg_static_inst ---------- seg_static seg_static_inst ( .sys_clk (sys_clk ), //系统时钟,频率50MHz .sys_rst_n (sys_rst_n ), //复位信号,低电平有效 .sel (sel ), //数码管位选信号 .seg (seg ) //数码管段选信号 ); //---------- hc595_ctrl_inst ---------- hc595_ctrl hc595_ctrl_inst ( .sys_clk (sys_clk ), //系统时钟,频率50MHz .sys_rst_n (sys_rst_n), //复位信号,低有效 .sel (sel ), //数码管位选信号 .seg (seg ), //数码管段选信号 .stcp (stcp ), //输出数据存储寄时钟 .shcp (shcp ), //移位寄存器的时钟输入 .ds (ds ), //串行数据输入 .oe (oe ) //输出使能信号 ); endmodule
仿真:tb_seg_595_static.v
`timescale 1ns/1ns module tb_seg_595_static(); //wire define wire stcp ; //输出数据存储寄时钟 wire shcp ; //移位寄存器的时钟输入 wire ds ; //串行数据输入 wire oe ; //输出使能信号 //reg define reg sys_clk ; reg sys_rst_n ; //对sys_clk,sys_rst_n赋初始值 initial begin sys_clk = 1'b1; sys_rst_n <= 1'b0; #100 sys_rst_n <= 1'b1; end //clk:产生时钟 always #10 sys_clk <= ~sys_clk; //重新定义参数值,缩短仿真时间 defparam seg_595_static_inst.seg_static_inst.CNT_WAIT_MAX = 10; //-------------seg_595_static_inst------------- seg_595_static seg_595_static_inst ( .sys_clk (sys_clk ), //系统时钟,频率50MHz .sys_rst_n (sys_rst_n ), //复位信号,低电平有效 .stcp (stcp ), //输出数据存储寄时钟 .shcp (shcp ), //移位寄存器的时钟输入 .ds (ds ), //串行数据输入 .oe (oe ) //输出使能信号 ); endmodule
第23讲:数码管动态显示
模块设计
系统框图绘制
data_gen波形图绘制
FPGA入门(6):数码管静态/动态显示(二)+https://developer.aliyun.com/article/1556562