verilog - 将 x(无关)分配给寄存器复位值或组合输出以提高区域效率
问题描述
我的问题是关于 FPGA 设计的——如果我的设计中有一些寄存器我不在乎它们的复位值是多少,我可以将复位值设置为 x 吗?这会提高面积效率(合成器是否能够利用这一点并以更有效的方式生成设计?)例如,
always @(posedge clk or negedge reset_n) begin
if(~reset_n) begin
reg_1 <= 'x
end
...
end
编辑:另一个类似主题的问题——假设我有一个状态机,例如我不在乎某些状态下的某些输出是什么——将它们设置为 'x 会提高区域效率吗?例如,如果我有一个具有两个状态的 fsm,STATE_1、STATE_2 和两个输出,那么综合工具将能够使用以下代码:
always_comb begin
case(state):
STATE_1:begin
out_1 = 1;
out_2 = x;
end
STATE_2:begin
out_1 = x;
out_2 = 0;
end
end
比这更好:
always_comb begin
case(state):
STATE_1:begin
out_1 = 1;
out_2 = 0;
end
STATE_2:begin
out_1 = 0;
out_2 = 0;
end
end
(假设我不在乎 STATE_1 中的 out_2 是什么,以及 STATE_2 中的 out_1 是什么)。谢谢
解决方案
'x
在顺序逻辑中使用
是的,在 Verilog 方面,您可以使用这种语法。但是,在您的特定示例中,这样做并没有真正意义,您可能会认为这是一种糟糕的编码实践。除了显式分配'x
,您还可以省略异步重置。
以下两个过程将综合到同一个触发器。我个人建议使用后一种风格。
// Assigning 'x to tell synthesis tool that there is no reset value
always @(posedge clk or negedge reset_n)
if(~reset_n)
reg_1 <= 'x;
else
reg_1 <= reg_1_next;
// Omitting the asynchronous reset from the sensitivity list to tell
// synthesis tool that there is no reset
always @(posedge clk)
reg_1 <= reg_1_next;
一般来说:如果您有不同的变量必须是可重置或不可重置的,您应该将它们的分配拆分为不同的always
块。这通常会使您的代码更具可读性。请参见下面的示例:
// Do NOT do this
always @(posedge clk or negedge reset_n)
if(~reset_n)
begin
vld <= 1'b0;
reg_1 <= 'x;
end
else
begin
vld <= vld_next;
reg_1 <= reg_1_next;
end
// Do this
always @(posedge clk or negedge reset_n)
if(~reset_n)
vld <= 1'b0;
else
vld <= vld_next;
always @(posedge clk)
reg_1 <= reg_1_next;
奖金
'x
话虽如此,在某些情况下,分配复位条件以告诉综合工具不要为特定变量生成可复位触发器是有意义的。请看一下这个答案:https ://stackoverflow.com/a/21477457/7949378
让我们根据这个答案创建一个示例。假设您有一个具有 1 个有效信号 ( vld
) 和 2 个数据信号 ( data_a
and data_b
) 的结构。数据仅在 为 时vld
有效1'b1
。换句话说,我们可以通过只重置vld
而不重置data_a
and来节省面积data_b
。
现在,我们想利用结构的全部潜力,并简单地分配完整的结构而不是单独的成员(请参阅 参考资料struct_example_q <= struct_example_next;
)。这意味着我们不能将此always
-block 拆分为两个单独的进程(就像我之前推荐的那样)。在这种情况下,我们必须明确告诉综合工具不要重置数据信号。
请看下面的代码:
typedef struct {
logic vld;
logic [31:0] data_a;
logic [31:0] data_b;
} struct_example_t;
struct_example_t struct_example_next;
struct_example_t struct_example_q;
always @(posedge clk or negedge reset_n)
if (!reset_n)
begin
/**
* Only reset the valid-bit
* We could use '{default:'x} to simplify this even further
**/
struct_example_q.data_a <= 'x;
struct_example_q.data_b <= 'x;
struct_example_q.vld <= 1'b0;
end
else
begin
struct_example_q <= struct_example_next;
end
'x
在组合逻辑中使用
让我们先看看你的 RTL:
always_comb begin
case(state):
STATE_1:begin
out_1 = 1;
out_2 = x;
end
STATE_2:begin
out_1 = x;
out_2 = 0;
end
end
我想指出,这并不是最好的例子。假设 FSM 是满的——也就是说,这STATE_1
是STATE_2
唯一state
可以采取的两种状态——你会用下面的代码实现完全相同的效果,假设你无论如何都不用 caseout_1
和out_2
在其他状态下。
always_comb begin
out_1 = 1;
out_2 = 0;
end
现在,为了这个例子,让我们假设我们不能重写它。在这种情况下,您应该在案例陈述之前设置默认值。这可以防止综合逻辑在您的无关状态下推断锁存器,但它也可以帮助您在开始进行门级仿真 (GLS)时不会遇到问题。'x
使用您的示例,您的 RTL 将如下面的代码所示。(再次注意,这里的情况有点多余。)
always_comb begin
out_1 = 1;
out_2 = 0;
case(state):
STATE_1:begin
out_1 = 1;
end
STATE_2:begin
out_2 = 0;
end
end
一旦你有了更精细的 FSM,你就会发现这个策略是有意义的。
奖金
我想举一个使用unique
orpriority
有意义的例子(而不是'x
作为默认值使用)。看看下面的 RTL 并假设它select == 3'b0
永远不会发生:
always_comb
begin
out_1 = 'x;
case (1'b1)
select[0]: out_1 = a & b;
select[1]: out_1 = a ^ b;
select[2]: out_1 = a | b;
endcase
end
设置默认值out_1
将阻止逻辑推断锁存器(因为它不知道select == 3'b0
永远不会发生)。此外,'x
此处将帮助综合工具优化此逻辑(不一定是 wrt 区域!)。然而,正如我们之前所讨论的,使用'x
通常被认为是不好的做法。
您可以不使用默认值,而是使用priority
关键字告诉综合工具已列出所有有效案例,并且该工具必须按顺序评估您的案例。因此,以下情况也将被视为已满:
always_comb
priority case (1'b1)
select[0]: out_1 = a & b;
select[1]: out_1 = a ^ b;
select[2]: out_1 = a | b;
endcase
此外,如果您可以确定这select
是一个单热信号 ( $countones(select) == 1
),则可以使用unique
关键字。这将告诉综合工具这是完全并行的情况
always_comb
unique case (1'b1)
select[0]: out_1 = a & b;
select[1]: out_1 = a ^ b;
select[2]: out_1 = a | b;
endcase
请注意,如果您违反了使用priority
或unique
.
推荐阅读
- security - 如何告诉我的用户他们输入了旧密码?
- c# - 跟踪 Revit 2018/ 2019 中的元素编辑或元素编辑事件
- javascript - Javascript - 如何使用 javascript 回调进行阻塞
- javascript - 没有找到选择器的节点,但选择器在 HTML 页面上
- mysql - 如何编写像 WHERE ban IN ('apple', 'banana', 'coconut') 这样的查询,ban 将匹配香蕉
- javascript - (C3 js) 加载 CSV 文件并使用时间序列
- java - For循环组合线
- python - Kivy 弹出窗口动态高度
- python - 在 sqlite3 中执行时如何使用元组中的值
- swift - 如何在 ios-Charts 的条形图中将渐变应用于条形图