数字电路思想篇
方案精细
设计方案是编写代码的前提,复杂的项目没有方案,无法写出代码。方案必须达到能指导编码的阶段,其中包括:功能描述、架构实现、表现描述、模块划分、模块实现细节和时序描述、接口描述等。
有几点建议:
- 方案细化到 always 块;
- 模块实现细节描述清楚;
- 重点电路和复杂电路时序要在编码前画出;
- 有架构和模块划分描述;
- 包括资源占用的评估报告。
模块划分
复杂系统一般由多模块完成,若模块划分不合理,会出现模块间耦合太多,导致系统不健壮和不清晰,易出问题,且系统接受新需求能力不强。
模块划分建议:
- 完全理解系统的需求和规格。
- 对系统的实现要非常清楚。
- 划分的模块需要和熟悉系统的人讨论。
- 模块间接口简单、清晰、没有歧义。
- 模块功能完整,同一个功能最好使用一个模块实现。
- 系统划分要方便验证。
代码简单
当前项目越来越复杂,新写的代码需要经过多轮检视和后续项目重用, 如果代码复杂无比, 那么检视、 重用工作量是巨大的,也是项目周期不容许的,所以最好是使用简单语句和逻辑实现复杂的功能,越简单越好。
代码简单化建议:
- 使用最基础和常见的语法,有利于工具的资源优化。
- 少用复杂的语法,如“~^” 、 “===”等。
- 复杂功能分析清楚,语句之间越少耦合越好。
- 少用状态机,状态机综合的电路较难分析,而且和其他电路相比还需要分析状态机覆盖率;当然有些控制逻辑比较复杂的电路可以使用状态机。
注释层次
代码越复杂,注释的意义越大, 注释分层可以提高对代码的理解和方案的划分。
注释层次化建议:
- 使用步骤 1、2、3等编号描述.V 文件的结构划分和功能。
- 每个步骤里面可以包括子步骤 1、2、3等。
- 每个子步骤如果还是很复杂,可以继续划分子子步骤。
- 每个子步骤包括几个 always 或者 assign 块逻辑。
交互界面清晰
模块间接口或者模块内子模块交互简单、清晰、没有歧义。涉及到接口配合的地方一般都不是一个人完成,需要理解对方的意图,容易出问题。
交互界面清晰化建议:
- 接口定义越简单越好,需要避免耦合太多。
- 信号功能描述清晰,没有歧义。
- 信号最好在任何时候代表的都是相同的功能。
- 从系统方案层面划分接口,保证接口耦合性最少
时序流水
时序设计是写代码前提,流水处理包括两种,第一是通过时隙划分实现,第二是通过寄存器延时进行流水设计。
时隙划分:
如果时序是时隙流水的形式,可极大减少设计复杂度。比如操作一个 RAM,我们使用四个时隙去划分,第一个时隙是逻辑读写,第二个时隙是 CPU 读写,那么这种就不需要做读写冲突处理。四个时隙作为一个流水不停的执行。设计简化非常多。进行时流水时隙处理需满足性能要求,如果需要每个周期都读写 RAM,那么用四个时隙去划分,第一个时隙是逻辑读写,第二个时隙是 CPU 读写就不可行了,这个时候需要做读写冲突处理。
寄存器延时:
比如从 FIFO 读出数据的第一个时钟周期进行数据校验,第二个时钟周期进行数据的处理,第三个时钟周期进行数据的拼接,第四个时钟周期进行数据的 CRC 校验。这种处理方式也是流水处理的一种,这种处理方式性能很高。
有几点建议:
- 满足性能要求的前提时隙化处理。
- 通过寄存器延时的方式难度大于时隙化处理方式。
- 每个时隙或者延迟周期处理事情要明确、单一。