0%

2 Description

1 连续赋值

1.1 延时

  • #(上升沿延时 1,下降沿延时 0,关闭延时 Z,输出变成 X 延时)
1
assign #(a, b, c, d) x = y;
  • #(Min: Typ: Max)
1
assign #(1: 2: 3) x = y;
  • 惯性延时:任何小于其延时的信号变化脉冲将被滤除掉,不体现在输出端口上。

1.2 多驱动源线网

多重驱动

1
2
assign x = y;
assign x = z; // Error

线与、线或

  • 线与 wand
1
2
3
wand x;
assign x = y;
assign x = z;
  • 线或 wor
1
2
3
wor x;
assign x = y;
assign x = z;
  • 实际综合仍为与门、或门。
  • 延时在综合时会被忽略。

三态总线

1
2
3
tri x;
assign x = a ? 1'bz : b;
assign x = c ? 1'bz : d;

2 过程赋值

注:定义为 reg 不一定是寄存器

2.1 语句组

  • begin - end

  • fork - join

  • 语句组标识符

    当一个语句组有标识符时,在语句组内部可以定义局部变量,而不会传递到语句组外部。它的值在整个仿真周期中是不变的,但是不会与另一个语句组中的同名变量冲突。

    1
    2
    3
    4
    5
    always @ (...) begin: sort
    integer i;
    for (i = -; i < 7; i = i + 1)
    ...
    end

2.2 条件

if - else

  • 优先级

    可根据关键路径设计优先级编码,提高性能。

  • 锁存器

    条件不全,可能产生锁存器。

  • 寄存器

    在描述时序逻辑时,常用 if 语句的隐式条件对带时钟、使能的 D 触发器建模。在这里综合器会将其总合成一个带时钟使能的寄存器。

    1
    2
    3
    4
    5
    6
    7
    always @ (posedge clk or negedge rst_n) begin
    if(~rst_n)
    q <= 0;
    else if (en)
    q <= a + b;
    // ? else
    end

case

  • 所有分支具有一样的优先级

  • 条件不全可能产生锁存器

  • casez

    将条件中的 z 看做不关心的值。

    1
    2
    casez (x)
    4'b1??? : ...
  • casex

    将条件中的 z & x 看做不关心的值。

    1
    2
    casex (x)
    4'b1xxxx : ...

2.3 循环

forever

1
2
3
4
initial begin
clk = 0;
forever #5 clk = ~clk;
end

repeat

1
2
3
4
if (...)
repeat (8) begin
data = {data[6:0], data[7]};
end

while

1
2
3
while(...) begin
...
end

for

1
2
3
4
5
6
reg[3:0] mem[8:0];
always @ (...) begin : init
integer i;
for (i = 0; i < 8; i = i + 1)
mem[i] = 4'b0;
end

3 结构化描述

3.1 实例化模块

端口

  • 模块内部
    • input 默认是线网。
    • output 是线网或者寄存器。
    • inout 默认是线网,一般定义为 tri 。
  • 实例化模块
    • input 由线网或寄存器驱动。
    • output 驱动线网。
    • inout 输入时由线网驱动,输出时驱动线网。

实例化

1
2
3
4
5
6
7
adder u_adder (
.in1 (in1),
.in2 (in2),
.cin () // 无对应信号,留空
.out (out),
);
adder u_adder (in1, in2, /* 无对应信号,留空 */ , out);

参数化模块

  • 实例化时带入

    所有参数都要按照顺序列出,不能颠倒顺序或有遗漏。(?)

1
2
3
4
5
6
7
8
9
adder #(
2, // INPUT_WIDTH
3 // OUTPUT_WIDTH
) u_adder (
.in1 (in1),
.in2 (in2),
.cin ()
.out (out),
)
  • defparam

    未重新定义的参数保留原模块缺省值。

1
2
3
4
5
6
7
8
9
adder u_adder (
.in1 (in1),
.in2 (in2),
.cin ()
.out (out),
);
defparam
u_adder.INPUT_WIDTH = 2,
u_adder.OUTPUT_WIDTH = 3;