NEXYS4_DDR迪芝伦XC7A100TCSG324-1型,点亮板载的8个8位数码管

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次,添加 4
2 = 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位数码管,从左到右,且为共阳极数码管,即端口为低电平时点亮
片选信号为低电平时数码管亮

selU13K2T14P14J14T9J18J17
片选AN7AN6AN5AN4AN3AN2AN1AN0

数码管的显示示意图
在这里插入图片描述

共阳极,低电平时点亮

T10R10K16K13P15T11L18H15
segabcdefgdp0h
00000001103
1100111119F
20010010125
3000011010D
41001100199
50100100149
60100000141
7000111111F
80000000101
90000100109
A0001000111
B11000001C1
C0110001163
D1000010185
E0110000161
F0111000171

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]}]


  • 4
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值