4 位二进制计数器
搭建一个 4 位二进制计数器,计数范围包含 0~15,计数周期为 16。复位信号为同步复位,复位时计数器数值置 0。

参考答案
java
// synthesis verilog_input_version verilog_2001
//-----------------------------------------------------------------------------
// 模块名称:top_module
// 电路功能:4位二进制同步加法计数器
// 参数特性:计数区间0~15、完整循环周期16个时钟周期,支持高电平同步复位
// 工作规则:
// 1.时钟上升沿统一执行复位判定或自增运算,全程同步时序
// 2.reset拉高时计数器立刻清零;复位撤销后每个时钟沿数值+1
// 3.4位天然模16计数:q=15再加1自动溢出回到0,循环往复
// 端口释义
// clk 系统时钟,上升沿触发所有状态更新
// reset 高电平同步复位,仅时钟上升沿生效,优先级高于计数自增
// q[3:0] 4位计数输出,取值范围十进制0~15
//-----------------------------------------------------------------------------
module top_module (
input clk, // 系统时钟,上升沿触发寄存器状态刷新
input reset, // 外部高电平同步复位,时钟上升沿采样生效
output reg [3:0] q // 4位计数输出,时序块赋值声明reg,范围0~15
);
// 同步时序逻辑块:所有状态变更仅在时钟上升沿执行
always @(posedge clk) begin
// 同步复位分支:复位优先级最高,满足条件直接清零计数器
if (reset) begin
q <= 4'd0;
end
// 正常计数分支:无复位时每个时钟周期数值自增1
// 4位位宽限制:15+1溢出自动归零,天然实现模16循环计数
else begin
q <= q + 1'b1;
end
end
endmodule
输出结果

模 10 计数器
设计一个十进制计数器,计数范围包含0至9,计数周期为10。复位信号为同步复位,复位时计数器置零。

参考答案
java
// synthesis verilog_input_version verilog_2001
//-----------------------------------------------------------------------------
// 模块名称:top_module
// 电路功能:模10同步加法十进制计数器(计数范围0~9,循环周期10个时钟周期)
// 控制规则:高电平同步复位优先级最高;计数到9后下一周期强制归零,实现十进制循环
// 端口释义
// clk 系统时钟,所有计数、复位动作仅在上升沿同步执行
// reset 高电平同步复位,需等待时钟上升沿采样生效,直接清零输出
// q[3:0] 4位计数输出,合法取值0~9,超出范围会被逻辑拦截归零
//-----------------------------------------------------------------------------
module top_module (
input clk, // 系统时钟,仅上升沿执行计数/复位逻辑
input reset, // 同步复位信号,高电平有效
output reg [3:0] q // 4位计数输出,取值 0 ~ 9
);
// 同步时序逻辑块:状态更新严格对齐时钟上升沿,无时钟边沿不会改变数值
always @(posedge clk) begin
// 分支1(最高优先级):同步复位触发,直接强制计数器清零
if (reset) begin
q <= 4'd0;
end
// 分支2:无复位且已计到十进制最大值9,下一时钟沿回到起点0完成循环
else if (q == 4'd9) begin
q <= 4'd0;
end
// 分支3:常规计数阶段,每个时钟周期数值自增1
else begin
q <= q + 1'b1;
end
end
endmodule
输出结果

十进制计数器
设计一个十进制计数器,计数范围包含 1 至 10。复位信号为同步复位,复位后计数器数值置为 1。

参考答案
java
// synthesis verilog_input_version verilog_2001
//-----------------------------------------------------------------------------
// 模块名称:top_module
// 电路功能:模10同步加法计数器,计数区间1~10(首尾包含),循环周期10个时钟周期
// 控制规则:
// 1.高电平同步复位优先级最高,复位生效时计数器强制置初始值1
// 2.正常计数逐拍自增,计数到达上限10后,下一时钟沿跳转回1循环往复
// 端口释义
// clk 系统时钟,全部计数、复位逻辑仅上升沿同步执行
// reset 高电平同步复位,需等待时钟上升沿采样生效
// q[3:0] 4位计数输出,取值范围十进制1~10,10对应二进制1010
//-----------------------------------------------------------------------------
module top_module (
input clk, // 输入时钟,上升沿触发所有时序逻辑
input reset, // 同步复位信号,高电平有效
output reg [3:0] q // 4位寄存器输出,最大数值10,二进制1010
);
// 同步时序逻辑块:所有计数值变更严格对齐时钟上升沿
always @(posedge clk) begin
// 分支1(最高优先级):同步复位触发,强制回到计数起始值1
if (reset) begin
q <= 4'd1;
end
// 分支2:无复位且计数达到最大值10,执行循环归零跳转,回到起点1
else if (q == 4'd10) begin
q <= 4'd1;
end
// 分支3:常规区间正常逐拍自增1
else begin
q <= q + 4'd1;
end
end
endmodule
输出结果

慢速十进制计数器
设计一个十进制计数器,计数范围包含0至9,计数周期为10。复位输入为同步复位,复位时将计数器置0。我们需要实现计数器暂停功能,使其不必在每个时钟周期都执行自增操作,slowena输入信号用于控制计数器何时进行数值递增。

参考答案
java
// synthesis verilog_input_version verilog_2001
//-----------------------------------------------------------------------------
// 模块名称:top_module
// 电路功能:带计数使能的模10同步十进制计数器(0~9循环计数)
// 控制逻辑优先级:同步复位 > 使能暂停保持 > 满值归零循环 > 正常自增
// 信号规则:
// 1.reset高电平同步复位,时钟上升沿生效,计数值强制清零
// 2.slowena高电平允许计数、低电平冻结当前数值,实现慢速启停控制
// 3.计数到9后下一拍回到0,完成十进制循环
// 端口释义
// clk 系统时钟,所有时序动作仅上升沿同步执行
// slowena 计数使能,高有效;控制计数器启停
// reset 高电平同步复位,优先级最高
// q[3:0] 外部计数输出端口,由内部寄存器直通驱动
// 内部信号释义
// q_reg[3:0] 4位计数寄存器,保存0~9实时计数值,时序块内赋值
//-----------------------------------------------------------------------------
module top_module (
input clk, // 系统时钟,上升沿触发全部时序逻辑
input slowena, // 计数使能信号:高电平允许计数,低电平保持当前数值
input reset, // 同步复位,高电平有效,复位后计数值置0
output [3:0] q // 计数输出端口,默认wire类型,承接内部寄存器结果
);
reg [3:0] q_reg; // 内部计数寄存器,存储0~9范围的实时计数值
// 同步时序逻辑块:仅时钟上升沿更新寄存器状态
always @(posedge clk) begin
// 分支1(最高优先级):同步复位触发,直接清空计数值
if (reset) begin
q_reg <= 4'd0;
end
// 分支2:使能无效,冻结计数,保持原有数值不变
else if (~slowena) begin
q_reg <= q_reg;
end
// 分支3:使能有效且计数达到上限9,下一周期归零循环
else if (q_reg == 4'd9) begin
q_reg <= 4'd0;
end
// 分支4:使能有效且未到上限,常规逐拍自增1
else begin
q_reg <= q_reg + 4'd1;
end
end
// 组合逻辑直通输出:内部寄存结果直接对外引出
assign q = q_reg;
endmodule
输出结果

模12计数器
设计一个计数范围 1~12 的计数器,包含以下输入、输出端口:
输入信号
- Reset:同步高电平复位;复位触发时强制计数器数值置为 1
- Enable:计数使能;置高电平时计数器才正常计数
- Clk:上升沿触发时钟输入
输出信号 - Q 3:0:计数器数值输出
- c_enable、c_load、c_d 3:0:送往底层 4 位计数器的控制信号,用于校验电路逻辑是否正确
可用器件资源 - 下方给出的 4 位二进制计数器模块 count4:自带使能输入、同步并行置数输入;置数 load 优先级高于计数使能 enable。该模块已预先提供,需要在代码中例化调用。
- 各类逻辑门电路
count4 模块端口说明
java
module count4(
input clk,
input enable, // 计数使能
input load, // 同步并行置数使能(优先级更高)
input [3:0] d, // 并行置数输入数据
output reg [3:0] Q
);
补充说明
输出 c_enable、c_load、c_d 分别直接连接内部例化 count4 模块的 enable、load、d 端口;设置这几组对外输出,是为了方便外部观测、校验内部控制信号是否逻辑正确。
参考答案
java
// synthesis verilog_input_version verilog_2001
//-----------------------------------------------------------------------------
// 模块名称:top_module
// 功能概述:控制内置count4子模块实现1~12循环计数,支持同步复位启停控制
// 计数规则:
// 1.复位触发/计数溢出时,同步载入初始值1;正常使能开启逐拍自增
// 2.计数上限12,仅使能有效时溢出才会回到1;使能关闭则数值冻结保持12不变
// 端口释义
// clk 系统时钟,上升沿驱动底层count4寄存器更新
// reset 同步高电平复位,触发底层同步置数、强制载入初始值1
// enable 全局计数使能:高电平允许自增/溢出重置,低电平暂停所有计数动作
// Q[3:0] 最终计数输出,合法取值范围1~12
// c_enable 转发至count4的使能信号,引出端口便于波形仿真观测
// c_load 转发至count4的同步置数控制信号,高电平触发载入c_d数值
// c_d[3:0] 转发至count4的置数常量数据,固定十进制1
// 子模块说明:count4为平台预置4位同步置数计数器,自带enable、load、d、Q标准接口
//-----------------------------------------------------------------------------
module top_module (
input clk, // 系统时钟,上升沿触发count4内部寄存器更新
input reset, // 同步高电平复位,复位时强制计数器置数值1
input enable, // 全局计数使能:高电平允许自增;低电平保持当前数值
output [3:0] Q, // 计数器对外输出,数值范围 1~12
output c_enable, // 送给底层count4的使能信号,引出端口用于仿真校验
output c_load, // 送给底层count4的同步置数信号,引出端口用于仿真校验
output [3:0] c_d // 送给底层count4的置数数据,固定为十进制1,引出端口校验
);
// 逻辑1:顶层全局使能直通底层计数器,启停控制完全同步
assign c_enable = enable;
// 逻辑2:预置固定置数初值,复位、溢出重置场景统一载入十进制1(二进制0001)
assign c_d = 4'b0001;
// 逻辑3:同步置数触发条件(或逻辑二选一触发)
// 条件A:外部同步复位拉高,强制重置初值
// 条件B:使能开启+当前计数达到上限12,执行循环重置回到起点1
// 关键约束:使能关闭时即使Q=12也不触发重置,保持数值冻结
assign c_load = reset || (enable && (Q == 4'b1100));
// 例化内置4位同步置数计数器子模块count4
count4 cnt(
.clk(clk), // 时钟信号直连顶层全局时钟
.enable(c_enable),// 接入顶层转发的计数使能
.Q(Q), // 计数输出引出至顶层,同时反馈参与溢出判断
.load(c_load), // 接入组合逻辑生成的同步置数控制信号
.d(c_d) // 接入固定初值1作为置数数据源
);
endmodule
输出结果

模1000 计数器
从 1000 Hz 时钟导出 1 Hz 信号,称为 OneHertz,该信号可用于驱动一组时/分/秒计数器的使能(Enable)输入,从而构成数字挂钟。由于我们希望时钟每秒计数一次,OneHertz 信号必须在每一秒内恰好有效(高电平)一个时钟周期。请使用模 10(BCD)计数器构建该分频器,并尽量少用其他逻辑门。同时,输出您所使用的每个 BCD 计数器的使能信号(c_enable0 对应最快计数器,c_enable2 对应最慢计数器)。
提供以下 BCD 计数器模块。enable 必须为高才能使计数器运行。reset 为同步复位,置高时将计数器强制清零。您电路中的所有计数器都必须直接使用相同的 1000 Hz 时钟信号。
java
module bcdcount (
input clk,
input reset,
input enable,
output reg [3:0] Q
);

参考答案
java
// synthesis verilog_input_version verilog_2001
//-----------------------------------------------------------------------------
// 模块名称:top_module
// 电路功能:3位BCD级联模1000分频电路,输入高频时钟分频输出1Hz脉冲
// 计数架构:个位、十位、百位3个十进制BCD计数器逐级进位,累计1000个时钟周期产生一次脉冲
// 控制逻辑:低位计满9才开放高位使能,实现逢十进位;全位为9时输出1Hz标志脉冲
// 端口释义
// clk 高频输入时钟,全局计数节拍基准
// reset 全局同步复位,高电平清零所有计数器,从头开始计数
// OneHertz 1Hz分频脉冲输出,个位+十位+百位同时等于9时拉高
// c_enable[2:0] 三级计数器独立使能总线,依次控制百位、十位、个位启停
// 内部信号释义
// Q0[3:0] 个位BCD计数输出(0~9)
// Q1[3:0] 十位BCD计数输出(0~9)
// Q2[3:0] 百位BCD计数输出(0~9)
// 子模块说明:bcdcount为标准带使能同步复位十进制(0~9)BCD加法计数器
//-----------------------------------------------------------------------------
module top_module (
input clk, // 输入时钟信号,整个计数电路的心跳节拍源
input reset, // 全局复位,触发后三级计数器全部清零,重启计数流程
output OneHertz, // 1Hz分频脉冲输出,累计满1000个时钟周期拉高一次
output [2:0] c_enable // 3位使能控制线:c_enable[0]个位、c_enable[1]十位、c_enable[2]百位
);
// 三级BCD计数器输出连线,分别寄存个位、十位、百位实时计数值(取值0~9)
wire [3:0] Q0,Q1,Q2;
// 个位计数器常驻使能,每个时钟上升沿固定自增,是进位链路最基础节拍单元
assign c_enable[0] = 1'b1;
// 进位规则1:个位计满最大值9(4'b1001),十位获得计数使能,下一拍十位+1、个位归零
assign c_enable[1] = (Q0 == 4'b1001);
// 进位规则2:个位、十位同时计满9,百位获得计数使能,实现逢百进位
assign c_enable[2] = (Q0 == 4'b1001) && (Q1 == 4'b1001);
// 满1000周期判定:个位、十位、百位全部等于9,完成一轮0~999循环,输出1Hz脉冲标记
assign OneHertz = (Q0 == 4'b1001) && (Q1 == 4'b1001) && (Q2 == 4'b1001);
// 例化个位BCD计数器:永久使能,逐时钟自增
bcdcount counter0 (clk, reset, c_enable[0], Q0);
// 例化十位BCD计数器:仅个位满9时允许进位计数
bcdcount counter1 (clk, reset, c_enable[1], Q1);
// 例化百位BCD计数器:仅个位、十位同时满9时允许进位计数
bcdcount counter2 (clk, reset, c_enable[2], Q2);
endmodule
输出结果

4 位十进制计数器(BCD 计数器)
搭建一个4 位 BCD 十进制计数器。 每一位十进制数字用 4 位二进制编码表示:
- q3:0:个位;
- q7:4:十位; 更高位以此类推。
针对第 1、2、3 位高位数字(十位、百位、千位,对应整体位段3:1),额外输出一组使能信号;该信号用于标识:对应高位数字何时需要加 1 进位。
提示:你可以实例化或复用单路模 10 十进制(decade)计数器模块完成设计。

参考答案
java
// synthesis verilog_input_version verilog_2001
//-----------------------------------------------------------------------------
// 顶层模块功能:4位BCD级联同步十进制计数器,计数范围0000~9999(模10000循环)
// 架构说明:个位/十位/百位/千位共4组独立模10计数器,低位满9触发高位进位使能
// 端口释义
// clk 全局同步时钟,所有计数器共用同一节拍
// reset 高电平同步复位,时钟上升沿生效,所有计数位强制清零
// ena[3:1] 进位使能输出:ena[1]十位、ena[2]百位、ena[3]千位进位开启信号
// q[15:0] 16位拼接输出:q15~q12千位、q11~q8百位、q7~q4十位、q3~q0个位
// 内部信号释义
// q0[3:0] 个位计数值 0~9
// q1[3:0] 十位计数值 0~9
// q2[3:0] 百位计数值 0~9
// q3[3:0] 千位计数值 0~9
//-----------------------------------------------------------------------------
module top_module (
input clk, // 全局时钟,所有十进制计数器共用节拍源
input reset, // 同步高电平复位,所有计数位统一清零重启
output [3:1] ena, // 进位使能输出:ena[1]十位、ena[2]百位、ena[3]千位进位控制
output [15:0] q // 16位拼接总输出:{千位,百位,十位,个位}
);
// 4组4位连线,分别寄存个位、十位、百位、千位实时BCD计数值
wire [3:0] q0,q1,q2,q3;
// 十位进位条件:个位计数满最大值9,开放十位计数权限
assign ena[1] = (q0 == 4'd9);
// 百位进位条件:个位、十位同时满9,开放百位计数权限
assign ena[2] = (q0 == 4'd9) && (q1 == 4'd9);
// 千位进位条件:个位、十位、百位同时满9,开放千位计数权限
assign ena[3] = (q0 == 4'd9) && (q1 == 4'd9) && (q2 == 4'd9);
// 位拼接组合逻辑:高位在前、低位在后,合并4组BCD值为16位总线输出
assign q = {q3,q2,q1,q0};
// 个位计数器:永久使能,每个时钟周期固定自增,进位链路最基础单元
decade_counter cnt0(
.clk(clk),
.reset(reset),
.en(1'b1),
.q(q0)
);
// 十位计数器:仅个位满9时开启计数,实现逢十进位
decade_counter cnt1(
.clk(clk),
.reset(reset),
.en(ena[1]),
.q(q1)
);
// 百位计数器:仅个位+十位同时满9时开启计数,实现逢百进位
decade_counter cnt2(
.clk(clk),
.reset(reset),
.en(ena[2]),
.q(q2)
);
// 千位计数器:仅低三位同时满9时开启计数,实现逢千进位
decade_counter cnt3(
.clk(clk),
.reset(reset),
.en(ena[3]),
.q(q3)
);
endmodule
//-----------------------------------------------------------------------------
// 底层子模块:单位模10 BCD同步加法计数器(计数区间0~9循环)
// 控制规则:同步复位优先级最高;使能拉高逐拍自增,计到9自动归零
// 端口释义
// clk 时钟节拍
// reset 高电平同步复位,上升沿清零输出
// en 计数使能,高电平允许自增,低电平数值保持
// q 4位BCD计数输出,取值0~9
//-----------------------------------------------------------------------------
module decade_counter(
input clk,
input reset,
input en,
output reg [3:0] q
);
// 同步时序逻辑:仅时钟上升沿更新状态
always @(posedge clk) begin
if(reset)
q <= 4'd0; // 复位触发,强制清零计数器
else if(en) begin // 无复位且使能有效,执行计数逻辑
if(q == 4'd9)
q <= 4'd0; // 达到十进制上限9,下一拍归零循环
else
q <= q + 4'd1; // 未到上限,常规逐拍自增1
end
end
endmodule
输出结果

12 小时制时钟
设计一组适用于 12 小时制时钟的计数器(附带上午 / 下午标识位)。计数器由高速时钟clk驱动;每当时钟需要走时(即每秒一次)时,使能信号ena产生脉冲。复位信号reset会将时钟重置为上午 12:00。pm为 0 代表上午,为 1 代表下午。hh、mm、ss均各由两位 BCD 码(二进制编码十进制)组成:小时范围 01--12,分钟 00--59,秒钟 00--59。 复位优先级高于使能,即便使能未开启,复位也能生效。 下方时序图展示两种切换逻辑:上午 11:59:59 跳转为下午 12:00:00 的进位规则,以及同步复位、使能的时序行为。

参考答案
java
//========================================================================
// 子模块1:十进制BCD个位计数器(0~9循环)
// 复用场景:秒个位、分钟个位共用此模块
// 端口说明:
// clk 同步时钟,上升沿更新寄存器数值
// reset 同步高电平复位,优先级高于计数使能
// en 计数使能,高电平允许数值自增1
// q 4bit 8421BCD输出,数值范围0~9
// carry 进位输出标志,仅当q==9且en=1时carry=1,用于向高位进位
// 计数规则:0→1→2...→9→0,满9归零并输出进位
//========================================================================
module bcd_0to9
#(
parameter RST_DATA = 4'd0 // 复位后默认输出数值为0
)
(
input clk,
input reset,
input en,
output reg [3:0] q,
output carry
);
// 组合逻辑生成进位信号:数值到9且使能打开,进位拉高
assign carry = (q == 4'd9) && en;
always @(posedge clk) begin
// 复位优先级最高,复位触发直接赋值初始值
if(reset) begin
q <= RST_DATA;
end
// 无复位、计数使能有效,执行BCD循环计数
else if(en) begin
if(q == 4'd9) begin
q <= 4'd0; // 个位计满9归零,同时carry输出进位给高位
end
else begin
q <= q + 1'b1; // 未到最大值,正常自增1
end
end
end
endmodule
//========================================================================
// 子模块2:六进制BCD十位计数器(0~5循环)
// 复用场景:秒十位、分钟十位共用,00~59计时高位最大仅到5
// 端口功能与bcd_0to9完全一致,仅计数上限改为5
// 计数规则:0→1→2...→5→0,满5归零并输出进位
//========================================================================
module bcd_0to5
(
input clk,
input reset,
input en,
output reg [3:0] q,
output carry
);
// 进位逻辑:数值等于5且使能打开,进位输出高电平
assign carry = (q == 4'd5) && en;
always @(posedge clk) begin
if(reset) begin
q <= 4'd0; // 分、秒十位复位统一清零
end
else if(en) begin
if(q == 4'd5) begin
q <= 4'd0; // 十位计满5归零,向更高一级输出进位
end
else begin
q <= q + 1'b1;
end
end
end
endmodule
//========================================================================
// 子模块3:12小时制双BCD状态机(FPGA工程三分支优化写法)
// 硬件存储:两组独立4bit寄存器分别存放小时十位hr_high、个位hr_low
// 全部有效状态(两位BCD):01,02,03,04,05,06,07,08,09,10,11,12
// 完整循环流转顺序:12 → 01 → 02 → 03~09 → 10 → 11 → 12
// 端口说明:
// clk 同步时钟上升沿更新小时状态
// reset 同步复位,复位后固定状态12,pm=0代表上午AM
// en_h 小时切换使能,仅时间走到59分59秒时拉高,才更新小时
// hr_low 小时个位BCD寄存器输出
// hr_high 小时十位BCD寄存器输出
// pm 上下午标识,0=上午,1=下午;仅11跳转12时翻转电平
// 分支设计优势:仅3层判断,减少组合逻辑级数,降低FPGA LUT消耗、时序更稳
// 分支划分:
// 1. 单独处理特殊状态12,强制跳转01,无PM翻转
// 2. 单独处理特殊状态11,跳转12并翻转PM标识
// 3. 剩余01~10全部共用一套通用自增逻辑,无特殊操作
//========================================================================
module hour_2bcd_12
(
input clk,
input reset,
input en_h,
output reg [3:0] hr_low,
output reg [3:0] hr_high,
output reg pm
);
always @(posedge clk) begin
// 复位逻辑:强制小时BCD输出12,pm置0代表上午
if(reset) begin
hr_high <= 4'd1;
hr_low <= 4'd2;
pm <= 1'b0;
end
// 只有分秒同时满59,en_h=1,才执行一次小时状态更新
else if(en_h) begin
// ========== 分支1:当前小时BCD为12(十位1,个位2) ==========
// 特殊跳转:正常+1会得到13,不符合12小时制,强制赋值为01
// 上下午标识pm保持原有电平,不翻转
if(hr_high == 4'd1 && hr_low == 4'd2) begin
hr_high <= 4'd0;
hr_low <= 4'd1;
end
// ========== 分支2:当前小时BCD为11(十位1,个位1) ==========
// 特殊跳转:跳转为12,同时翻转pm电平,实现上下午切换
else if(hr_high == 4'd1 && hr_low == 4'd1) begin
hr_high <= 4'd1;
hr_low <= 4'd2;
pm <= ~pm;
end
// ========== 分支3:剩余所有常规小时 01,02,03~09,10 通用逻辑 ==========
// 该区间所有小时自增规则完全统一,无需拆分多个if判断,节约硬件资源
// 规则:个位数值+1;若个位计满9,则个位清零、十位自增1(09进位到10)
else begin
// 个位到达9,需要向十位进位
if(hr_low == 4'd9) begin
hr_low <= 4'd0; // 个位归零
hr_high <= hr_high + 1'b1; // 十位自增1
end
else begin
hr_low <= hr_low + 1'b1; // 个位未到9,仅个位数字+1
end
end
end
end
endmodule
//========================================================================
// 顶层总模块 top_module
// 设计约束硬性要求:秒个位计数器使能端口直接连接顶层全局计时开关ena
// 输出格式说明:hh/mm/ss均为8位双8421BCD,高4bit是十位,低4bit是个位
// 复位规则:reset复位优先级高于ena,复位后全局时间锁定12:00:00 AM
// 进位联动机制:低位计数器计满产生进位,逐级控制高位计数使能,实现60进制时分秒
//========================================================================
module top_module(
input clk, // 系统全局同步时钟
input reset, // 同步复位信号
input ena, // 全局计时总开关,高电平时钟正常走时,低电平全部暂停
output pm, // 向外输出上下午标识信号
output [7:0] hh, // 小时8位BCD输出,范围01~12
output [7:0] mm, // 分钟8位BCD输出,范围00~59
output [7:0] ss // 秒钟8位BCD输出,范围00~59
);
// ---------------------- 内部连线定义:时分秒十位、个位4位BCD信号 ----------------------
wire [3:0] sec_low, sec_high; // sec=秒,low个位,high十位
wire [3:0] min_low, min_high; // min=分钟,low个位,high十位
wire [3:0] hr_low, hr_high; // hr=小时,low个位,high十位
// ---------------------- 底层计数器进位输出信号定义 ----------------------
wire carry_sec_low; // 秒个位bcd_0to9模块的进位输出
wire carry_sec_high; // 秒十位bcd_0to5模块的进位输出
wire carry_min_low; // 分钟个位bcd_0to9模块的进位输出
wire carry_min_high; // 分钟十位bcd_0to5模块的进位输出
// ---------------------- 各级计数器计数使能信号(由进位组合逻辑生成) ----------------------
wire en_sec_high; // 秒十位计数器的计数允许开关
wire en_min_low; // 分钟个位计数器的计数允许开关
wire en_min_high; // 分钟十位计数器的计数允许开关
wire en_hour; // 小时状态跳转使能,仅59分59秒时有效
// ====================== 进位逐级传递逻辑详细注释 ======================
// 规则:只有低位完整计满、进位标志为1时,高位才获得计数使能,实现逢十/逢六十进位
// en_sec_high:秒十位使能,仅秒个位走到9(carry_sec_low=1)时允许秒十位+1
assign en_sec_high = carry_sec_low;
// en_min_low:分钟个位使能,必须秒钟刚好走完完整60秒(秒个位9+秒十位5,两个进位同时为1)
// 到达整分钟节点,分钟数值才+1
assign en_min_low = carry_sec_low && carry_sec_high;
// en_min_high:分钟十位使能,两个条件同时成立
// 条件1:秒钟满60秒;条件2:分钟个位走到9
// 只有分钟个位到9且秒走完60秒,分钟十位才能进位自增
assign en_min_high = carry_sec_low && carry_sec_high && carry_min_low;
// en_hour:小时切换总使能,四个进位全部同时拉高代表当前时间为XX:59:59
// 秒个位满9 + 秒十位满5 + 分个位满9 + 分十位满5
// 仅此时刻en_hour=1,小时状态执行一次更新
assign en_hour = carry_sec_low && carry_sec_high && carry_min_low && carry_min_high;
// ==================== 秒钟双BCD模块例化(实现00~59六十秒循环) ====================
// 秒个位模块:严格遵循要求,使能en直接连接顶层全局计时开关ena,无中间逻辑中转
bcd_0to9 sec_unit_low(
.clk(clk),
.reset(reset),
.en(ena),
.q(sec_low),
.carry(carry_sec_low) // 模块进位输出绑定信号carry_sec_low ,做为秒 十 位的使能信号
);
// 秒十位模块:0~5六进制计数器,计数使能来自秒个位进位carry_sec_low
bcd_0to5 sec_unit_high(
.clk(clk),
.reset(reset),
.en(en_sec_high),
.q(sec_high),
.carry(carry_sec_high)
);
// ==================== 分钟双BCD模块例化(实现00~59六十分循环) ====================
bcd_0to9 min_unit_low(
.clk(clk),
.reset(reset),
.en(en_min_low),
.q(min_low),
.carry(carry_min_low)
);
bcd_0to5 min_unit_high(
.clk(clk),
.reset(reset),
.en(en_min_high),
.q(min_high),
.carry(carry_min_high)
);
// ==================== 12小时三分支状态机模块例化 ====================
hour_2bcd_12 hour_unit(
.clk(clk),
.reset(reset),
.en_h(en_hour),
.hr_low(hr_low),
.hr_high(hr_high),
.pm(pm)
);
// ==================== 8位双BCD输出拼接逻辑 ====================
// 拼接规则:{十位4bitBCD,个位4bitBCD},组合为8位输出供给数码管显示
assign ss = {sec_high, sec_low};
assign mm = {min_high, min_low};
assign hh = {hr_high, hr_low};
endmodule
输出结果
