为了给电脑腾出空间,加之数电实验成绩已出,因而准备卸载 Vivado 这个占据 44.70GB 体积的集成环境。😅

之前在这门课也花了不少的精力去琢磨,因此在软件卸载之前,在本篇文章中留下自己的一点学习记录吧,项目的相关核心源码也存放到我的仓库了(大佬们不妨给个Star⭐️吧~)

实验环境

实验内容

  1. 设计可控进制的计数器:在输入控制变量的作用下实现计数器。在输入 0 时工作在 8 进制;在输入 1 时工作在 15 进制。

  2. 用数码管显示输出结果。

实验原理

输入变量

  • 一位二进制 opt ,代表进制选择:opt=0,则工作 8 进制;opt=1,则工作在 15 进制;
  • 一位二进制 clk ,代表时钟信号,为更好地演示效果,将时钟信号映射到开发板的按钮 P17
  • 一位二进制 rst ,用于异步清零;

输出变量

  • 八位二进制 dis ,代表电路当前的计数状态

功能分析

  • 当 opt=0 时,电路工作在 8 进制,每当接收到上升沿的时钟信号,电路计数状态 cnt 就会加一,同时,数码管会显示当前计数状态对应的数字。直到计满 8 个状态即 cnt=0111 时,电路在下一个上升沿的时钟信号下,就会自动地清零。

  • 当 opt=1 时,电路工作在 15 进制,每当接收到上升沿的时钟信号,电路计数状态 cnt 就会加一,同时,数码管会显示当前计数状态对应的数字。直到计满 15 个状态即 cnt=1110 时,电路在下一个上升沿的时钟信号下,就会自动地清零。

实验过程

Verilog 源代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer: Joy Dee
//
// Create Date: 2021/06/16 15:16:32
// Design Name: 可控进制的计数器
// Module Name: ControllableCounter
//
//////////////////////////////////////////////////////////////////////////////////

module ControllableCounter(
input opt,
input clk,
input rst,
output reg[7:0] dis
);

reg[3:0] cnt;

initial cnt = 0;

always @(posedge clk or posedge rst)
begin
if(rst) //异步清零
begin
cnt = 4'b0000;
end
else
begin
if(!opt) //8进制
begin
if(cnt == 4'b0111)
begin //进位
cnt = 4'b0000;
end

else
begin
cnt = cnt + 4'b0001;
end
end
else //15进制
begin
if(cnt == 4'b1110)
begin //进位
cnt = 4'b0000;
end

else
begin
cnt = cnt + 4'b0001;
end
end
end
end

wire[7:0] AN;

assign AN = 8'b00000000;
always @(*) begin
case (cnt)
4'b0000: dis = 8'b00000011; //0
4'b0001: dis = 8'b10011111; //1
4'b0010: dis = 8'b00100101; //2
4'b0011: dis = 8'b00001101; //3
4'b0100: dis = 8'b10011001; //4
4'b0101: dis = 8'b01001001; //5
4'b0110: dis = 8'b01000001; //6
4'b0111: dis = 8'b00011111; //7
4'b1000: dis = 8'b00000001; //8
4'b1001: dis = 8'b00001001; //9
4'b1010: dis = 8'b00010001; //A
4'b1011: dis = 8'b11000001; //b
4'b1100: dis = 8'b01100011; //C
4'b1101: dis = 8'b10000101; //d
4'b1110: dis = 8'b01100001; //E
4'b1111: dis = 8'b01110001; //F
default: dis = 8'b10000001; //0
endcase
end
endmodule

仿真

仿真源代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer: Joy Dee
//
// Create Date: 2021/06/16 23:41:27
// Design Name: 可控进制的计数器的仿真代码
// Module Name: ControllableCounter_sim
//
//////////////////////////////////////////////////////////////////////////////////

module ControllableCounter_sim();
reg opt;
reg clk;
reg rst;
wire[7:0] dis;
FinalCounter test(
.opt(opt),
.clk(clk),
.rst(rst),
.dis(dis)
);
initial
begin
clk = 0;
rst = 0;
opt = 0;
end
always #20 clk = ~clk;
endmodule

分析

  • 如下图,当 opt=0 时,每当上升沿的时钟信号到来时,电路计数状态加 1 ,并对应到相应的数码管数字,当第 8 个时钟信号到来时,电路计数状态就会清零;

    注意,图中 dis 值对应的含义是七段数码管显示的数字(包括了小数点位)

  • 如下图,当 opt=1 时,每当上升沿的时钟信号到来时,电路计数状态加 1 ,并对应到相应的数码管数字,当第 15 个时钟信号到来时,电路计数状态就会清零;

约束文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
##Buttons
set_property -dict { PACKAGE_PIN P17 IOSTANDARD LVCMOS33 } [get_ports { clk }]; #IO_L9N_T1_DQS_D13_14 Sch=btnd
set_property -dict { PACKAGE_PIN P18 IOSTANDARD LVCMOS33 } [get_ports { rst }]; #IO_L9N_T1_DQS_D13_14 Sch=btnd
set_property CLOCK_DEDICATED_ROUTE FALSE [get_nets clk]

##Switches
set_property -dict { PACKAGE_PIN J15 IOSTANDARD LVCMOS33 } [get_ports { opt }]; #IO_L24N_T3_RS0_15 Sch=sw[0]

##7 segment display
set_property -dict { PACKAGE_PIN T10 IOSTANDARD LVCMOS33 } [get_ports { dis[7] }]; #IO_L24N_T3_A00_D16_14 Sch=ca
set_property -dict { PACKAGE_PIN R10 IOSTANDARD LVCMOS33 } [get_ports { dis[6] }]; #IO_25_14 Sch=cb
set_property -dict { PACKAGE_PIN K16 IOSTANDARD LVCMOS33 } [get_ports { dis[5] }]; #IO_25_15 Sch=cc
set_property -dict { PACKAGE_PIN K13 IOSTANDARD LVCMOS33 } [get_ports { dis[4] }]; #IO_L17P_T2_A26_15 Sch=cd
set_property -dict { PACKAGE_PIN P15 IOSTANDARD LVCMOS33 } [get_ports { dis[3] }]; #IO_L13P_T2_MRCC_14 Sch=ce
set_property -dict { PACKAGE_PIN T11 IOSTANDARD LVCMOS33 } [get_ports { dis[2] }]; #IO_L19P_T3_A10_D26_14 Sch=cf
set_property -dict { PACKAGE_PIN L18 IOSTANDARD LVCMOS33 } [get_ports { dis[1] }]; #IO_L4P_T0_D04_14 Sch=cg
set_property -dict { PACKAGE_PIN H15 IOSTANDARD LVCMOS33 } [get_ports { dis[0] }]; #IO_L19N_T3_A21_VREF_15 Sch=dp

set_property -dict { PACKAGE_PIN J17 IOSTANDARD LVCMOS33 } [get_ports { AN[0] }]; #IO_L23P_T3_FOE_B_15 Sch=an[0]
set_property -dict { PACKAGE_PIN J18 IOSTANDARD LVCMOS33 } [get_ports { AN[1] }]; #IO_L23N_T3_FWE_B_15 Sch=an[1]
set_property -dict { PACKAGE_PIN T9 IOSTANDARD LVCMOS33 } [get_ports { AN[2] }]; #IO_L24P_T3_A01_D17_14 Sch=an[2]
set_property -dict { PACKAGE_PIN J14 IOSTANDARD LVCMOS33 } [get_ports { AN[3] }]; #IO_L19P_T3_A22_15 Sch=an[3]
set_property -dict { PACKAGE_PIN P14 IOSTANDARD LVCMOS33 } [get_ports { AN[4] }]; #IO_L8N_T1_D12_14 Sch=an[4]
set_property -dict { PACKAGE_PIN T14 IOSTANDARD LVCMOS33 } [get_ports { AN[5] }]; #IO_L14P_T2_SRCC_14 Sch=an[5]
set_property -dict { PACKAGE_PIN K2 IOSTANDARD LVCMOS33 } [get_ports { AN[6] }]; #IO_L23P_T3_35 Sch=an[6]
set_property -dict { PACKAGE_PIN U13 IOSTANDARD LVCMOS33 } [get_ports { AN[7] }]; #IO_L23N_T3_A02_D18_14 Sch=an[7]

开发板运行

当 opt=0 时,此时电路工作在八进制。

最初,电路计数状态为 0000 ,故数码管显示数字为“0”。

感谢为神献出黄金左手帮我操作

当按下 P17 按钮时,电路接收到一个新的脉冲,电路计数状态加1,此时计数状态变为 0001,映射到数码管显示数字为“1”。

如下图,此时电路计数状态为最后的状态,cnt=0111,映射到数码管显示数字为“7”

当下一个脉冲信号到来时,电路已经计满8个状态,此时电路计数状态清零,故数码管显示数字为“0”;

将J15开关打开,此时opt=1,电路工作在15进制。

按下P17按键,电路接收脉冲,电路计数状态加1。如下图,电路计数状态已达到第12个状态(即cnt=1100),此时数码管显示数字为16进制的“C”

此时,电路已经计满15个计数状态,数码管显示“E”,代表cnt=0110

电路再接收新的脉冲信号时,由于电路计数状态已计满15个状态,此时电路将会清零,回归到起点。