全球最实用的IT互联网信息网站!

AI人工智能P2P分享&下载搜索网页发布信息网站地图

当前位置:诺佳网 > 电子/半导体 > 可编程逻辑 >

FPGA代码经验 case,casez,casex语句

时间:2020-12-11 10:42

人气:

作者:admin

标签: FPGA 

导读:使用case语句代替嵌套的if-else将会产生更易读的代码,更好的逻辑利用率和更高的性能。...

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块是唯一标识的,所以在仿真中更容易找到它。 而且,限制变量的范围允许重复使用相同的变量名称。

编辑:hfy

温馨提示:以上内容整理于网络,仅供参考,如果对您有帮助,留下您的阅读感言吧!
相关阅读
本类排行
相关标签
本类推荐

CPU | 内存 | 硬盘 | 显卡 | 显示器 | 主板 | 电源 | 键鼠 | 网站地图

Copyright © 2025-2035 诺佳网 版权所有 备案号:赣ICP备2025066733号
本站资料均来源互联网收集整理,作品版权归作者所有,如果侵犯了您的版权,请跟我们联系。

关注微信