10. case,casez,casex语句
verilog定义了case,casez和casex语句,用于做多种情况下的选择语句。
reg [1:0] sel;
reg [2:0] result;
always @(*)
case(sel)
2’b00: result = 3’d0;
2’b01: result = 3’d1;
2’b10: result = 3’d2;
endcase
使用case语句代替嵌套的if-else将会产生更易读的代码,更好的逻辑利用率和更高的性能。
casez和casex语句在比较中允许“don't care”条件。 casez将“z“”值视为don't care,casex将“z”和“x”值都视为“don't care”。如果casez或casex表达式中的任何位都是don't care value,那么该位将被忽略。以下是casez和casex的例子。
reg [1:0] sel;
reg [2:0] result;
// using casez
always @(*)
casez(sel)
2’b0?: result = 3’d0;
2’b10: result = 3’d1;
2’b11: result = 3’d2;
endcase
// using casex
always @(*)
casex(sel)
2’b0x: result = 3’d0;
2’b10: result = 3’d1;
2’b11: result = 3’d2;
endcase
case的表达式可以是一个常量,如下例所示。
reg [1:0] sel;
reg [2:0] result;
always @(*)
case(1
~sel[1]: result = 3’d0;
sel[1] & ~sel[0]: result = 3’d1;
sel[1] & sel[0]: result = 3’d2;
endcase
在案例中使用don't care条件很容易导致case 条件重叠或重复。而且,使用这些语句会导致综合和仿真不匹配。以下是案例case条件重叠的一个例子。
// casez statement contains overlapped case items
reg [1:0] sel;
reg [2:0] result;
always @(*)
casez(sel)
2’b0z: result = 3’d0;
2’b10: result = 3’d2;
2’b11: result = 3’d3;
2’b01: result = 3’d1; // overlap with 2’b0z
endcase
允许重叠或重复的case条件,在大多数情况下不会触发任何仿真或综合警告。这是一种危险且难以调试的情况.。建议开发人员完全避免使用casex和casez语句。
在case语句中添加一个默认的条件是避免一系列问题的简单方法。 有两种方法可以达到相同的效果,如以下示例所示。
reg [1:0] sel;
reg [2:0] result;
// using default clause
always @(*)
case(sel)
2’b00: result = 3’d0;
2’b01: result = 3’d1;
2’b10: result = 3’d2;
default: result = 3’d3;
endcase
// 在case语句之前进行默认赋值
always @(*)
result = 3’d3;
case(sel)
2’b00: result = 3’d0;
2’b01: result = 3’d1;
2’b10: result = 3’d2;
endcase
11. 在always块中混合阻塞和非阻塞赋值
verilog指定了总是可以出现在块中的两种赋值类型:阻塞和非阻塞。阻塞和非阻塞赋值分别用于描述组合逻辑和时序逻辑。永远不要在同一个块中混合使用阻塞和非阻塞赋值。这样做可能会导致不可预知的综合和仿真结果。在许多情况下,综合工具不会产生任何警告,但综合结果将是不正确的。以下两个代码示例说明了阻塞和非阻塞赋值的混合使用。
reg blocking, non_blocking;
always @(posedge clk) begin
if(reset) begin
blocking = 0;
non_blocking
end
else begin
blocking = ^data;
non_blocking
end
end
always @(*) begin
blocking = ^data;
non_blocking
end
正确的方法是:
reg blocking, non_blocking;
always @(posedge clk) begin
if(reset) begin
non_blocking
end
else begin
non_blocking
end
end
always @(*) begin
blocking = ^data;
end
12. 多个阻塞赋值
always块中的阻塞赋值按其顺序执行。 尽管这样做通常很方便,但是建议开发者限制使用多个阻塞赋值来赋值always块中的相同变量。下面的两个代码示例显示了使用多个阻塞分配的潜在问题。
reg signal_a, signal_b, signal_c, signal_d;
always (*) begin
signal_a = signal_b & signal_c;
// …
// additional code
signal_d = signal_a & signal_e;
end
无意中改变signal_a和signal_d分配的顺序将会破坏signal_d的功能。
reg [15:0] signal_a, signal_b;
always (*) begin
signal_a[15:12] = 4’b0;
// …
// additional code
signal_a = signal_b;
end
signal_a的最后一个赋值优先,signal_a的位[15:12]永远不会被复位。
13. 使用命名的always块
以下是always块的例子。
reg reg_unnamed;
always @(posedge clk) begin : myname
// only visible in the “myname” block
reg reg_named;
// post-synthesis name : myname.reg_named
reg_named
// post-synthesis name : reg_unnamed
reg_unnamed
end // always
命名块可以在几种情况下有用。 因为always块是唯一标识的,所以在仿真中更容易找到它。 而且,限制变量的范围允许重复使用相同的变量名称。
如何从选型和安装上避免压力变送器故障
出售Agilent83494A时钟恢复模块
压电能量收集器的制作图解
用于便携式远程痕量生物标志物检测的自供电传感装置
Mu6 Ring空气耳机:黑科技加持,不入耳的“运动”耳机
FPGA代码经验 case,casez,casex语句
局部放电检测难度大、风险高?FLIR Si124让你安全准确检测
从类型/原理/特点及应用四个方面论述温度传感器
本周看点:三星赔偿苹果5.38亿美元 小米正式进军意大利
选用颗粒专用热值仪化验颗粒燃料发热量,轻松实现零误差
技术分享|使用TSMaster从零打造车辆控制器HIL实时仿真系列5-ECU HIL仿真的具体实施
ICinsights:DRAM年度销售额将突破1000亿美元 NAND闪存销售额有望达到626亿美元
人脸识别辅助系统使安检更加便捷
新的定点DSP系列提供并行信号的高性能处理
浅谈电线电缆家装布线的规范以及相关常识
软通云智能跻身Forrester Wave™ 市场领导者象限
特斯拉发布重磅AI芯片 AI独角兽商汤科技最早月底赴港上市
工业互联网园区指南
卢伟冰:苹果公司如果还那么傲慢,市场份额还会继续下滑!
“新基建”下,5G模组风口已来