一、系统方案论证:
概述:
"Tube" 模块旨在与数码管或7段数码管进行接口。它包括一个状态机,用于控制段数据,并管理指示按键按下和按键释放的标志。
功能:
代码片段中描述的模块执行以下任务:
计时,同时精确到秒和100毫秒。
控制两个7段数码管上显示的段数据。
根据按键输入管理启动和停止标志。
设计分析:
"Tube" 模块维护两个计数器,用于在秒和100毫秒内计时。它使用状态机来控制两个7段数码管的段数据。它还基于按键输入管理启动和停止标志。
"Tube" 模块需要一个 "Segment" 实例来显示段数据,以及一个 "Key" 实例来处理按键输入。"Key" 实例管理按键输入并根据按键释放检测设置 "r_flag"。
考虑因素:
"Tube" 模块的设计基于同步逻辑和正沿触发的触发器。按键输入用于控制启动和停止标志,从而影响段数据的显示。
重要的是要确保设计中的时序参数适合目标硬件平台,并满足7段数码管的电气规格。
总体而言,该设计展示了对段数据和按键输入管理的有效控制,以操作数码管。
二、理论分析与电路设计
设计思路:利用计数器驱动数码管,从而达到一个秒表功能
1. 利用reset按键来实现数码管清空功能
2. 当按键key1被按下时,启动计数器,从而改变数码管显示
3. 当按键key2被按下时,停止计数器,让数码管保持当时的数值不变
4. 当按键key3(flag)被按下时,数码管递增0.1s,达到递增效果
整体设计思路如下:
模块功能:
模块包含了一个用于显示时间的数码管显示器和一个按键模块,能够实现倒计时功能。
数码管显示器分为两部分,分别用于显示秒和毫秒。
按键模块用于启动和停止倒计时功能。
输入输出:
输入包括时钟信号clk、复位信号rst_n、按键信号key和一个标志位add。
输出包括用于显示秒的数码管信号seg_led_1和用于显示毫秒的数码管信号seg_led_2。
寄存器定义:
cnt_1s用于计时秒数,共24位。
cnt_100ms用于计时毫秒数,共21位。
flag用于控制倒计时的启动和停止。
seg_data_1和seg_data_2分别用于存储数码管显示的数据。
状态机设计:
设计了三个时序逻辑块,分别用于计时秒数、计时毫秒数和控制数码管显示数据。
每个逻辑块在正边沿时钟信号或者负边沿复位信号下更新寄存器的值。
控制逻辑:
当按键为10时,启动倒计时;当按键为01时,停止倒计时。
每个时序逻辑块的更新受到flag标志位和按键信号的控制。
根据计时条件和数码管显示值,更新数码管显示数据。
子模块实例化:
实例化了名为segment_inst的segment模块用于控制数码管的显示。
实例化了名为key_inst的key模块用于按键检测与处理。
主要难题可能包括以下几点:
时序逻辑设计复杂性:
解决方法:时序逻辑设计中涉及多个计时器和状态机,需要确保逻辑正确性和时序稳定性。建议使用状态图等工具来清晰描述各状态转移和逻辑控制条件,同时对时序逻辑进行仿真验证。
数码管显示数据更新条件复杂:
解决方法:数码管数据更新受多个条件影响,包括秒数、毫秒数、标志位等。建议优化逻辑控制条件,确保更新条件清晰明确,减少逻辑混乱和可能出现的bug。
按键检测与处理:
解决方法:按键模块关键影响倒计时的启动和停止,正确检测和处理按键信号至关重要。建议添加消抖电路,确保按键信号稳定,并且对按键模块的逻辑进行充分测试。
功能框图如下:
代码如下:
module timer(
input wire clk, // 输入时钟信号
input wire rst, // 复位信号(低有效)
input wire add, // 加0.1s
input wire start, // 开始
input wire stop, // 结束
output wire [8:0] led_1, // 七段数码管输出
output wire [8:0] led_2 // 七段数码管输出
);
wire add_edge, start_edge, stop_edge;
wire clk10hz; //输出分频后的时钟信号
reg state; //状态机状态
reg [8:0] seg [9:0];
reg [3:0] count_gewei; //个位
reg [3:0] count_shiwei; //十位
//时钟分频模块
IntegerDivider #
(
.your_divisor(1200000)
)
IntegerDivider_inst
(
.clk(clk),
.rst_n(rst),
.clkout(clk10hz)
);
// 下降沿捕获模块
edge_detector edge_detector_inst(
.clk(clk10hz),
.rst_n(rst),
.add(add),
.start(start),
.stop(stop),
.add_edge(add_edge),
.start_edge(start_edge),
.stop_edge(stop_edge)
);
//参数化
parameter IDLE = 1'b0; // 初始空闲状态
parameter COUNTING = 1'b1; // 计数状态
// 程序主题:使用状态机
always @ (posedge clk10hz or negedge rst) begin
if(!rst == 1) begin
state <= 0;
count_gewei <= 4'd0;
count_shiwei <= 4'd0;
end
else begin
case(state)
//IDLE
IDLE : begin
if(add_edge == 1) begin
if(count_shiwei==9 && count_gewei==9) begin
count_shiwei <= 0;
count_gewei <= 0;
end
else if(count_gewei==9) begin
count_shiwei <= count_shiwei + 1;
count_gewei <= 0;
end
else begin
count_gewei <= count_gewei + 1;
end
end
else if(start_edge == 1) begin
state <= 1'd1;
end
else begin
count_shiwei <= count_shiwei;
count_gewei <= count_gewei;
end
end
//COUNTER
COUNTING : begin
if(stop_edge == 1) begin
state <= 1'd0;
end
else begin
if(count_shiwei==9 && count_gewei==9) begin
count_shiwei <= 0;
count_gewei <= 0;
end
else if(count_gewei==9) begin
count_shiwei <= count_shiwei + 1;
count_gewei <= 0;
end
else begin
count_gewei <= count_gewei + 1;
end
end
end
default : state <= 0;
endcase
end
end
initial
begin
seg[0] = 9'h3f; // 数码管输出显示0
seg[1] = 9'h06; // 数码管输出显示1
seg[2] = 9'h5b; // 数码管输出显示2
seg[3] = 9'h4f; // 数码管输出显示3
seg[4] = 9'h66; // 数码管输出显示4
seg[5] = 9'h6d; // 数码管输出显示5
seg[6] = 9'h7d; // 数码管输出显示6
seg[7] = 9'h07; // 数码管输出显示7
seg[8] = 9'h7f; // 数码管输出显示8
seg[9] = 9'h6f; // 数码管输出显示9
end
assign led_1 = seg[count_shiwei] + 9'b10000000;
assign led_2 = seg[count_gewei];
endmodule
//顶层模块
三、结果显示
资源占用:
仿真结果: