1. vivado文件编写,根据模块设计图
系统的时钟为100MHz,管脚E3提供;使用复位引脚为拨码开关,管脚K15
1.1 点亮数码管之前首先产生一个100ms自增长的数据data[26:0]
1.1.1 时序图
1.1.2 data_gen.v 文件
module data_gen
#(
parameter CNT_100MS_MAX = 27'd9_999_999,
parameter DATA_MAX = 27'd99_999_999
)
(
input wire sys_clk ,
input wire sys_rst_n ,
output reg [26:0] data
);
reg [26:0] cnt_100ms;
reg cnt_flag;
//cnt_100ms
always@(posedge sys_clk or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
cnt_100ms <= 27'd0;
else if(cnt_100ms == CNT_100MS_MAX)
cnt_100ms <= 27'd0;
else
cnt_100ms <= cnt_100ms + 1'b1;
//cnt_flag
always@(posedge sys_clk or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
cnt_flag <= 1'b0;
else if(cnt_100ms == CNT_100MS_MAX - 1'b1)
cnt_flag <= 1'b1;
else
cnt_flag <= 1'b0;
//data
always@(posedge sys_clk or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
data <= 27'd0;
else if(cnt_flag == 1'b1 && data == DATA_MAX)
data <= 27'd0;
else if(cnt_flag == 1'b1)
data <= data + 1'b1;
else
data <= data;
endmodule
1.1.3 tb_data_gen.v 文件
`timescale 1ns/1ns
module tb_data_gen();
reg sys_clk;
reg sys_rst_n;
wire [26:0] data;
initial
begin
sys_clk = 1'b0;
sys_rst_n = 1'b0;
#20
sys_rst_n = 1'b1;
end
always #10 sys_clk = ~sys_clk;
data_gen
#(
.CNT_100MS_MAX (27'd99_999_999),
.DATA_MAX (27'd99_999_999)
)
data_gen_inst
(
.sys_clk (sys_clk ),
.sys_rst_n (sys_rst_n),
.data (data )
);
endmodule
1.2 点亮数码管的核心在于将十进制数不通过除法器转换为二进制,这里使用bcd_8421码
1.2.0 将十进制11转换为bcd_8421码的简单过程
转换的全程使用判断移位来完成,转换的数有几个二进制就要判断移位多少次,前面要添加 4n 个0
即十进制11 的二进制为1011,4位二进制,需要4次,添加 42 = 8个0
如果当前的数大于4,要进行 +3 再移位
1.2.1 时序图
1.2.2 bcd_8421.v文件
module bcd_8421
(
input wire sys_clk ,
input wire sys_rst_n ,
input wire [26:0] data ,
output reg [3:0] in , //个
output reg [3:0] ten , //十
output reg [3:0] hun , //百
output reg [3:0] tho , //千
output reg [3:0] ten_tho , //万
output reg [3:0] hun_tho , //十万
output reg [3:0] mil , //百万
output reg [3:0] must //千万
);
reg [4:0] cnt_shift ;
reg [58:0] data_shift ;
reg shift_flag ;
always@(posedge sys_clk or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
cnt_shift <= 5'd0;
else if((cnt_shift == 5'd28) && (shift_flag == 1'b1))
cnt_shift <= 5'd0;
else if(shift_flag == 1'b1)
cnt_shift <= cnt_shift + 1'b1;
else
cnt_shift <= cnt_shift;
always@(posedge sys_clk or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
data_shift <= 59'd0;
else if(cnt_shift == 5'd0)
data_shift <= {32'b0,data};
else if((cnt_shift <= 5'd27) && (shift_flag == 1'b0))
begin
data_shift[30:27] <= (data_shift[30:27] > 4) ? (data_shift[30:27] + 2'd3) : (data_shift[30:27]);
data_shift[34:31] <= (data_shift[34:31] > 4) ? (data_shift[34:31] + 2'd3) : (data_shift[34:31]);
data_shift[38:35] <= (data_shift[38:35] > 4) ? (data_shift[38:35] + 2'd3) : (data_shift[38:35]);
data_shift[42:39] <= (data_shift[42:39] > 4) ? (data_shift[42:39] + 2'd3) : (data_shift[42:39]);
data_shift[46:43] <= (data_shift[46:43] > 4) ? (data_shift[46:43] + 2'd3) : (data_shift[46:43]);
data_shift[50:47] <= (data_shift[50:47] > 4) ? (data_shift[50:47] + 2'd3) : (data_shift[50:47]);
data_shift[54:51] <= (data_shift[54:51] > 4) ? (data_shift[54:51] + 2'd3) : (data_shift[54:51]);
data_shift[58:55] <= (data_shift[58:55] > 4) ? (data_shift[58:55] + 2'd3) : (data_shift[58:55]);
end
else if((cnt_shift <= 5'd27) && (shift_flag == 1'b1))
data_shift <= data_shift << 1;
else
data_shift <= data_shift;
always@(posedge sys_clk or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
shift_flag <= 1'b0;
else
shift_flag <= ~shift_flag;
always@(posedge sys_clk or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
begin
in <= 4'b0;
ten <= 4'b0;
hun <= 4'b0;
tho <= 4'b0;
ten_tho <= 4'b0;
hun_tho <= 4'b0;
mil <= 4'b0;
must <= 4'b0;
end
else if(cnt_shift == 5'd28)
begin
in <= data_shift[30:27];
ten <= data_shift[34:31];
hun <= data_shift[38:35];
tho <= data_shift[42:39];
ten_tho <= data_shift[46:43];
hun_tho <= data_shift[50:47];
mil <= data_shift[54:51];
must <= data_shift[58:55];
end
endmodule
1.2.3 tb_bcd_8421.v文件
`timescale 1ns/1ns
module tb_bcd_8421();
//声明变量
reg sys_clk ;
reg sys_rst_n ;
reg [26:0] data ;
wire [3:0] in ;
wire [3:0] ten ;
wire [3:0] hun ;
wire [3:0] tho ;
wire [3:0] ten_tho ;
wire [3:0] hun_tho ;
wire [3:0] mil ;
wire [3:0] must ;
//初始化
initial
begin
sys_clk = 1'b1;
sys_rst_n <= 1'b0;
data <= 27'd0;
#30
sys_rst_n <= 1'b1;
data <= 27'd12_345_678;
#3000
data <= 27'd87_654_321;
#3000
data <= 27'd98_765_432;
#3000
data <= 27'd99_999_999;
end
always #10 sys_clk = ~sys_clk;
bcd_8421 bcd_8421_inst
(
.sys_clk (sys_clk ),
.sys_rst_n (sys_rst_n),
.data (data ),
.in (in ), //个
.ten (ten ), //十
.hun (hun ), //百
.tho (tho ), //千
.ten_tho (ten_tho ), //万
.hun_tho (hun_tho ), //十万
.mil (mil ), //百万
.must (must ) //千万
);
endmodule
1.3 将bcd_8421包装为seg_dynamic
此处需要注意的问题就是数据同步,即sel信号和seg信号必须保持同步,否则会发生显示错误
1.3.1 时序图
从时序图中可以看出,seg_data 随着 cnt_sel 变化,且1ms改变一次,滞后 cnt_sel 一个周期 10ns,这里是否会因为in~must 变化太快而无法读取到准确的数值?
这里不会,原因是 data 数据变化的周期是100ms,远远大于 flag_1ms 和 cnt_sel 信号 1ms 的改变,即使 seg_data 读取一个完整的数据需要8个周期8ms,最后传到 seg 的数据也是准确的。
若是 data 数据的变化太快,小于 8ms ,此时 seg 的数据会出错;但是这种情况下,数码管显示的画面人眼是无法识别的,只能看到不停闪烁。
1.3.2 seg_dynamic.v文件
module seg_dynamic
#(
parameter CNT_MAX = 17'd99_999
)
(
input wire sys_clk ,
input wire sys_rst_n ,
input wire [26:0] data ,
output reg [7:0] sel ,
output reg [7:0] seg
);
wire [3:0] in ;
wire [3:0] ten ;
wire [3:0] hun ;
wire [3:0] tho ;
wire [3:0] ten_tho ;
wire [3:0] hun_tho ;
wire [3:0] mil ;
wire [3:0] must ;
reg [3:0] seg_data ;
reg [2:0] cnt_sel ;
reg [16:0] cnt_1ms ;
reg flag_1ms ;
//cnt_1ms:1ms循环计数
always@(posedge sys_clk or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
cnt_1ms <= 17'd0;
else if(cnt_1ms == CNT_MAX)
cnt_1ms <= 17'd0;
else
cnt_1ms <= cnt_1ms + 1'b1;
//flag_1ms:1ms标志信号
always@(posedge sys_clk or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
flag_1ms <= 1'b0;
else if(cnt_1ms == CNT_MAX - 1'b1)
flag_1ms <= 1'b1;
else
flag_1ms <= 1'b0;
//cnt_sel:从0到7循环数,用于选择当前显示的数码管
always@(posedge sys_clk or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
cnt_sel <= 3'd0;
else if((cnt_sel == 3'd7) && (flag_1ms == 1'b1))
cnt_sel <= 3'd0;
else if(flag_1ms == 1'b1)
cnt_sel <= cnt_sel + 1'b1;
else
cnt_sel <= cnt_sel;
always@(posedge sys_clk or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
seg_data <= 8'b0000_0011;
else
begin
case(cnt_sel)
3'd0: seg_data <= in ;
3'd1: seg_data <= ten ;
3'd2: seg_data <= hun ;
3'd3: seg_data <= tho ;
3'd4: seg_data <= ten_tho;
3'd5: seg_data <= hun_tho;
3'd6: seg_data <= mil ;
3'd7: seg_data <= must ;
endcase
end
always@(posedge sys_clk or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
sel <= 8'b0111_1111;
else if(flag_1ms == 1'b1)
begin
case(cnt_sel)
3'd0: sel <= 8'b1111_1110;
3'd1: sel <= 8'b1111_1101;
3'd2: sel <= 8'b1111_1011;
3'd3: sel <= 8'b1111_0111;
3'd4: sel <= 8'b1110_1111;
3'd5: sel <= 8'b1101_1111;
3'd6: sel <= 8'b1011_1111;
3'd7: sel <= 8'b0111_1111;
endcase
end
always@(posedge sys_clk or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
seg <= 8'b0000_0011;
else if(flag_1ms == 1'b1)
begin
case(seg_data)
4'd0: seg <= 8'b0000_0011;
4'd1: seg <= 8'b1001_1111;
4'd2: seg <= 8'b0010_0101;
4'd3: seg <= 8'b0000_1101;
4'd4: seg <= 8'b1001_1001;
4'd5: seg <= 8'b0100_1001;
4'd6: seg <= 8'b0100_0001;
4'd7: seg <= 8'b0001_1111;
4'd8: seg <= 8'b0000_0001;
4'd9: seg <= 8'b0000_1001;
endcase
end
else
seg <= seg;
bcd_8421 bcd_8421_inst
(
.sys_clk (sys_clk ),
.sys_rst_n (sys_rst_n),
.data (data ),
.in (in ), //个
.ten (ten ), //十
.hun (hun ), //百
.tho (tho ), //千
.ten_tho (ten_tho ), //万
.hun_tho (hun_tho ), //十万
.mil (mil ), //百万
.must (must ) //千万
);
endmodule
1.3.3 tb_seg_dynamic.v文件
`timescale 1ns/1ns
module tb_seg_dynamic();
reg sys_clk ;
reg sys_rst_n ;
reg [26:0] data ;
wire [7:0] sel ;
wire [7:0] seg ;
initial
begin
sys_clk = 1'b0;
sys_rst_n = 1'b0;
data <= 27'd0;
#20
sys_rst_n = 1'b1;
end
always #10 sys_clk = ~sys_clk;
seg_dynamic
#(
.CNT_MAX(17'd99_999)
)
seg_dynamic_inst
(
.sys_clk (sys_clk ),
.sys_rst_n (sys_rst_n),
.data (data ),
.sel (sel ),
.seg (seg )
);
endmodule
1.3.4 sel信号和seg信号不同步的问题
always@(posedge sys_clk or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
sel <= 8'b0111_1111;
else if(flag_1ms == 1'b1)
begin
case(cnt_sel)
3'd0: sel <= 8'b1111_1110;
3'd1: sel <= 8'b1111_1101;
3'd2: sel <= 8'b1111_1011;
3'd3: sel <= 8'b1111_0111;
3'd4: sel <= 8'b1110_1111;
3'd5: sel <= 8'b1101_1111;
3'd6: sel <= 8'b1011_1111;
3'd7: sel <= 8'b0111_1111;
endcase
end
当此处语句缺少
if(flag_1ms == 1’b1)
会产生不同步,时序图会发生下面的变化,数码管会从第二位开始显示,第一位保持为0,发生显示错误
1.4 将seg_dynamic和data_gen包装为top_seg_dynamic
1.4.1 top_seg_dynamic文件
module top_seg_dynamic
(
input wire sys_clk ,
input wire sys_rst_n ,
output wire [7:0] sel ,
output wire [7:0] seg
);
wire [26:0] data ;
data_gen
#(
.CNT_100MS_MAX (27'd99_999_999),
.DATA_MAX (27'd99_999_999)
)
data_gen_inst
(
.sys_clk (sys_clk ),
.sys_rst_n (sys_rst_n),
.data (data )
);
seg_dynamic
#(
.CNT_MAX(17'd99_999)
)
seg_dynamic_inst
(
.sys_clk (sys_clk ),
.sys_rst_n (sys_rst_n),
.data (data ),
.sel (sel ),
.seg (seg )
);
endmodule
1.4.2 tb_top_seg_dynamic文件
`timescale 1ns/1ns
module tb_top_seg_dynamic();
reg sys_clk;
reg sys_rst_n;
wire [7:0] sel;
wire [7:0] seg;
//初始化
initial
begin
sys_clk = 1'b0;
sys_rst_n <= 1'b0;
#30
sys_rst_n <= 1'b1;
end
always #10 sys_clk = ~sys_clk;
//defparam top_seg_dynamic_inst.seg_dynamic_inst.CNT_MAX = 20'd5;
//defparam top_seg_dynamic_inst.data_gen_inst.CNT_MAX = 20'd5;
top_seg_dynamic top_seg_dynamic_inst
(
.sys_clk (sys_clk),
.sys_rst_n (sys_rst_n),
.sel (sel),
.seg (seg)
);
endmodule
2. NEXYS4_DDR迪芝伦XC7A100TCSG324-1型的原理图与管脚绑定
2.1相关原理图
数码管原理图
8个8位数码管,从左到右,且为共阳极数码管,即端口为低电平时点亮
片选信号为低电平时数码管亮
sel | U13 | K2 | T14 | P14 | J14 | T9 | J18 | J17 |
---|---|---|---|---|---|---|---|---|
片选 | AN7 | AN6 | AN5 | AN4 | AN3 | AN2 | AN1 | AN0 |
数码管的显示示意图
文章来源:https://www.toymoban.com/news/detail-409529.html
共阳极,低电平时点亮文章来源地址https://www.toymoban.com/news/detail-409529.html
T10 | R10 | K16 | K13 | P15 | T11 | L18 | H15 | ||
---|---|---|---|---|---|---|---|---|---|
seg | a | b | c | d | e | f | g | dp | 0h |
0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 1 | 03 |
1 | 1 | 0 | 0 | 1 | 1 | 1 | 1 | 1 | 9F |
2 | 0 | 0 | 1 | 0 | 0 | 1 | 0 | 1 | 25 |
3 | 0 | 0 | 0 | 0 | 1 | 1 | 0 | 1 | 0D |
4 | 1 | 0 | 0 | 1 | 1 | 0 | 0 | 1 | 99 |
5 | 0 | 1 | 0 | 0 | 1 | 0 | 0 | 1 | 49 |
6 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 1 | 41 |
7 | 0 | 0 | 0 | 1 | 1 | 1 | 1 | 1 | 1F |
8 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 01 |
9 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 1 | 09 |
A | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 1 | 11 |
B | 1 | 1 | 0 | 0 | 0 | 0 | 0 | 1 | C1 |
C | 0 | 1 | 1 | 0 | 0 | 0 | 1 | 1 | 63 |
D | 1 | 0 | 0 | 0 | 0 | 1 | 0 | 1 | 85 |
E | 0 | 1 | 1 | 0 | 0 | 0 | 0 | 1 | 61 |
F | 0 | 1 | 1 | 1 | 0 | 0 | 0 | 1 | 71 |
2.2 seg_dynamic.xdc文件
set_property IOSTANDARD LVCMOS33 [get_ports sys_clk]
set_property IOSTANDARD LVCMOS33 [get_ports sys_rst_n]
set_property IOSTANDARD LVCMOS33 [get_ports {seg[7]}]
set_property IOSTANDARD LVCMOS33 [get_ports {seg[6]}]
set_property IOSTANDARD LVCMOS33 [get_ports {seg[5]}]
set_property IOSTANDARD LVCMOS33 [get_ports {seg[4]}]
set_property IOSTANDARD LVCMOS33 [get_ports {seg[3]}]
set_property IOSTANDARD LVCMOS33 [get_ports {seg[2]}]
set_property IOSTANDARD LVCMOS33 [get_ports {seg[1]}]
set_property IOSTANDARD LVCMOS33 [get_ports {seg[0]}]
set_property IOSTANDARD LVCMOS33 [get_ports {sel[7]}]
set_property IOSTANDARD LVCMOS33 [get_ports {sel[6]}]
set_property IOSTANDARD LVCMOS33 [get_ports {sel[5]}]
set_property IOSTANDARD LVCMOS33 [get_ports {sel[4]}]
set_property IOSTANDARD LVCMOS33 [get_ports {sel[3]}]
set_property IOSTANDARD LVCMOS33 [get_ports {sel[2]}]
set_property IOSTANDARD LVCMOS33 [get_ports {sel[1]}]
set_property IOSTANDARD LVCMOS33 [get_ports {sel[0]}]
set_property PACKAGE_PIN E3 [get_ports sys_clk]
set_property PACKAGE_PIN J15 [get_ports sys_rst_n]
set_property PACKAGE_PIN J17 [get_ports {sel[0]}]
set_property PACKAGE_PIN J18 [get_ports {sel[1]}]
set_property PACKAGE_PIN T9 [get_ports {sel[2]}]
set_property PACKAGE_PIN J14 [get_ports {sel[3]}]
set_property PACKAGE_PIN P14 [get_ports {sel[4]}]
set_property PACKAGE_PIN T14 [get_ports {sel[5]}]
set_property PACKAGE_PIN K2 [get_ports {sel[6]}]
set_property PACKAGE_PIN U13 [get_ports {sel[7]}]
set_property PACKAGE_PIN H15 [get_ports {seg[0]}]
set_property PACKAGE_PIN L18 [get_ports {seg[1]}]
set_property PACKAGE_PIN T11 [get_ports {seg[2]}]
set_property PACKAGE_PIN P15 [get_ports {seg[3]}]
set_property PACKAGE_PIN K13 [get_ports {seg[4]}]
set_property PACKAGE_PIN K16 [get_ports {seg[5]}]
set_property PACKAGE_PIN R10 [get_ports {seg[6]}]
set_property PACKAGE_PIN T10 [get_ports {seg[7]}]
到了这里,关于NEXYS4_DDR迪芝伦XC7A100TCSG324-1型,点亮板载的8个8位数码管的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!