当前位置:网站首页>别乱用 FULL_CASE 和 PARALLEL_CASE
别乱用 FULL_CASE 和 PARALLEL_CASE
2022-06-26 12:37:00 【孤独的单刀】
文章目录
写在前面
case语句可以说是我们在FPGA开发中使用频率非常高的一条语句。同时,Verilog还提供了语句 casex 和 casez供我们使用。在使用case语句的时候,各类综合工具都提供了以下类似的两句综合语句供我们使用(以Xilinx为例):FULL_CASE 和 PARALLEL_CASE
这两条综合属性可以帮助我们在一定程度上减少资源,但是其使用也比较容易引入BUG--前后仿真不匹配。接下里就一起看看这把双刃剑的正反两面吧。
1、FULL_CASE的用法
在case语句的使用中,我们通常会加上default语句来说明未使用状态的输出赋值,如果不加上default语句则通常会产生锁存器LATCH。
1.1、使用default语句
在如下的8位独热码编码器中,我们用default语句指令了所有除8个有用状态的其他状态。8位2进制数可以一共表示256个状态,这其中只有这8个状态是独热码,剩余的都是我们不需要的。使用default语句全给其输出接到了统一的0。但是,虽然我们不需要使用其他状态,但是综合出来的电路也会有其他状态的编码部分。
module one_hot(
input [7:0] sel,
output reg [2:0] out
);
always @(*) begin
case(sel)
8'b0000_0001 : out = 3'b000;
8'b0000_0010 : out = 3'b001;
8'b0000_0100 : out = 3'b010;
8'b0000_1000 : out = 3'b011;
8'b0001_0000 : out = 3'b100;
8'b0010_0000 : out = 3'b101;
8'b0100_0000 : out = 3'b110;
8'b1000_0000 : out = 3'b111;
default : out = 3'b001;
endcase
end
endmodule下图是综合出来的电路结构,就是一个纯组合逻辑的编码电路。

使用的资源情况:6个LUT。

1.2、不使用default语句
接下来把default语句注释掉,这样在非独热码状态的情况下,输出就只能保持之前的状态不变了,也就是说3bit输出应该会输出3个锁存器LATCH。
综合出来的电路结构如下,和料想的一致,组合逻辑LUT+锁存器LATCH。

使用的资源情况:5个LUT + 3个FF(FF转变的LATCH)。

1.3、使用综合属性 FULL_CASE
那么综合属性 FULL_CASE是干啥的?
FULL_CASE的作用就是告诉综合工具,在这个case语句中,我已经把所有需要的情况都列出来的,剩下的那些是我不需要,你可别再生成多余的电路了。
还是上面的例子,8bit的独热码编码器,我已经把8个独热码都列出来了,剩下的那256-8=248个臭鱼烂虾都不是独热码编码形式的,我肯定不会用,所以我警告你(综合工具)最好识相点儿,不要生成对应剩余编码的编码电路了。
module one_hot(
input [7:0] sel,
output reg [2:0] out
);
always @(*) begin
(* full_case *)case(sel) //所有需要的情况都列出来了
8'b0000_0001 : out = 3'b000;
8'b0000_0010 : out = 3'b001;
8'b0000_0100 : out = 3'b010;
8'b0000_1000 : out = 3'b011;
8'b0001_0000 : out = 3'b100;
8'b0010_0000 : out = 3'b101;
8'b0100_0000 : out = 3'b110;
8'b1000_0000 : out = 3'b111;
//default : out = 3'b001;
endcase
end
endmodule综合出来的电路,比上面两种情况少用了很多资源。因为多余的248个状态vivado不需要编码了,只需要对8个独热码状态进行编码即可。

使用的资源情况:3个LUT。

1.4、综合前后电路仿真不一致
优点是显而易见的,就是节省资源。缺点同样明显,那就是 FULL_CASE 语句是一条综合属性,只能在vivado对RTL进行综合,translate成电路的时候才使用,在做功能仿真的时候是不适用的,也就是说会造成前后仿真结果不一致的问题,容易引入BUG。
我们可以写个简单的testbench分别对综合前、综合后的功能仿真做下测试。
`timescale 1 ns/ 1 ns
module one_hot_tb();
reg [7:0] sel;
wire [2:0] out;
one_hot one_hot_inst(
.sel (sel),
.out (out)
);
initial begin
sel=8'b0;
# 400 $finish; //200ns后结束仿真
end
always #10 sel = {$random}%256; //没10ns生成一个0~255的随机数
endmodule综合前功能仿真结果如下:

由于之前sel值均不是独热码值,所以输出out无法被编码,又没有使用default语句,所以此时的输出均为x。直到第一个独热码00000001出现,输出开始编码到000。后面又不符合独热码规则,无法编码,所以输出值一直保持之前的值不变,成为了事实上的锁存器。

直到输入重新变成了10000000和00100000后,输出才开始变成对应的编码值 。
综合后功能仿真结果如下:

这个结果是没有生成锁存器的,即使对于非独热码,也有默认的编码值。
1.5、陷阱
一般情况下,FULL_CASE 语句是不建议使用的,除非你对自己的RTL代码和电路结构有很深的理解。下面是一些使用该语句的陷阱。
(情况一:可能还会存在的锁存器)
有种说法是:FULL_CASE 语句技能减少资源使用,也能消除锁存器。实则不然,在某些情况下FULL_CASE 语句并不能消除锁存器,比如:
module addrDecode1a (mce0_n, mce1_n, rce_n, addr);
output mce0_n, mce1_n, rce_n;
input [31:30] addr;
reg mce0_n, mce1_n, rce_n;
always @(addr)
(* full_case *)casez (addr)
2'b10: {mce1_n, mce0_n} = 2'b10;
2'b11: {mce1_n, mce0_n} = 2'b01;
2'b0?: rce_n = 1'b0;
endcase
endmodule综合出来的电路结构:可以看到还是综合出了2个锁存器。这是因为在case执行语句中,同时出现了对多个变量和单个变量进行赋值,这使得在某些条件下某些变量是无法执行输出的。

解决这一情况的办法,就是在case语句之前对所有变量均进行赋值,后者直接使用default语句,让所有的情况都有一个入口。
(情况二:非预期的电路结构)
有些时候,如果不注意电路的结构,非要使用FULL_CASE 语句的话,甚至会综合出与预期功能完全不一样的电路。比如:
// no full_case
module code4a (y, a, en);
output [3:0] y;
input [1:0] a;
input en;
reg [3:0] y;
always @(a or en) begin
y = 4'b0; //初始赋值,防止其他情况无入口产生锁存器
case ({en,a})
3'b1_00: y[a] = 1'b1;
3'b1_01: y[a] = 1'b1;
3'b1_10: y[a] = 1'b1;
3'b1_11: y[a] = 1'b1;
endcase
end
endmodule上面的例子中,首先通过 y = 4'b0;为所有情况都提供了一个赋值的入口,防止了锁存器的产生。然后en作为使能信号,只有在其高电平有效的情况下,才能将地址选择信号a对应的输出y[a]的值拉高。
综合出来的电路如下:可以看到每一位y的输出都有en参与运算。

因为地址选择信号只有2位,所以其最大只有4种情况,在上述代码中,这四种情况刚好都列出来。于是,你觉得这个时候可以使用FULL_CASE 语句了,说不定能节省点电路面积。所以,让我们看看接下来会发生什么。
这是使用了FULL_CASE 语句后综合出来的电路:

注意看,这个电路最离谱的是,使能信号en已经和整个电路完全没关系了。这是为什么呢?
这是因为,虽然在使能信号置位时,地址选择信号a只有4个状态;但是在使能信号无效时, 地址选择信号a同样有4个状态。如果使用了FULL_CASE 语句,综合工具可能就会认为此时地址选择信号a已经列出了所有的情况,那么case语句中的{en,a}就从一个3bit信号变成了2bit信号,而自动把使能信号en给忽略掉了!
2、PARALLEL_CASE的用法
在学习综合语句PARALLEL_CASE的使用之前可能需要复习一下casex和casez语句的使用。Verilog中case,casez,casex语句的用法
有时在用case语句时,产生的电路会有优先级。如果希望没有优先级,即所有的输入都是并行的情况,要怎么办呢?答案就是使用综合属性PARALLEL_CASE。
PARALLEL_CASE的作用就是告诉综合工具,在这个case语句中,所有已经被我列出来的情况都是并行的,不需要优先级,你可别按优先级给我生成电路了!
比如下面使用casez语句的例子,如果不使用PARALLEL_CASE属性,则综合出来的电路肯定是有优先级的:
module intctl2a (int2, int1, int0, irq);
output int2, int1, int0;
input [2:0] irq;
reg int2, int1, int0;
always @(irq) begin
{int2, int1, int0} = 3'b0;
casez (irq)
3'b1??: int2 = 1'b1;
3'b01?: int1 = 1'b1;
3'b001: int0 = 1'b1;
endcase
end
endmodule综合出来的电路如下。可以看到 int2 只由 irq[2] 决定,int1 由 irq[2] 和 irq[1] 决定,int0 则由irq[2], irq[1] 和 irq[0] 决定。这是因为 case 语句是有优先级的,写在前面的优先级最高。

接下来我们加入综合属性语句:(* parallel_case *)。
module intctl2a (int2, int1, int0, irq);
output int2, int1, int0;
input [2:0] irq;
reg int2, int1, int0;
always @(irq) begin
{int2, int1, int0} = 3'b0;
(* parallel_case *)casez (irq)
3'b1??: int2 = 1'b1;
3'b01?: int1 = 1'b1;
3'b001: int0 = 1'b1;
endcase
end
endmodule综合的电路如下。修改后的电路已经不存在优先级了,都是对应bit的irq信号直接控制对应的int信号。

parallel_case与full_case综合属性一样,存在的一个最大问题就是综合前后的仿真结果不一致的问题,容易引入BUG。
3、总结
- casez语句的使用要要谨慎,而casex语句则尽量不要使用
- 如果计划在Verilog代码中添加“full_case parallel_case”指令,则需要更对设计的RTL有全面深入的了解
- 不要滥用仅full_case和parallel_case,一般情况下只用来来优化独热码的状态机设计
- 最重要的一点,比起使用“full_case”和“parallel_case”指令,更好的方法是编写完整和并行的case语句!
.
边栏推荐
- 7-2 数的三次方根
- Comparison of latest mobile phone processors in 2020 (with mobile phone CPU ladder diagram)
- 【网络是怎么连接的】第二章(上): 建立连接,传输数据,断开连接
- Installing MySQL under Linux (RPM package installation)
- Mongodb of NoSQL - 03 mongodb CRUD
- Php+laravel5.7 use Alibaba oss+ Alibaba media to process and upload image / video files
- JS get the current screen height method and listen for DOM elements to enter the viewport
- NLP-D60-nlp比赛D29
- Lodash common methods (filtering, anti shake...)
- Mysql8 master-slave replication
猜你喜欢
![[BSidesCF 2019]Kookie 1](/img/22/585d081668e67b8389a1b90aaebe9d.png)
[BSidesCF 2019]Kookie 1

【网络是怎么连接的】第二章(中):一个网络包的发出
solo 博客系统的 rss 渲染失败

Laravel+gatewayworker completes the im instant messaging and file transfer functions (Chapter 4: server debugging errors)

Less than 40 lines of code to create a blocprovider

TP5 thinkphp5 report serialization of'closure'is not allowed

ES6模块

Microservice governance (nocas)

Software testing - Fundamentals
Adobe Acrobat prevents 30 security software from viewing PDF files or there are security risks
随机推荐
轻流完成与「DaoCloud Enterprise 云原生应用云平台」兼容性认证
Ubuntu安装配置PostgreSQL(18.04)
几行代码就能实现复杂的 Excel 导入导出,这个工具类真心强大!
New routing file in laravel framework
QT .pri 的建立与使用
Redis learning - 03 transaction
[solved] data duplication or data loss after laravel paginate() paging
dried food! Yiwen will show you SD card, TF card and SIM card!
TP5 thinkphp5 report serialization of'closure'is not allowed
NoSQL mongodb - 02 mongodb server installation, mongodb shell, basic concepts and visualization tools
opencv高速下载
Introduction to the four major FPGA manufacturers abroad
Learning Processing Zoog
sqlalchemy event listen Automatic generate CRUD excel
710. 黑名单中的随机数
机器学习笔记 - 时间序列的季节性
一个快速切换一个底层实现的思路分享
Websocket and socket IO case practice
find及du -sh显示权限不够的解决方法
NLP-D60-nlp比赛D29