0%

3 RTL

RTL 级的基本要素和设计步骤

  • ds

非阻塞赋值、阻塞赋值、连续赋值

  • 时序逻辑:always 为边沿敏感,使用 <=

  • 组合逻辑:always 为电平敏感,使用 =

  • 组合逻辑:assign 使用 =

    1
    2
    assign x1 = x + 1;
    assign x = x + 1; // 组合逻辑环

寄存器电路建模

  • 寄存器信号声明

    定义为 reg 不一定是寄存器,还需要 always 为边沿敏感。

  • 时钟

    1
    always @ (posedge clk)
  • 异步复位、置位

    1
    2
    3
    4
    5
    always @ (posedge clk or negedge rst)
    if (rst)
    ...
    else
    ...
  • 同步复位、置位

    1
    2
    3
    4
    5
    always @ (posedge clk)
    if (rst)
    ...
    else
    ...
  • **同时使用时钟的 posedgenegedge **

    相当于使用了倍频时钟,但是 PLD 内的 PLL/DLL 往往只能对一个时钟边沿保证很好的指标,因此不推荐使用。

组合逻辑建模

  • always
  • assign

双向端口和三态信号建模

建议仅在顶层模块定义双向总线和例化的三态信号,禁止在除顶层外的其他层次赋值高阻态 Z ,而是在顶层将双向信号分为输入信号和输出信号,然后根据需要分别传递到不同的子模块中。

1
2
3
4
inout[7:0] data_bus;
wire [7:0] data_in, data_out;
assign data_in = data_bus;
assign data_bus = sel ? data_out : 8'bz;
  • assign

    1
    2
    3
    assign data_bus =   sel1 ? data_out1 :
    sel2 ? data_out2 :
    8'bz;
  • case

    1
    2
    3
    4
    5
    6
    7
    8
    reg 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
    10
    reg [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
2
3
always @ (posedge clk)
if (!rst_n) ...
else ...
  • 如果目标器件有同步复位端口,可直接调用。如果没有同步复位端口,则与输入信号组成某种组合逻辑达成同步复位效果。

  • 同步复位优点

    • 利于时序分析,综合结果可达到更高的频率。
    • 仅在时钟沿生效,可避免因复位电路毛刺造成的亚稳态和错误。(复位组合电路产生的毛刺很难被时钟沿采集到)
  • 同步复位缺点

    • 必须保证复位信号足够长(至少要大于设计的最长时钟周期 + 同步复位信号穿过的组合逻辑路径延时 + 时钟偏移),才能保证所有时钟的有效沿都能采集到复位信号。

      1
      T_syn_rst > PeriodMax + (t1 + t2) + (clk2 - clk1)
    • 有的触发器没有同步复位端口,会增加逻辑资源消耗。

异步复位

  • always 敏感表中包含复位信号边沿。
1
2
3
always @ (posedge clk or negedge rst_n)
if (!rst_n) ...
else ...
  • 大多数触发器都有异步复位端口。
  • 异步复位优点
    • 设计简单
    • 节约逻辑资源
    • FPGA GSR
  • 异步复位缺点
    • 异步复位释放时间若与时钟有效沿接近,易造成触发器输出为亚稳态,造成逻辑错误。
    • 如果异步复位逻辑树的组合逻辑产生了毛刺,则会使触发器误复位,造成逻辑错误。

异步复位,同步释放

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
module top_module( 
input clk, reset_n,
output rst_n
);
reg rst_nr1, rst_nr2;

always @(posedge clk or negedge reset_n) begin
if(!reset_n) begin
{rst_nr2, rst_nr1} <= 2'b00;
end else begin
{rst_nr2, rst_nr1} <= {rst_nr1, 1'b1};
end
end
assign rst_n = rst_nr2;
endmodule
1
2
3
4
5
reset_n = 1		->		rst_nr1 = 1, rst = 1
reset_n = 0 -> rst_nr1 = 0, rst = 0 // 异步复位
reset_n = 1 -> rst_nr1 = 0, rst = 0 // 保持
posedge clk -> rst_nr1 = 1, rst = 0 // 两级:防止第一级 reset_n 释放时间与 clk 有效沿接近,造成亚稳态
posedge clk -> rst_nr1 = 1, rst = 1 // 同步释放(2个周期)