基于STEP-Baseboard-V4.0定时报警时钟设计
该项目使用了STEP-Baseboard-V4.0,实现了定时报警时钟的设计,它的主要功能为:基础时钟功能,设定报警时间功能,报警功能。
标签
FPGA
2024寒假在家一起练
STEP-MXO2-LPC
STEP-Baseboard-V4.0
Steven Kai
更新2024-04-01
重庆邮电大学
29

一.项目分析

该项目使硬禾推出的2024寒假在家一起练的项目,该项目的开发平台是STEP-Baseboard-V4.0,使用lattice的LCMXO2-4000HC-4MG132C芯片。

项目要求完成以下基本任务

设计一个能够显示时、分、秒钟的数字时钟,时间在7段数码管上显示。自定义扩展板上的矩阵按键调整数字时钟的时间并设定定时报警的时间,分别用四个键来控制分、时的增、减,将设定好的定时时间存储在EEPROM中,断电并再次上电以后(需要重新再调整当前时钟的时间)能够根据上次设定的定时报警的时间进行报警,到报警时间时蜂鸣器播放音乐5秒钟、核心板上的一颗RGB LED以呼吸灯的方式闪烁5秒钟,闪烁的过程中通过R、G、B颜色的不同组合显示不同颜色(类似警灯的效果)。

根据项目的要求提炼出一下设计要点:

1.能在数码管上显示时,分,秒的数字是时钟

2.能够使用矩阵按键设置时钟时间及报警时间

3.能够将设置好的报警时间存放在EEPROM中,并且在下次上电能够读取

4.当时钟走到报警时间时能够触发RGB灯和蜂鸣器报警

二.需求分析

根据上述的项目要求分析其设计需求用到的模块由数码管,RGB LED灯,矩阵按键,蜂鸣器,EEPROM。下面分器件分析其设计需求:

1.根据STEP-Baseboard-V4.0的原理图可知,数码管是由三个FPGA的io口控制两个串联的74HC595来控制数码管的显示,这样可以节省io口的使用数量,但增大了设计难度。因此在设计数码管显示时需要设计74HC595控制器。并且需要设计数码管的动态显示,需要通过轮询显示8个数码管来呈现8位不同的显示效果。

image.png

2.任务要求RGB LED呼吸灯,并且呈现警灯的效果,而且持续5秒,共三个要求。

实现警灯的效果可以控制RGB的三个io口分别呈现不同强度的红绿蓝三种颜色呈现警灯效果,警灯的效果是红蓝交替,因此控制红色和蓝色的交替闪烁即可。然后是呼吸灯,呼吸灯是采用PWM的原理,不同的占空比会让灯呈现不一样的亮度,通过递增或递减占空比即可实现呼吸灯。最后是限定在5秒的范围内,这个需求相对容易满足,可以通过记时的方式控制RGB LED闪烁5秒。

image.png

3.根据STEP-Baseboard-V4.0的原理图可知,板子上一共16个按键,四排四列,由8个io口控制,项目要求可以控制时钟和报警时间的设定,并且可以加减,若使用第一排的四个按键进行控制则需拉低ROW1,然后分别检测COL1,COL2,COL3,COL4。若为低则为按下,若为高则为没有按下。

image.png

4.项目要求蜂鸣器也和RGB LED灯一样在报警的时候能够以放音乐的形式响5秒,若要将蜂鸣器实现放音乐的效果和呼吸灯的原理一样只需控制蜂鸣器的电平以PWM的形式变化,PWM的方波的频率不同蜂鸣器响的音调也不同,就实现了放音乐的效果。

image.png

5.项目要求需要将定时的时间存放在EEPROM中,开发板上使用的EEPROM芯片是AT24C02,AT24C02存储容量为2k共分为8页,每页32个字节,每个字节8位数,该器件由I2C控制。I2C由数据线SDA和时钟线SCL组成,需要按照固定的时序读写器件。由原理图可知,在I2C总线上挂载了若干器件,其中AT24C02的器件地址为1010000。在进行读写操作时需要先发送器件地址确定与哪个器件通信。

image.png

三.实现方式

根据上述的需求分析将以上器件的控制依次实现,首先是时钟动态数码管的实现,将整体的实现分为time_count.v,time_num.v,divideer.v,seg_scan.v,hc595.v。其中time_count.v用于产生一秒的记时信号 ,time_count.v中可以接收按键1的信号,用于控制时钟的开始和停止。

time_count.v代码实现如下

module time_count(
input sys_clk,
input sys_rst_n,
input key_posedge1,
output reg second_flag
);

parameter COUNT_MAX = 26'd11_999_999;

reg [25:0] count;
reg key_count_flag;
reg flag;

always@(posedge sys_clk or negedge sys_rst_n) begin
if(!sys_rst_n)
flag <= 1'b1;
else if(key_posedge1)
flag <= ~flag;
end

always@(posedge sys_clk or negedge sys_rst_n) begin
if(!sys_rst_n)
count <= 26'd0;
else if(count == COUNT_MAX)
count <= 26'd0;
else if(flag == 1'b1)
count <= count + 1'd1;
else
count <=count;
end

always@(posedge sys_clk or negedge sys_rst_n) begin
if(!sys_rst_n)
second_flag <= 1'b0;
else if(count == COUNT_MAX)
second_flag <= 1'b1;
else
second_flag <= 1'b0;
end

endmodule

time_num是时钟实现的关键代码,这个模块通过输入的秒钟信号和三个控制时钟,报警事件的按键来输出时钟的时,分,秒,以及报警的时,分信号。其中key2用于控制调整哪个信号的大小,共有5个状态分别时时钟的秒,时钟的分,时钟的时,报警的分,报警的时,然后通过5个led灯标记这5中状态,分别对应STEP-MXO2-LPC上的led0,led1,led2,led3,led4。key3用于控制被选中信号的加,按一次就加一位,key4用于控制被选中信号的减,按一次就减一位。

time_num.v的代码实现如下:


module time_num(
input sys_clk,
input sys_rst_n,
input second_flag,
input key_posedge2,
input key_posedge3,
input key_posedge4,
output reg [5:0] second,
output reg [5:0] minute,
output reg [5:0] hour,
output reg [5:0] alarm_hour,
output reg [5:0] alarm_minute,
output wire alarm_posedge,
output wire [4:0] led
);

parameter SECOND_MAX = 6'd59;
parameter MINUTE_MAX = 6'd59;
parameter HOUR_MAX = 5'd23;

reg minute_flag;

reg hour_flag;

reg [4:0] num_flag;

assign alarm_posedge = num_flag[3] || num_flag[4];

assign led = ~num_flag;

always@(posedge sys_clk or negedge sys_rst_n) begin
if(!sys_rst_n)
num_flag <= 5'b00001;
else if(key_posedge2)
num_flag[4:0] <= {num_flag[3:0],num_flag[4]};
end

always@(posedge sys_clk or negedge sys_rst_n) begin
if(!sys_rst_n) begin
second <= 6'd40;
minute_flag <= 1'b0;
end
else if(second_flag||(num_flag[0]&key_posedge3))
if(second == SECOND_MAX) begin
second <= 6'd0;
minute_flag <= 1'b1;
end
else begin
second <= second + 1'd1;
minute_flag <= 1'b0;
end


else if(num_flag[0]&key_posedge4)
if(second == 6'd0) begin
second <= SECOND_MAX;
end
else begin
second <= second - 1'd1;
end


else begin
second <= second;
minute_flag <= 1'b0;
end
end

always@(posedge sys_clk or negedge sys_rst_n) begin
if(!sys_rst_n) begin
minute <= 6'd59;
hour_flag <= 1'b0;
end
else if(minute_flag||(num_flag[1]&&key_posedge3))
if(minute == MINUTE_MAX) begin
minute <= 6'd0;
hour_flag <= 1'b1;
end
else begin
minute <= minute + 1'd1;
hour_flag <= 1'b0;
end

else if(num_flag[1]&key_posedge4)
if(minute == 6'd0) begin
minute <= MINUTE_MAX;
end
else begin
minute <= minute - 1'd1;
end

else begin
minute <= minute;
hour_flag <= 1'b0;
end
end

always@(posedge sys_clk or negedge sys_rst_n) begin
if(!sys_rst_n)
hour <= 6'd23;
else if(hour_flag||(num_flag[2]&&key_posedge3))
if(hour == HOUR_MAX)
hour <= 6'd0;
else
hour <= hour + 6'd1;

else if(num_flag[2]&&key_posedge4)
if(hour == 6'd0)
hour <= HOUR_MAX;
else
hour <= hour - 6'd1;

else
hour <= hour;
end

always@(posedge sys_clk or negedge sys_rst_n) begin
if(!sys_rst_n) begin
alarm_minute <= 6'd0;
end
else if(num_flag[3]&&key_posedge3)
if(alarm_minute == MINUTE_MAX) begin
alarm_minute <= 6'd0;
end
else begin
alarm_minute <= alarm_minute + 1'd1;
end

else if(num_flag[3]&key_posedge4)
if(alarm_minute == 6'd0) begin
alarm_minute <= MINUTE_MAX;
end
else begin
alarm_minute <= alarm_minute - 1'd1;
end

else begin
alarm_minute <= alarm_minute;
end
end

always@(posedge sys_clk or negedge sys_rst_n) begin
if(!sys_rst_n)
alarm_hour <= 6'd0;
else if(num_flag[4]&&key_posedge3)
if(alarm_hour == HOUR_MAX)
alarm_hour <= 6'd0;
else
alarm_hour <= alarm_hour + 6'd1;

else if(num_flag[4]&&key_posedge4)
if(alarm_hour == 6'd0)
alarm_hour <= HOUR_MAX;
else
alarm_hour <= alarm_hour - 6'd1;

else
alarm_hour <= alarm_hour;
end
endmodule​

在产生时钟信号和报警信号后需要将其显示在数码管上,由于时钟信号和报警信号的数据是十进制的数码管是一位一位显示的,因此需要将十进制的数字转化为单个的二进制,由于lattice的开发工具不支持处罚,所以要使用其他办法转化,一种方法是使用BCD码,在这里因为信号数值最高为59不会超过三位数,因此这里使用了一个取巧的方法,在divider.v中将数据转化为6个单个的数据,其中data0是秒的个位,data1是秒的十位,data2是分的个位,data3是分的十位,data4是时的个位,data5是时的十位。

module divider(
input sys_clk,
input sys_rst_n,
input alarm_posedge,
input [5:0] second,
input [5:0] minute,
input [5:0] hour,
input [5:0] alarm_hour,
input [5:0] alarm_minute,
output [3:0] data0,
output reg [3:0] data1,
output [3:0] data2,
output reg [3:0] data3,
output [3:0] data4,
output reg [3:0] data5,
output reg alarm_flag
);

wire [5:0] data_tem1;
wire [5:0] data_tem3;
wire [5:0] data_tem5;

reg [5:0] seg_hour;
reg [5:0] seg_minute;
reg [5:0] seg_second;

always @(posedge sys_clk or negedge sys_rst_n) begin
if (!sys_rst_n)
alarm_flag = 1'b0;
else if((hour == alarm_hour)&&(minute == alarm_minute)&&(second <= 6'd5))
alarm_flag = 1'b1;
else
alarm_flag = 1'b0;
end

always @(posedge sys_clk or negedge sys_rst_n) begin
if(!sys_rst_n) begin
seg_hour <= hour;
seg_minute <= minute;
seg_second <= second;
end
else if(alarm_posedge==1'b1) begin
seg_hour <= alarm_hour;
seg_minute <= alarm_minute;
seg_second <= 6'd0;
end
else begin
seg_hour <= hour;
seg_minute <= minute;
seg_second <= second;
end

end

assign data0 = seg_second % 4'd10;

assign data2 = seg_minute % 4'd10;

assign data4 = seg_hour % 4'd10;

assign data_tem1 = seg_second - data0;

assign data_tem3 = seg_minute - data2;

assign data_tem5 = seg_hour - data4;

always@(posedge sys_clk or negedge sys_rst_n) begin
if(!sys_rst_n) begin
data1 <= 6'd0;
end
else begin
case (data_tem1)
6'd0 : data1 <= 4'd0;
6'd10 : data1 <= 4'd1;
6'd20 : data1 <= 4'd2;
6'd30 : data1 <= 4'd3;
6'd40 : data1 <= 4'd4;
6'd50 : data1 <= 4'd5;
default : data1 <= 4'd0;
endcase
end
end

always@(posedge sys_clk or negedge sys_rst_n) begin
if(!sys_rst_n) begin
data3 <= 6'd0;
end
else begin
case (data_tem3)
6'd0 : data3 <= 4'd0;
6'd10 : data3 <= 4'd1;
6'd20 : data3 <= 4'd2;
6'd30 : data3 <= 4'd3;
6'd40 : data3 <= 4'd4;
6'd50 : data3 <= 4'd5;
default : data3 <= 4'd0;
endcase
end
end

always@(posedge sys_clk or negedge sys_rst_n) begin
if(!sys_rst_n) begin
data5 <= 6'd0;
end
else begin
case (data_tem5)
6'd0 : data5 <= 4'd0;
6'd10 : data5 <= 4'd1;
6'd20 : data5 <= 4'd2;
6'd30 : data5 <= 4'd3;
6'd40 : data5 <= 4'd4;
6'd50 : data5 <= 4'd5;
default : data5 <= 4'd0;
endcase
end
end
endmodule

然后将六位的时分秒数据送入seg_scan.v模块中转化为8位的段选数据和8位的位选数据,其中seg_sel为位选,seg_led为位选。

seg_scan.v的代码实现如下:

module seg_scan(
input wire sys_clk,
input wire sys_rst_n,
input [3:0] data0,
input [3:0] data1,
input [3:0] data2,
input [3:0] data3,
input [3:0] data4,
input [3:0] data5,
output reg [7:0] seg_sel,
output reg [7:0] seg_led
);

reg data_flag;
reg [15:0] count2;
reg [3:0] data_display;

parameter DATA_MAX = 16'd10_000;

parameter num0 = 8'b0011_1111;
parameter num1 = 8'b0000_0110;
parameter num2 = 8'b0101_1011;
parameter num3 = 8'b0100_1111;
parameter num4 = 8'b0110_0110;
parameter num5 = 8'b0110_1101;
parameter num6 = 8'b0111_1101;
parameter num7 = 8'b0000_0111;
parameter num8 = 8'b0111_1111;
parameter num9 = 8'b0110_1111;
parameter lever = 8'b0100_0000;
parameter idle = 8'b0000_0000;

always@(posedge sys_clk or negedge sys_rst_n) begin
if(!sys_rst_n)
count2 <= 0;
else if(count2 == DATA_MAX)
count2 <= 0;
else
count2 <= count2 + 1'b1;
end

always@(posedge sys_clk or negedge sys_rst_n) begin
if(!sys_rst_n)
data_flag <= 0;
else if(count2 == DATA_MAX)
data_flag <=1;
else
data_flag <=0;
end

always@(posedge sys_clk or negedge sys_rst_n) begin
if(!sys_rst_n)
seg_sel <= 8'b1111_1110;
else if(data_flag)
seg_sel[7:0] <= {seg_sel[6:0],seg_sel[7]};
end

always@(posedge sys_clk or negedge sys_rst_n) begin
if(!sys_rst_n)
data_display <= 4'b0;
else
case (seg_sel)
8'b1111_1110 :data_display <= data5;
8'b1111_1101 :data_display <= data4;
8'b1111_1011 :data_display <= 4'd10;
8'b1111_0111 :data_display <= data3;
8'b1110_1111 :data_display <= data2;
8'b1101_1111 :data_display <= 4'd10;
8'b1011_1111 :data_display <= data1;
8'b0111_1111 :data_display <= data0;
default : data_display <= 4'b0;
endcase
end

always@(posedge sys_clk or negedge sys_rst_n) begin
if(!sys_rst_n)
seg_led <= idle;
else begin
case (data_display)
4'h0: seg_led <= num0;
4'h1: seg_led <= num1;
4'h2: seg_led <= num2;
4'h3: seg_led <= num3;
4'h4: seg_led <= num4;
4'h5: seg_led <= num5;
4'h6: seg_led <= num6;
4'h7: seg_led <= num7;
4'h8: seg_led <= num8;
4'h9: seg_led <= num9;
4'd10 : seg_led <= lever;
default : seg_led <= idle;
endcase

end
end
endmodule

然后通过hc595.v模块接收8位段选和8位位选信号控制板子上的两个串联595芯片控制数码管的动态显示。

hc595.v的代码实现如下:

module hc595
(
input sys_clk,
input sys_rst_n,
input [7:0] seg_led,
input [7:0] seg_sel,
output reg DIN, //数据输出引脚
output reg SCK, //移位寄存
output reg RCK //存储寄存
);

reg [3:0] time_1MZ;//12分频计数1MZ
reg [3:0] data_count;
wire [15:0] data;

assign data={seg_sel[0],seg_sel[1],seg_sel[2],seg_sel[3],seg_sel[4],seg_sel[5],seg_sel[6],seg_sel[7],seg_led[0],seg_led[1],seg_led[2],seg_led[3],seg_led[4],seg_led[5],seg_led[6],seg_led[7]};

always @(posedge sys_clk or negedge sys_rst_n) begin
if(!sys_rst_n)
time_1MZ <= 4'd0;
else if(time_1MZ==4'd11)
time_1MZ <= 4'd0;
else
time_1MZ <= time_1MZ +4'd1;
end

always @(posedge sys_clk or negedge sys_rst_n) begin
if(!sys_rst_n)
data_count <= 4'd0;
else if(time_1MZ == 4'd11 && data_count ==4'd15)
data_count <= 4'd0;
else if(time_1MZ ==4'd11)
data_count <= data_count + 4'd1;
else
data_count <= data_count;
end
//移位12分频信号
always @(posedge sys_clk or negedge sys_rst_n) begin
if(!sys_rst_n)
SCK <= 1'b0;
else if(time_1MZ >= 4'd10)
SCK <= 1'b1;
else
SCK <= 1'b0;
end

//存储信号
always @(posedge sys_clk or negedge sys_rst_n) begin
if(!sys_rst_n)
RCK <= 1'b0;
else if(time_1MZ == 4'd11 && data_count ==4'd15)
RCK <= 1'b1;
else
RCK <= 1'b0;
end

//移位存入信号
always @(posedge sys_clk or negedge sys_rst_n) begin
if(!sys_rst_n)
DIN <= 1'b0;
else if(time_1MZ == 4'd0)
DIN <= data[data_count];
else
DIN <= DIN;
end
endmodule

然后是实现RGB LED的控制这部分相对比较简单通过控制三个口产生占空比不断变化的PWM波控制RGB LED灯以呼吸警灯的形式闪烁。

RGB_LED.v的实现代码如下:

module RGB_LED
(
input sys_clk,
input sys_rst_n,
input alarm_flag,
output reg [2:0] rgb
);

reg [25:0] counter_1s;
reg [15:0] counter_1ms;
reg [15:0] duty_num;
reg flag;

always @(posedge sys_clk or negedge sys_rst_n) begin
if(!sys_rst_n)
counter_1s <= 26'd0;
else if (counter_1s<26'd4800_0000)
counter_1s <=counter_1s +1'd1;
else
counter_1s<=26'd0;
end

always @(posedge sys_clk or negedge sys_rst_n) begin
if(!sys_rst_n)
counter_1ms <= 16'd0;
else if (counter_1ms<16'd12_000)
counter_1ms <=counter_1ms +1'd1;
else
counter_1ms<=24'd0;
end

always @(posedge sys_clk or negedge sys_rst_n) begin
if(!sys_rst_n) begin
duty_num <= 16'd0;
flag <= 1'b0;
end
else begin
if(counter_1ms == 16'd12_000) begin
if(flag == 1'b0) begin
if(duty_num == 16'd12_000)
flag <=1'b1;
else
duty_num <= duty_num + 16'd12;
end
else begin
if(duty_num == 16'd0)
flag <= 1'b0;
else
duty_num <= duty_num - 16'd12;
end
end
end
end

always @(posedge sys_clk or negedge sys_rst_n) begin
if(!sys_rst_n)
rgb <= 3'd7;
else if(counter_1s < 26'd2400_0000) begin
if((counter_1ms > duty_num)&&(alarm_flag))
rgb <= 3'd3;
else
rgb <= 3'd7;
end
else if(counter_1s > 26'd2400_0000) begin
if((counter_1ms > duty_num)&&(alarm_flag))
rgb <= 3'd6;
else
rgb <= 3'd7;
end
else
rgb <=3'd7;
end
endmodule

然后时蜂鸣器的实现原理与RGB基本相同

buzzer.v的代码实现如下:

module  buzzer
#(
parameter TIME_500MS = 25'd11999999,
parameter DO = 18'd95839 ,
parameter RE = 18'd85067 ,
parameter MI = 18'd75514 ,
parameter FA = 18'd71265 ,
parameter SO = 18'd63550 ,
parameter LA = 18'd56635 ,
parameter XI = 18'd50214
)
(
input wire sys_clk,
input wire sys_rst_n,
input wire alarm_flag,
output reg beep
);

reg [24:0] cnt;
reg [17:0] freq_cnt;
reg [2:0] cnt_500ms;
reg [17:0] freq_data;

wire [16:0] duty_data ;

assign duty_data = freq_data >> 1'b1;

always@(posedge sys_clk or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
cnt <= 25'd0;
else if(cnt == TIME_500MS )
cnt <= 25'd0;
else
cnt <= cnt + 1'b1;
always@(posedge sys_clk or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
cnt_500ms <= 3'd0;
else if(cnt == TIME_500MS && cnt_500ms == 6)
cnt_500ms <= 3'd0;
else if(cnt == TIME_500MS)
cnt_500ms <= cnt_500ms + 1'b1;

always@(posedge sys_clk or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
freq_data <= DO;
else case(cnt_500ms)
0: freq_data <= DO;
1: freq_data <= RE;
2: freq_data <= MI;
3: freq_data <= FA;
4: freq_data <= SO;
5: freq_data <= LA;
6: freq_data <= XI;
default: freq_data <= DO;
endcase

always@(posedge sys_clk or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
freq_cnt <= 18'd0;
else if(freq_cnt == freq_data || cnt == TIME_500MS)
freq_cnt <= 18'd0;
else
freq_cnt <= freq_cnt + 1'b1;

always@(posedge sys_clk or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
beep <= 1'b0;
else if((freq_cnt >= duty_data)&&alarm_flag)
beep <= 1'b1;
else if((freq_cnt <= duty_data)&&alarm_flag)
beep <= 1'b0;
else
beep <= 1'b0;

endmodule

然后是矩阵按键的实现,在将ROW1拉低之后和普通按键的检测方式一样,这里为了按键的稳定为按键模块进行消抖。

key.v的代码实现如下:

module key
(
input wire sys_clk,
input wire sys_rst_n,
input wire key_in,
output reg key_posedge
);

reg key_flag;
reg key_value;
reg [19:0] cnt;
parameter CNT_MAX = 20'd999_999;
reg key_reg;
reg key_value_d;
always @(posedge sys_clk or negedge sys_rst_n) begin
if (!sys_rst_n) begin
key_reg <= 1'b1;
cnt <= 20'd0;
end
else begin
key_reg <= key_in;
if(key_reg != key_in)
cnt <= 20'd0;
else if(key_reg == key_in) begin
if(cnt == CNT_MAX)
cnt <= cnt;
else
cnt <= cnt + 1'd1;
end
end
end

always @(posedge sys_clk or negedge sys_rst_n) begin
if (!sys_rst_n) begin
key_flag <= 1'b0;
key_value <= 1'b1;
end
else begin
if(cnt == CNT_MAX) begin
key_flag <= 1'b1;
key_value <= key_in;
end
else begin
key_flag <= 1'b0;
key_value <= key_value;
end
end
end

always @(posedge sys_clk or negedge sys_rst_n) begin
if(!sys_rst_n)
key_posedge <= 1'b0;
else begin
key_value_d <= key_value;
key_posedge <= ~key_value_d&key_value;
end

end
endmodule

在读写EEPROM中遇到了问题读写时序复杂在经过几天的尝试之后写出来的代码都不能正常运行,时间也不太够了就只做到了这里。

下面是整个模块的顶层模块的代码,将各个模块综合起来。

顶层模块seg_clock.v的代码实现如下:

module seg_clock(
input sys_clk,
input sys_rst_n,
input wire key_in1,
input wire key_in2,
input wire key_in3,
input wire key_in4,
output wire key_row,
output DIN,
output SCK,
output RCK,
output [4:0] led,
output [2:0] rgb,
output beep
);

wire second_flag;
wire [5:0] second;
wire [5:0] minute;
wire [5:0] hour;
wire [5:0] alarm_hour;
wire [5:0] alarm_minute;
wire alarm_posedge;
wire alarm_flag;

wire [3:0] data0;
wire [3:0] data1;
wire [3:0] data2;
wire [3:0] data3;
wire [3:0] data4;
wire [3:0] data5;

wire [7:0] seg_led;
wire [7:0] seg_sel;

wire key_posedge1;
wire key_posedge2;
wire key_posedge3;
wire key_posedge4;
assign key_row = 1'b0;
time_count my_time_count(
.sys_clk (sys_clk),
.sys_rst_n (sys_rst_n),
.key_posedge1 (key_posedge1),
.second_flag (second_flag)
);

time_num my_time_num(
.sys_clk (sys_clk),
.sys_rst_n (sys_rst_n),
.second_flag (second_flag),
.key_posedge2 (key_posedge2),
.key_posedge3 (key_posedge3),
.key_posedge4 (key_posedge4),
.second (second),
.minute (minute),
.hour (hour),
.alarm_posedge (alarm_posedge),
.alarm_hour (alarm_hour),
.alarm_minute (alarm_minute),
.led (led)
);

divider my_divider(
.sys_clk (sys_clk),
.sys_rst_n (sys_rst_n),
.second (second),
.minute (minute),
.hour (hour),
.alarm_posedge (alarm_posedge),
.alarm_hour (alarm_hour),
.alarm_minute (alarm_minute),
.data0 (data0),
.data1 (data1),
.data2 (data2),
.data3 (data3),
.data4 (data4),
.data5 (data5),
.alarm_flag (alarm_flag)
);

seg_scan my_seg_scan(
.sys_clk (sys_clk),
.sys_rst_n (sys_rst_n),
.data0 (data0),
.data1 (data1),
.data2 (data2),
.data3 (data3),
.data4 (data4),
.data5 (data5),
.seg_sel (seg_sel),
.seg_led (seg_led)
);

hc595 my_hc595(
.sys_clk (sys_clk),
.sys_rst_n (sys_rst_n),
.seg_led (seg_led),
.seg_sel (seg_sel),
.DIN (DIN),
.SCK (SCK),
.RCK (RCK)
);

key my_key1(
.sys_clk (sys_clk),
.sys_rst_n (sys_rst_n),
.key_in (key_in1),
.key_posedge (key_posedge1)
);

key my_key2(
.sys_clk (sys_clk),
.sys_rst_n (sys_rst_n),
.key_in (key_in2),
.key_posedge (key_posedge2)
);

key my_key3(
.sys_clk (sys_clk),
.sys_rst_n (sys_rst_n),
.key_in (key_in3),
.key_posedge (key_posedge3)
);

key my_key4(
.sys_clk (sys_clk),
.sys_rst_n (sys_rst_n),
.key_in (key_in4),
.key_posedge (key_posedge4)
);

RGB_LED my_RGB_LED(
.sys_clk (sys_clk),
.sys_rst_n (sys_rst_n),
.alarm_flag (alarm_flag),
.rgb (rgb)
);

buzzer my_buzzer(
.sys_clk (sys_clk),
.sys_rst_n (sys_rst_n),
.alarm_flag (alarm_flag),
.beep (beep)
);
endmodule

四.实现框图

image.png

五.FPGA资源利用说明

资源利用如下:

1.png

2.png

3.png

附件下载
seg_clock.rar
团队介绍
Steven Kai
评论
0 / 100
查看更多
目录
硬禾服务号
关注最新动态
0512-67862536
info@eetree.cn
江苏省苏州市苏州工业园区新平街388号腾飞创新园A2幢815室
苏州硬禾信息科技有限公司
Copyright © 2023 苏州硬禾信息科技有限公司 All Rights Reserved 苏ICP备19040198号