Lab7_时序逻辑验证
一、简易电子时钟
-
功能描述:
设计一简易电子时钟,支持时、分、秒显示,其中HEX7-HEX6显示时,HEX5-HEX4显示分,HEX1-HEX0显示秒,假设进制为:18秒=1分钟;13分钟=1小时;9小时=1天。 -
设计方案:
首先,设计三个寄存器分别用来存储当前时、分、秒的计时结果,并将秒级作为最低级,进行嵌套循环:
①每逢时钟上升沿,秒加一,并对其进行判断,若符合进位条件,则该位置零,同时上一位加一;若上一位同时也符合进位条件,则继续向上一位进位。
②时钟上升沿出现的时间间隔为1s,则对应时钟频率为1Hz,初始时钟采用开发板自带的50MHz振荡器,对该信号进行分频,其中M=50M -
关键代码:
module elec_clk(
input clk,
output reg [7:0] second=8'b00000000,
output reg [7:0] minute=8'b00000000,
output reg [7:0] hour=8'b00000000);
always@(posedge clk) begin
second <= second + 8'b00000001;
if(second == 8'b00010001) begin //second:18
second <= 8'b00000000;
minute <= minute + 8'b00000001;
if(minute == 8'b00001100) begin //minute:13
minute <= 8'b00000000;
hour <= hour + 8'b00000001;
if(hour == 8'b00001000) //hour:9
hour <= 8'b00000000;
end
end
end
endmodule
module fpga_clk(
input CLOCK_50,
output [6:0] HEX0,
output [6:0] HEX1,
output [6:0] HEX4,
output [6:0] HEX5,
output [6:0] HEX6,
output [6:0] HEX7);
wire clock;
wire [7:0] second_bin;
wire [7:0] second_bcd;
wire [7:0] minute_bin;
wire [7:0] minute_bcd;
wire [7:0] hour_bin;
wire [7:0] hour_bcd;
clk_div U0(
.clk(CLOCK_50),
.rstn(1),
.clk_out(clock));
elec_clk U1(
.clk(clock),
.second(second_bin),
.minute(minute_bin),
.hour(hour_bin));
bin2bcd U3(
.bin_code(second_bin),
.bcd_code(second_bcd));
bin2bcd U4(
.bin_code(minute_bin),
.bcd_code(minute_bcd));
bin2bcd U5(
.bin_code(hour_bin),
.bcd_code(hour_bcd));
led_display H0(
.ctrl(0),
.data(hour_bcd[3:0]),
.dev0(HEX6));
led_display H1(
.ctrl(0),
.data(hour_bcd[7:4]),
.dev0(HEX7));
led_display M0(
.ctrl(0),
.data(minute_bcd[3:0]),
.dev0(HEX4));
led_display M1(
.ctrl(0),
.data(minute_bcd[7:4]),
.dev0(HEX5));
led_display S0(
.ctrl(0),
.data(second_bcd[3:0]),
.dev0(HEX0));
led_display S1(
.ctrl(0),
.data(second_bcd[7:4]),
.dev0(HEX1));
endmodule
- 综合结果:
顶级模块的综合结果如图1,仅由分频模块和字符循环模块组成:
图1 顶级模块的综合结果
elec_clk模块的综合结果如图2:
图2 elec_clk模块的综合结果
summary结果如图3:
图3 summary结果
-
总结分析:
可以尝试将进位数据作为parameter,从而便于整个函数在后续过程中被调用。 -
运行结果:
另附视频。
二、七段管循环显示
- 功能描述:
①在8个七段管上循环显示字符串:BUAA_1952-2022_(其中_表示七段管全灭);
②同时四个LED灯(LEDR[14-7])随BUAA的移动而移动;
③SW[17]作为复位信号,高电平有效,LED灯全灭;
④SW[0]作为使能信号,高电平有效,七段管和LED灯正常循环,低电平时,二者暂停循环;
⑤循环显示时间间隔为0.5s,即每隔0.5s字符串向左移一位。
图4 显示示例
- 设计方案:
①循环显示的时间间隔为0.5s,我们选择每逢时钟上升沿进行一次移位,则对应时钟的频率为2Hz,初始时钟采用开发板自带的50MHz振荡器,对该信号进行分频,其中M=25M;
②使用一个长度为7N的寄存器变量来存储字符,每个字符占七位,同时考虑到复位信号有效时,能够回复到初始状态,则应分别创建一个初始寄存器来寄存初始字符串,另一个寄存器来存储循环移位的结果,与此同时设置一个7*8的寄存器用来存储七段管上字符情况;
③对于LED灯,可知不同循环阶段时对应的亮暗情况是不同的,这里选择用i循环的状态做标记,遍历出i的状态及相应的LED灯亮暗情况。 - 关键代码:
module str_display(
input clk,
input reset,
input ensignal,
input [104:0] str,
output reg [55:0] seven,
output reg [7:0] LED_state);
reg [104:0] shift_str;
reg [3:0] i=14;
always@(posedge clk) begin
if(reset) begin
shift_str[104 -: 105] <=str[104 -: 105];
seven[55 -: 56] <= 56'b1;
LED_state <= 8'b00000000;
end
else if(!ensignal) begin
shift_str[104 -: 105] <= shift_str[104 -: 105];
seven[55 -: 56] <= seven[55 -: 56];
LED_state <= LED_state;
end
else begin
seven[55:0] <= {seven[48 -: 49],shift_str[104 -: 7]};
shift_str[104:0] <= {shift_str[97 -: 98],shift_str[104 -: 7]};
case(i)
4'b1110: LED_state <= 8'b00000001;
4'b1101: LED_state <= 8'b00000011;
4'b1100: LED_state <= 8'b00000111;
4'b1011: LED_state <= 8'b00001111;
4'b1010: LED_state <= 8'b00011110;
4'b1001: LED_state <= 8'b00111100;
4'b1000: LED_state <= 8'b01111000;
4'b0111: LED_state <= 8'b11110000;
4'b0110: LED_state <= 8'b11100000;
4'b0101: LED_state <= 8'b11000000;
4'b0100: LED_state <= 8'b10000000;
default: LED_state <= 8'b00000000;
endcase
if(i==0)
i<=14;
else
i<=i-1'b1;
end
end
endmodule
module fpga_seven(
input CLOCK_50,
input [17:0] SW,
output [17:0] LEDR,
output [6:0] HEX0,
output [6:0] HEX1,
output [6:0] HEX2,
output [6:0] HEX3,
output [6:0] HEX4,
output [6:0] HEX5,
output [6:0] HEX6,
output [6:0] HEX7);
wire clk;
wire [55:0] seven;
wire [7:0] LED_state;
reg [104:0] str=105'b000000010000011001000100100011111111111001001000000100100100100011111101001001000000010010001001001111111;
clk_div U0(
.clk(CLOCK_50),
.rstn(1),
.clk_out(clk));
str_display U1(
.clk(clk),
.reset(SW[17]),
.ensignal(SW[0]),
.str(str),
.seven(seven),
.LED_state(LED_state));
assign LEDR[14 -: 8]=LED_state[7 -: 8];
assign HEX7=seven[55 -: 7];
assign HEX6=seven[48 -: 7];
assign HEX5=seven[41 -: 7];
assign HEX4=seven[34 -: 7];
assign HEX3=seven[27 -: 7];
assign HEX2=seven[20 -: 7];
assign HEX1=seven[13 -: 7];
assign HEX0=seven[6 -: 7];
endmodule
- 综合结果:
顶级模块的综合结果如图5,仅由分频模块和字符循环模块组成:
图5 顶级模块的综合结果
str_display模块的综合结果如图6:
图6 str_display模块的综合结果
7
图7 summary结果
-
总结分析:
最初进行设计时,将大部分功能的实现全部放在了顶级模块中,结果造成在调整思路时异常混乱,将功能模块和顶级模块的实现分开可以使得整体设计的脉络更加清晰,同时有利于在不同的电路中进行复用。 -
运行结果:
另附视频。