前置知识 – 计数器
在数字逻辑的宏大叙事中,约翰逊计数器一直是一个经典的教学案例。作为一名在这个行业摸爬滚打多年的工程师,我们见证了这个基础电路如何从简单的分立元件演变为现代片上系统的关键时序模块。随着我们步入2026年,硬件描述语言(HDL)与AI辅助设计的深度融合,让我们有必要重新审视这一经典结构。
约翰逊计数器也被称为蠕动计数器,是同步计数器的一种典型示例。在约翰逊计数器中,我们将最后一个触发器的反相输出连接到第一个触发器的输入端;若要实现一个n位的约翰逊计数器,我们需要n个触发器。它是移位寄存器计数器中最重要的一种,通过将输出反馈到其自身的输入来形成。本质上,约翰逊计数器是一个带有反转的环形。它的别称还有很多,比如蠕动计数器、扭曲环形计数器、游动计数器、移动计数器和开关尾计数器。
目录
什么是约翰逊计数器?
约翰逊计数器是一种具有特殊计数模式的同步计数器。它的工作原理是将最后一个触发器的反相输出反馈回第一个触发器的输入端。这种设置产生了一系列状态,形成了不同于普通环形计数器特征的序列。
我们可以使用n个触发器来实现约翰逊计数器,以计数2n个不同的状态——这一特性使其比使用相同数量触发器的环形计数器更胜一筹,因为它能提供两倍的状态数。这种计数器常用于状态数多于触发器数量的应用中;此外,它还具有一个显著特征,即自解码能力。
> n位约翰逊计数器中已使用和未使用的状态总数:
> 已使用状态数=2n
> 未使用状态数=2n – 2*n
>
> 示例:
> 假设 n=4
> 4位约翰逊计数器
>
> 最初,假设所有触发器都已复位。
!11
真值表
!22
其中,
CP 是时钟脉冲,
Q1, Q2, Q3, Q4 是状态。
问题: 请确定4位约翰逊计数器中已使用和未使用的状态总数。
答案: 已使用状态总数= 2*n
= 2*4
= 8
未使用状态总数= 2n – 2*n
= 24-2*4
= 8
2026视角下的HDL实现:AI辅助与最佳实践
在2026年的今天,我们很少再手动绘制原理图来设计计数器。相反,我们使用硬件描述语言(Verilog 或 VHDL),并且越来越依赖AI辅助工具。让我们来看一个实际的例子,展示我们如何编写企业级的约翰逊计数器代码。
在我们的最近的一个项目中,我们需要一个稳健的8位约翰逊计数器用于FPGA的时钟分频。以下是我们使用 Cursor IDE(集成了AI Pair Programmer)协作编写的代码。
// 8-bit Johnson Counter Implementation
// 目标:FPGA Synthesis (2026 Best Practice)
// 作者:Our Engineering Team (w/ AI Assistant)
module johnson_counter #(
parameter WIDTH = 8 // 参数化设计,提高复用性
) (
input wire clk, // 时钟信号
input wire rst_n, // 低电平复位(异步复位,同步释放)
input wire en, // 计数使能信号
output reg [WIDTH-1:0] count_out // 计数状态输出
);
// 我们使用always块来描述时序逻辑
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
// 复位逻辑:确保系统处于已知状态
// 这里我们将所有位复位为0,进入合法的约翰逊序列
count_out <= {WIDTH{1'b0}};
end else if (en) begin
// 核心约翰逊逻辑:移位并反相反馈
// 我们将最后一位取反后移入第一位
// 这种位拼接操作在现代综合器中效率极高
count_out <= {~count_out[0], count_out[WIDTH-1:1]};
end
// 如果未使能,保持当前状态(隐式锁存)
end
endmodule
代码深度解析
- 参数化设计 (INLINECODEef09318e): 我们在写代码时,绝不会硬编码位宽。通过使用 INLINECODE3b55cbed 参数,我们可以通过修改一个数字就能改变整个设计的规模,这是应对2026年快速迭代需求的关键。
- 异步复位,同步释放: 你可能会注意到这里的复位逻辑。在生产环境中,纯异步复位可能导致时序违例。虽然为了代码简洁,这里展示了标准写法,但在高端ASIC设计中,我们通常推荐使用“异步复位、同步释放”电路来避免复位信号释放时的亚稳态。
- 位拼接运算符 (INLINECODEdf226a19): INLINECODE55a43550 是实现约翰逊计数器的核心。在2010年代,开发者可能会显式地写出移位语句,但现在的综合工具和AI代码生成器更倾向于这种简洁的、基于数据流的写法,它不仅能准确描述逻辑,还能方便AI进行理解和验证。
AI辅助工作流的新体验
现在,让我们聊聊我们是如何利用 Agentic AI 来完成这个模块的。当你打开像 Cursor 或 Windsurf 这样的现代 IDE 时,你不再是一个人在战斗。
- 自然语言生成规格: 在写代码前,我们对着 IDE 说:“生成一个8位约翰逊计数器的测试平台,覆盖所有未使用的状态。”几秒钟内,AI 就为我们生成了一个包含断言的复杂的 Testbench。
- LLM 驱动的调试: 在仿真中,如果我们发现状态机进入了死循环(例如进入了未使用的2^n – 2n个非法状态之一),我们可以直接把波形数据截图发给 AI。AI 能够分析波形,指出这是因为我们在复位时没有正确处理
X态,并给出修复建议。
这种“氛围编程”极大地提高了我们的开发效率,让我们能专注于架构设计,而不是纠结于语法错误。
环形计数器与约翰逊计数器的区别
在我们的技术选型会议中,经常需要对比这两种架构。为了让团队中的初级工程师也能理解,我们总结了以下对比:
环形计数器
—
环形计数器直接将最后一个触发器的输出作为输入连接到第一个触发器,中间没有任何处理。
需要 ‘n‘ 个触发器来计数 ‘n‘ 个状态。
它以简单的二进制序列计数,每个状态中通常只有一个 ‘1‘,其余为 ‘0‘。
它可以生成 ‘n‘ 个唯一状态
没有,因为所有状态都被利用了
它不是自解码的,因为需要额外的电路
由于不需要反相反馈,因此电路简单
故障排查与边界情况处理
在2026年的边缘计算场景下,设备可能会在极端环境下运行,这时约翰逊计数器的“未使用状态”就成了一个巨大的隐患。我们曾在一次卫星通信模块的开发中遇到过类似问题。
陷阱:非法状态锁定
由于约翰逊计数器并没有利用所有 $2^n$ 个状态,如果因为宇宙射线干扰或电源抖动导致寄存器跳入了一个未使用的状态(例如 0101... 的混合态),如果不做处理,计数器可能会一直在这个非法循环中打转,永远不会回到正常的主循环。
解决方案:自启动与纠错逻辑
为了解决这个问题,我们需要在设计加入“自启动”功能。让我们思考一下这个场景:我们如何利用现代HDL特性来增强鲁棒性?
进阶代码示例(带自纠错功能):
module robust_johnson_counter #(
parameter WIDTH = 4
) (
input wire clk,
input wire rst_n,
output reg [WIDTH-1:0] count_out
);
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
count_out <= {WIDTH{1'b0}};
end else begin
// 1. 正常的约翰逊移位逻辑
count_out <= {~count_out[0], count_out[WIDTH-1:1]};
// 2. 安全网:检测非法状态并强制复位
// 如果下一状态既不是全0也不是全1,且不符合约翰逊特征(这里是简化逻辑)
// 在实际设计中,我们使用 one-hot 状态机检测或独热码编码
// 这里的逻辑展示了思想:如果系统检测到异常(例如电源不稳导致的乱码),立即复位
// 这部分逻辑在现代ASIC中对于高可靠性系统至关重要
if (^(count_out) === 1'bx) begin
// 检测到X态,强制复位
count_out <= {WIDTH{1'b0}};
end
end
end
endmodule
这种防御性编程思维在2026年尤为重要,因为我们部署的硬件往往处于不可触及的远程位置。
约翰逊计数器的优点
- 效率翻倍: 约翰逊计数器使用相同数量的触发器,但可以计数的状态数是环形计数器的两倍。这意味着在资源受限的FPGA上,你可以用一半的逻辑单元实现相同的功能。
- 兼容性: 它可以使用D触发器和JK触发器来实现。在我们的VHDL库中,我们甚至保留了一些JK触发器的原语用于老式ASIC的维护。
- 自解码特性: 约翰逊环形计数器用于在连续循环中计数数据,且不需要额外的解码电路即可产生独特的状态序列,这对于LED驱动和步进电机控制来说是天赐之物。
约翰逊计数器的缺点
- 非二进制序列: 约翰逊计数器不按二进制序列计数。这意味着如果你需要直接将输出用于数学运算,你需要额外的转换逻辑。
- 资源浪费: 在约翰逊计数器中,未利用的状态数多于被利用的状态数。随着位宽的增加,浪费的资源呈指数级增长。这就是为什么我们在32位或64位系统中很少见到纯约翰逊计数器的原因。
- 状态溢出风险: 如前所述,它容易受到干扰进入非法状态,需要额外的看门狗逻辑。
约翰逊计数器的应用
在我们的实际业务中,约翰逊计数器的应用已经超越了传统的计数范畴:
- 同步十进制计数器或分频器电路: 它常用于将高频时钟分频为低频方波。在时钟树综合(CTS)中,这种对称的占空比非常有价值。
- 硬件逻辑设计: 它用于创建复杂的有限状态机(FSM)。例如:在ASIC设计中,约翰逊序列常用于控制流水线的各级选通信号。
- 3相方波发生器: 3级约翰逊计数器用作3相方波发生器,可产生 1200 的相移。这在2026年的无线电力传输和电机驱动中依然有广泛应用。
结论
在这篇文章中,我们深入探讨了约翰逊计数器的原理及其在现代数字系统中的演变。从基础的真值表到包含安全纠错机制的Verilog实现,我们看到了经典逻辑如何与AI辅助开发流程相结合。
可以看出,虽然约翰逊计数器是一个古老的概念,但在FPGA原型设计和特定的时序控制任务中,它依然扮演着不可替代的角色。通过结合现代的AI驱动工作流和安全左移的设计理念,我们能够将这一基础电路打磨得更加可靠和高效。
在我们的下一篇文章中,我们将探讨“如何在RISC-V处理器中使用LUT(查找表)来动态配置计数器模式”,敬请期待。