学习:
An if statement usually creates a 2-to-1 multiplexer, selecting one input if the condition is true, and the other input if the condition is false.
always @(*) begin if (condition) begin out = x; end else begin out = y; end end
This is equivalent to using a continuous assignment with a conditional operator:
assign out = (condition) ? x : y;
However, the procedural if statement provides a new way to make mistakes. The circuit is combinational only if out is always assigned a value.
译:
一个 if 语句通常会产生一个2选1的多路选择器(multiplexer),如果条件为真,则选择一个输入;如果条件为假,则选择另一个输入。
这相当于使用带有条件运算符的连续赋值(continuous assignment):
assign out = (condition) ? x : y;
然而,程序化的 if 语句提供了犯新错误的可能。只有当输出 out
总是被赋值时,电路才是组合逻辑的。
练习:
Build a 2-to-1 mux that chooses between a and b. Choose b if both sel_b1 and sel_b2 are true. Otherwise, choose a. Do the same twice, once using assign statements and once using a procedural if statement.
构建一个2选1多路选择器(2-to-1 mux),在 a
和 b
之间进行选择。如果 sel_b1
和 sel_b2
都为真,则选择 b
。否则,选择 a
。用两种方式完成这个任务,一次使用赋值语句(assign statements),一次使用程序化的 if 语句。
sel_b1 | sel_b2 | out_assign out_always |
---|---|---|
0 | 0 | a |
0 | 1 | a |
1 | 0 | a |
1 | 1 | b |
// synthesis verilog_input_version verilog_2001
module top_module(
input a,
input b,
input sel_b1,
input sel_b2,
output wire out_assign,
output reg out_always );
assign out_assign = (sel_b1 & sel_b2)?b:a;
always@(*) begin
if (sel_b1 & sel_b2) begin
out_always = b;
end
else begin
out_always = a;
end
end
endmodule
运行结果:
分析:
主要是两种判断方式的使用,一种是前面提到的三元选择法(三元运算符);另外就是if - else的方法;
使用if - else的方法要注意使用格式,配合好 begin - end 的调用;另外 if- else 只能在 always中调用,要注意赋值方式;关于赋值方式的选择,参考上一篇;
介绍begin - end
在硬件描述语言(HDL)如Verilog和SystemVerilog中,`begin` 和 `end` 是用来定义代码块的关键字。它们通常成对出现,用以标识一段特定的代码区域的开始和结束。这种结构在编写复杂的赋值语句、条件语句、循环语句以及其他控制结构时非常有用。
组合逻辑中的 `begin` - `end`
在组合逻辑的 `always` 块中,`begin` 和 `end` 用于包含一系列的赋值和操作,这些操作是同时发生的,不涉及时序控制。
always @(a or b) begin
// 组合逻辑操作
output = a & b; // 逻辑与操作
// 更多的组合逻辑操作...
end
在这个例子中,`begin` 和 `end` 之间的代码块定义了输出信号 `output` 是如何根据输入信号 `a` 和 `b` 的逻辑与结果来计算的。
### 时序逻辑中的 `begin` - `end`
在时序逻辑的 `always` 块中,`begin` 和 `end` 也用于定义代码块,但这里的操作是按照它们在代码中出现的顺序依次执行的,并且通常与时钟信号的边沿同步。
always @(posedge clk) begin
// 时序逻辑操作
if (reset) begin
reg_value = 0; // 异步复位
end else begin
reg_value = input; // 时钟边沿触发的赋值
end
end
在这个例子中,`begin` 和 `end` 之间的代码块定义了一个寄存器 `reg_value` 的行为。当复位信号激活时,`reg_value` 被异步清零;否则,在时钟的上升沿,`reg_value` 会被 `input` 的值更新。
### 条件语句中的 `begin` - `end`
在 `if`、`else if`、`else` 条件语句中,`begin` 和 `end` 用于定义每个条件分支的代码块。
if (condition1) begin
// 条件1为真时执行的代码
end else if (condition2) begin
// 条件2为真时执行的代码
end else begin
// 所有条件都不为真时执行的代码
end
### 循环语句中的 `begin` - `end`
在 `for`、`while` 循环语句中,`begin` 和 `end` 定义了循环体中的操作。
for (i = 0; i < N; i = i + 1) begin
// 循环体内的代码
end
在这个例子中,`begin` 和 `end` 之间的代码块定义了 `for` 循环的执行体。
### 总结
`begin` 和 `end` 是Verilog和SystemVerilog中定义代码块的重要结构。它们使得代码更加结构化和模块化,提高了代码的可读性和可维护性。无论是在组合逻辑还是时序逻辑中,正确地使用这些关键字对于设计正确的硬件电路至关重要。