关注、星标公众号,直达精彩内容

公众号:ZYNQ
来源:优快云文章
使用逻辑门和连续赋值对电路建模,是相对详细的描述硬件的方法。使用过程块可以从更高层次的角度描述一个系统,称作行为级建模(behavirol modeling)。
1. 过程赋值
阻塞赋值和非阻塞赋值的区别都很熟悉了。这里记录两个特性。
1.1 特性1
绝大多数情况下,非阻塞赋值都是一个时间点处最后执行的赋值语句。看下面的示例代码:
module test
(
input clk,
output reg a, b
);
always @ (posedge clk) begin
a = 0;
b = 1;
a <= b;
b <= a;
end
endmodule
非阻塞赋值可以认为包括两步:
(1)求值和调度(evaluate and schedule),先得到非阻塞赋值等式右侧的值,并将这次赋值安排在当前时间点的结束时刻。
(2)当前时间点结束时,更新左侧的值。因此这段代码的结果是 a = 1,b = 0。
1.2 特性2
如果过程块内,有针对同一个变量的多个非阻塞赋值,那么这些非阻塞赋值会按顺序执行(但我认为不能简单地说过程块内是“顺序执行的”,容易造成误导,应该说具有一定的“顺序性”特点)。
看下面的示例代码:
module test
(
input clk,
output reg a, b
);
always @ (posedge clk) begin
a <= 0;
a <= 1;
end
endmodule
always块内有两条对于变量a的赋值语句,但由于顺序性特点,a的赋值结果应该是1。利用这个特性,会经常见到下面这种代码写法:
always @ (posedge clk) begin
a <= 0;
if (flag == 1)
a <= 1;
end
只有当flag=1时,a才为1。
2. 过程连续赋值
这种赋值方式允许在过程块中连续地驱动网络或变量。但这种建模方法不可综合,因此这里只简单记录一下两种过程连续赋值方式的作用。
assign和deassign:assign连续赋值会优先占用一个变量,让其它对这个变量进行赋值的过程块无效。deassign连续赋值会解除占用关系。
看下面的示例代码:
`timescale 1ns / 1ps
module sim();
reg clk = 0, rst_n = 0, d = 1;
reg q;
//test i1
//(
// .clk (clk),
// .rst_n(rst),
// .q(q),
// .d(d)
//);
always @ (rst_n)
if (!rst_n) assign q = 0;
else deassign q;
always @ (posedge clk)
q <= d;
always #5 clk <= ~clk;
initial begin
#50 rst_n = 1;
end
endmodule
当rst_n=0时,asssign连续赋值占用了q,q的值恒为0;当rst_n=1时,deassign解除了占用,q的值由其它过程赋值决定,在clk上升沿随d变化而变化。
force和release:功能和assign、deassign相同,只是赋值对象可以是变量也可以是网络。force过程赋值的对象为网络时,会使其它所有对该网络的驱动无效。
3. case语句
case语句的default分支不是必须的,只要设计者清楚设计意图即可。记录一下case两个比较少见但有时候特别有用的用法。
3.1 do-not-cares
包括两种&#