RTL 级的基本要素和设计步骤
- ds
非阻塞赋值、阻塞赋值、连续赋值
时序逻辑:always 为边沿敏感,使用
<=
组合逻辑:always 为电平敏感,使用
=
组合逻辑:assign 使用
=
1
2assign x1 = x + 1;
assign x = x + 1; // 组合逻辑环
寄存器电路建模
寄存器信号声明
定义为
reg
不一定是寄存器,还需要always
为边沿敏感。时钟
1
always @ (posedge clk)
异步复位、置位
1
2
3
4
5always @ (posedge clk or negedge rst)
if (rst)
...
else
...同步复位、置位
1
2
3
4
5always @ (posedge clk)
if (rst)
...
else
...**同时使用时钟的
posedge
和negedge
**相当于使用了倍频时钟,但是 PLD 内的 PLL/DLL 往往只能对一个时钟边沿保证很好的指标,因此不推荐使用。
组合逻辑建模
- always
- assign
双向端口和三态信号建模
建议仅在顶层模块定义双向总线和例化的三态信号,禁止在除顶层外的其他层次赋值高阻态 Z ,而是在顶层将双向信号分为输入信号和输出信号,然后根据需要分别传递到不同的子模块中。
1 | inout[7:0] data_bus; |
assign
1
2
3assign data_bus = sel1 ? data_out1 :
sel2 ? data_out2 :
8'bz;case
1
2
3
4
5
6
7
8reg data_out;
always @ (data_out1 or data_out2)
case ({data_out1, data_out2})
2'b10 : data_out = data_out1;
2'b01 : data_out = data_out2;
default : 8'bz;
endcase
assign data_bus = data_out; // data_bus 是 wire 或 tri ,不能在 always 块中被赋值
MUX 建模
? :
case
if - else
根据综合工具不同,可能综合出优先级或无优先级 MUX 。一般情况下综合工具会优化成无优先级结构。
存储器建模
reg [REG_WIDTH - 1 : 0] mem [MEM_WIDTH - 1 : 0]
- 调用 IP
时钟分频
偶数分频
1
2
3
4
5
6
7
8
9
10reg [2:0] cnt;
always @ (posedge clk_200k or negedge rst_n) begin
if (!rst_n)
cnt <= 0;
else
cnt <= cnt + 1;
end
assign clk_100k = cnt[0];
assign clk_50k = cnt[1];
assign clk_25k = cnt[2];奇数分频
ds
串并转换建模
ds
复位
同步复位
- always 敏感表中仅有时钟边沿。
1 | always @ (posedge clk) |
如果目标器件有同步复位端口,可直接调用。如果没有同步复位端口,则与输入信号组成某种组合逻辑达成同步复位效果。
同步复位优点
- 利于时序分析,综合结果可达到更高的频率。
- 仅在时钟沿生效,可避免因复位电路毛刺造成的亚稳态和错误。(复位组合电路产生的毛刺很难被时钟沿采集到)
同步复位缺点
必须保证复位信号足够长(至少要大于设计的最长时钟周期 + 同步复位信号穿过的组合逻辑路径延时 + 时钟偏移),才能保证所有时钟的有效沿都能采集到复位信号。
1
T_syn_rst > PeriodMax + (t1 + t2) + (clk2 - clk1)
有的触发器没有同步复位端口,会增加逻辑资源消耗。
异步复位
- always 敏感表中包含复位信号边沿。
1 | always @ (posedge clk or negedge rst_n) |
- 大多数触发器都有异步复位端口。
- 异步复位优点
- 设计简单
- 节约逻辑资源
- FPGA GSR
- 异步复位缺点
- 异步复位释放时间若与时钟有效沿接近,易造成触发器输出为亚稳态,造成逻辑错误。
- 如果异步复位逻辑树的组合逻辑产生了毛刺,则会使触发器误复位,造成逻辑错误。
异步复位,同步释放
1 | module top_module( |
1 | reset_n = 1 -> rst_nr1 = 1, rst = 1 |

