关键词:解除分配,强制,释放
过程连续赋值是过程赋值的一种。赋值语句能够替换其他所有wire 或 reg 的赋值,改写wire 或 reg 类型变量的当前值。
与过程赋值不同的是,过程连续赋值表达式能被连续的驱动到wire 或 reg 类型变量中,即过程连续赋值发生作用时,右端表达式中任意操作数的变化都会引起过程连续赋值语句的重新执行。
过程连续性分配主要有2种,分配-取消分配和强制-释放。
分配、取消分配
分配(过程赋值操作)与取消分配(取消过程赋值操作)表示第一类过程连续赋值语句。赋值对象只能是注册或注册组,而不能是线型变量。
分配过程中对分配的连续分配,分配过程中的值被保留直到被重新分配。
例如,一个带解密端的 D 触发器可以用下面的代码描述:
实例
模块dff_normal (
输入 rstn 、
输入 clk 、
输入 D 、
输出 reg Q
);
总是 @ ( posege clk或 negedge rstn ) begin
if ( ! rstn ) begin //复位后 Q = 0 有效
Q <= 1'b0 ;
结束
否则 开始
Q <= D ; //Q = D 位于时钟端
end
endmodule
的posege 处
下面,用分配与取消分配改写,完成相同的功能。
即在复位信号为0时,Q端被分配语句赋值,首先输出为0。
复位信号为1时,Q端被取消分配语句取消分配,在时钟上升沿被重新分配分配。
实例
模块dff_assign (
输入 rstn 、
输入 clk 、
输入 D 、
输出 reg Q
);
总是 @ ( posege clk ) 开始
Q <= D ; //Q = D 在时钟结束的 posege 处总是@ ( negedge rstn ) begin if ( ! rstn ) begin赋值Q = 1'b0 ; //复位时改变Q值有效end else begin //取消Q值叠加,取消分配Q ; //Q 保持 0 值,直到时钟脉冲到来end end endmodule
施力、释放
force(强制操作赋值)与release(取消强制赋值)表示第二类过程连续赋值语句。
但使用方法和效果,和分配与取消分配类似,赋值对象可以是reg型变量,也可以是wire型变量。
由于是无条件强制赋值,一般多用于吸附过程,不要在设计模块中使用。
当强制作用在寄存器上时,寄存器当前值被覆盖;释放时寄存器值将继续保留强制赋值时的值。之后,该寄存器的值可以被原来的过程语句赋值改变。
当强制作用在线网上时,线网型变量被强制。但是,一旦释放线网型变量,其值马上改为原来的驱动值。
为观察观察两个类型变量强制赋值的区别,利用第一节中的元素计数器10作为设计模块,测试台设计如下。
实例
`时标 1ns / 1ns
模块测试;
注册 rstn ;
寄存器 时钟;
reg [ 3 : 0 ] cnt ;
线 输出;
counter10 u_counter (
.rstn ( rstn ) 、.
clk ( clk ) 、.
cnt ( cnt ) 、.
cout ( cout ) ) ;
初始 开始
时钟 = 0 ;
rstn = 0 ;
# 10 ;
rstn = 1'b1 ;
等待 ( test.u_counter.cnt_temp == 4'd4 ) ;
@ (negedge时钟) ;
强制 test.u_counter.cnt_temp = 4'd6 ;
强制 test.u_counter.cout = 1'b1 ;
# 40 ;
@ (negedge时钟) ;
释放 test.u_counter.cnt_temp ;
释放 test.u_counter.cout ;
结束
初始 开始
clk = 0 ;
永远 # 10 clk = ~ clk ;
end
//完成模拟
always begin
# 1000 ;
if ( $time >= 1000 ) $finish ;
结束
模块 // 测试
仿真结果如下。
由图可知,在 cnt_temp 等于 4 时(80ns), cnt_temp 被强制赋值为 6,cout 被强制赋值为 1。
释放时(120ns), cnt_temp 为寄存器类型,仍然保持原有值不变,直到时钟上升沿由此进行加法赋值操作,值才等于 7 。
120ns 时,由于 cout 是线网型变量,其值不能保存。原码 counter10 模型中而存在语句驱动:allocate cout = (cnt_temp==4'd9),所以 cout 值等于 0 。