一、数码管静态显示
1、数码管
数码管是一种半导体发光器件,其基本单元是发光二极管。
待显示内容 段码(二进制格式) 段码(十六进制格式)
6位8段数码管
2、74HC595
74HC595是一个8位串行输入、并行输出的位移缓存器。其内部具有8位移位寄存器和一个存储器,具有三态输出功能。
输入方式:seg[0]…seg[7] sel[7]…sel[0]
端口作用
连接到FPGA上的端口有4个,分别是DS、SHCP、STCP、OE
MR:复位端,对数据进行清零,不接到FPGA芯片上面,直接接到vcc上,避免对数据清零
DS:将串行数据传送到移位寄存器中
SHCP:移位寄存器的时钟输入端,在上升沿时将输入的数据移入到移位寄存器中间,先进来的数据在最后面,最多输入8bit数据,如果超过8bit,比如14位,那么最前面输入的6位数据会通过Q7S端口输出,Q7S会与下一个74HC595芯片的DS相连接
STCP:存储寄存器时钟,控制8位的存储器,在上升沿时,将移位寄存器中的数据写入到8位存储器中。
OE:使能信号,低电平有效,当使能信号有效时,会将存储器中的数据通过端口传输出去。
二、实现
实现数码管从000000~FFFFFF的循环显示,每个显示0.5s
1、电路图
2、输入输出方式
3、整体框图
4、数码管显示部分
波形图
程序:
module seg_static
#(
parameter CNT_MAX = 25'd24999999
)
(
input wire sys_clk,
input wire sys_rst_n,
output reg [5:0] sel,
output reg [7:0] seg
);
reg [24:0] cnt;
reg [3:0] data;
/* reg cnt_flag; */
//cnt_wait:0.5秒计数
always@(posedge sys_clk or negedge sys_rst_n)
if (sys_rst_n == 1'b0)
cnt <= 25'd0;
else if (cnt == CNT_MAX)
cnt <= 25'd0;
else
cnt <= cnt + 1'b1;
//num:从 4'h0 加到 4'hf 循环
always@(posedge sys_clk or negedge sys_rst_n)
if (sys_rst_n == 1'b0)
data <= 4'd0;
else if ((data == 4'd15)&&(cnt == CNT_MAX))
data <= 4'd0;
else if (cnt == CNT_MAX)//也可以使用标志信号进行控制
data <= data + 1'b1;
else
data <= data;
//add_flag:0.5s拉高一个标志信号
/* always@(posedge sys_clk or negedge sys_rst_n)
if (sys_rst_n ==1'b0)
cnt_flag <= 1'b0;
else if (cnt == (CNT_MAX-25'd1))
cnt_flag <= 1'b1;
else
cnt_flag <= 1'b0; */
//sel:选中六个数码管
always@(posedge sys_clk or negedge sys_rst_n)
if (sys_rst_n ==1'b0)
sel <= 6'd0;
else
sel <= 6'b111111;
//给要显示的值编码,段显示
always@(posedge sys_clk or negedge sys_rst_n)
if (sys_rst_n == 1'b0)
seg <= 8'hff;
else case(data)
4'd0: seg <= 8'hc0;
4'd1: seg <= 8'hf9;
4'd2: seg <= 8'ha4;
4'd3: seg <= 8'hb0;
4'd4: seg <= 8'h99;
4'd5: seg <= 8'h92;
4'd6: seg <= 8'h82;
4'd7: seg <= 8'hf8;
4'd8: seg <= 8'h80;
4'd9: seg <= 8'h90;
4'd10: seg <= 8'h88;
4'd11: seg <= 8'h83;
4'd12: seg <= 8'hc6;
4'd13: seg <= 8'ha1;
4'd14: seg <= 8'h86;
4'd15: seg <= 8'h8e;
default: seg <= 8'hff;
endcase
endmodule
5、hc595控制
程序:
module hc595_ctrl
(
input wire sys_clk ,
input wire sys_rst_n ,
input wire [5:0] sel ,
input wire [7:0] seg ,
output reg ds , //串行数据输入
output reg shcp , //移位寄存器时钟
output reg stcp , //移位寄存器时钟
output wire oe //使能信号,低有效
);
wire [13:0] data ; //数码管信号寄存
reg [1:0] cnt ; //分频计数器
reg [3:0] cnt_bit ; //传输位数计数器
//将数码管信号寄存
assign data ={seg[0],seg[1],seg[2],seg[3],seg[4],seg[5],seg[6],seg[7],sel[5:0]};
//分频计数器:0~3循环计数
always@(posedge sys_clk or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
cnt <= 2'd0;
else if (cnt == 2'd3)
cnt <= 2'd0;
else
cnt <= cnt + 1'b1;
//cnt_bit:每输入一位数据加一
always@(posedge sys_clk or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
cnt_bit <= 4'b0;
else if ((cnt_bit == 4'd13)&&(cnt == 2'd3))
cnt_bit <= 4'b0;
else if(cnt == 2'd3)
cnt_bit <= cnt_bit +1'b1;
else
cnt_bit <= cnt_bit;
//ds:将寄存器里存储的数码管信号输入即
always@(posedge sys_clk or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
ds <= 1'b0;
else if (cnt == 2'd0)
ds <= data [cnt_bit];
else
ds <= ds;
//shcp:产生四分频移位时钟
always@(posedge sys_clk or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
shcp <= 1'b0;
else if (cnt >= 2'd2)
shcp <= 1'b1;
else
shcp <= 1'b0;
//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'd0)&&(cnt == 2'd0))
stcp <= 1'b1;
else if ((cnt_bit == 4'd0)&&(cnt == 2'd2))
stcp <= 1'b0;
else
stcp <= stcp;
//使能信号,低电平有效,所以一直为低电平
assign oe = 1'b0;
endmodule
6、整体程序(将前面两个模块连接起来)
module seg_595_static
(
input wire sys_clk,
input wire sys_rst_n,
output wire ds,
output wire shcp,
output wire stcp,
output wire oe
);
wire [5:0] sel;
wire [7:0] seg;
seg_static
#(
.CNT_MAX (25'd24999999)
)
seg_static_inst
(
. sys_clk (sys_clk),
. sys_rst_n(sys_rst_n),
. sel (sel ),
. seg (seg )
);
hc595_ctrl hc595_ctrl_inst
(
. sys_clk (sys_clk) ,
. sys_rst_n (sys_rst_n) ,
. sel (sel) ,
. seg (seg) ,
. ds (ds) ,
.shcp (shcp) ,
.stcp (stcp) ,
. oe (oe)
);
endmodule
测试程序
对整体的框图进行编写测试程序
`timescale 1ns/1ns
module tb_seg_595_static();
wire stcp ; //输出数据存储寄时钟
wire shcp ; //移位寄存器的时钟输入
wire ds ; //串行数据输入
wire oe ; //输出使能信号
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;
//-------------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