VERILOG中IF和CASE 语句的互换问题

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了VERILOG中IF和CASE 语句的互换问题相关的知识,希望对你有一定的参考价值。

module state_machine(A,B,C,rst,clk,Z,W);

input [3:0] A,B,C;
input rst,clk;
output [5:0] Z;
wire [4:0] Y;
reg [5:0] Z;
wire [6:0] Y1,Y2;
output W;
reg W;
reg[1:0] CTRL;

adder adder1(.input1(A),.input2(B),.output1(Y));
adder adder2(.input1(Z),.input2(Y),.output1(Y1));
adder adder3(.input1(Z),.input2(C),.output1(Y2));

always@(posedge clk or negedge rst)
begin
if(rst==0)
begin
Z=6'b000000; //reset all outputs
CTRL <= 2'b00;
end
else
begin

if (CTRL==2'b00)
begin
Z <= 6'b000000;
W <= 1'b0;
CTRL <= CTRL+2'b01;
end

else if (CTRL==2'b01)
begin
Z = Y1;
W <= 1'b0;
CTRL <= CTRL+2'b01;
end

else if (CTRL==2'b10)
begin
Z = Y2;
W <= 1'b0;
if(Z>4*A)
CTRL <= 2'b11;
else
CTRL <= 2'b01;
end

else if(CTRL==2'b11)
begin
W <= 1'b1;
Z = Z;
CTRL <= 2'b11;
end
end
end
endmodule

想问一下如何把上面的IF ELSE语句改成CASE语句?我的程序如下,但是结果不对
module state_machine(A,B,C,rst,clk,Z,W);

input [3:0] A,B,C;
input rst,clk;
output [5:0] Z;
wire [4:0] Y;
reg [5:0] Z;
wire [5:0] Y1,Y2;
output W;
reg W;
reg[1:0] CTRL;

adder adder1(.input1(A),.input2(B),.output1(Y));
adder adder2(.input1(Z),.input2(Y),.output1(Y1));
adder adder3(.input1(Z),.input2(C),.output1(Y2));

always@(posedge clk or negedge rst)
begin
if(rst==0)
begin
Z=6'b000000; //reset all outputs
CTRL <= 2'b00;
end
end

always@(CTRL)
begin
case(CTRL)
2'b00:begin
Z <= 6'b000000;
W <= 1'b0;
CTRL <= CTRL+2'b01;
end

2'b01:begin
Z = Y1;
W <= 1'b0;
CTRL <= CTRL+2'b01;
end

2'b10:begin
Z = Y2;
W <= 1'b0;
if(Z>4*A)
CTRL <= 2'b11;
else
CTRL <= 2'b01;
end

2'b11:begin
W <= 1'b1;
Z = Z;
CTRL <= 2'b11;
end

default: begin
Z=6'b000000;
CTRL <= 2'b00;
end

endcase
end

endmodule

基本的语法都不通,非阻塞赋值是综合成寄存器的,需要在时钟的沿触发,不能写成组合逻辑。

另外每一个信号单独成块,不要合在一起写,难以定位
参考技术A always@(posedge clk or negedge rst)
begin
if(rst==0)
begin
Z=6'b000000; //reset all outputs
CTRL <= 2'b00;
end
else
case(CTRL)
2'b00:begin
Z <= 6'b000000;
W <= 1'b0;
CTRL <= CTRL+2'b01;
end

2'b01:begin
Z = Y1;
W <= 1'b0;
CTRL <= CTRL+2'b01;
end

2'b10:begin
Z = Y2;
W <= 1'b0;
if(Z>4*A)
CTRL <= 2'b11;
else
CTRL <= 2'b01;
end

2'b11:begin
W <= 1'b1;
Z = Z;
CTRL <= 2'b11;
end

default: begin
Z=6'b000000;
CTRL <= 2'b00;
end
end
endcase

我也是初学者,不知道这样行不行。
另外楼上说:“另外每一个信号单独成块,不要合在一起写,难以定位”具体什么意思,能详细说说吗
参考技术B 从代码看楼主需要补基础。
推荐简@贝斯克的书,黄色+白色皮的那本,
薄薄的一小本,绝对解决楼主的问题。

Verilog的If语句和Case语句

这篇文章将讨论 verilog 中两个最常用的结构----if语句和case语句。

在之前的文章中学习了如何使用过程块(例如always块)来编写按顺序执行的verilog 代码。此外还可以在过程块中使用许多语句----统称为顺序语句,如case 语句和 if 语句。

这篇文章将讨论如何在 verilog 中使用这两个语句,然后,针对这两种语句构造一个简短的示例,以展示如何在实践中使用它们。

1、Verilog If 语句

if 语句是一种条件语句,它使用布尔条件来确定要执行哪些 verilog 代码。每当条件判定为时,就执行与该条件对应的代码分支,反之亦然。此语句类似于其他编程语言(如C语言)中所使用的条件语句if。

下面的 verilog 代码片段展示了 if 语句的基本语法。

if (<expression1>) begin
  //要执行的代码
end

else if (<expression2>) begin
  //要执行的代码
end

else begin
  //要执行的代码
end

如果不需要,可以从语句中排除 else 和 else-if 分支。当然,设计者也可以根据需要包含尽可能多的 else-if 分支以正确实现底层电路。

在上面的代码片段中,这些表达式由<expression1> <expression2> 给出。这些表达式按顺序计算,如果表达式的计算结果为,则执行与表达式关联的代码;反之亦然。

if 语句中只有一个分支会被执行----通常是第一个计算结果为真的表达式。唯一的例外是当所有表达式都不为真时,在这种情况下,将执行 else 分支中的代码。

与每个分支关联的代码可以包括任何有效的 verilog 代码,包括下一级的 if 语句----这种方法称为嵌套式 if 语句。

在 verilog 中使用此类代码时,应该注意限制嵌套语句的数量,因为它会导致难以满足时序要求。

If 语句示例

接下来将以用异步复位的D触发器实现的多路选择器作为示例讲解如何使用if语句。

下面的电路图是该示例的电路。

下面的代码片段展示了如何使用一个 always 块和一个 if 语句来实现预期功能。

always @(posedge clock, posedge reset) begin
  if (reset) begin
    Q <= 1'b0;
  end
  else begin
    if (addr) begin
      Q <= b;
    end
    else begin
      Q <= a;
    end
  end
end

此示例使用的第一个 if 语句在复位时将触发器的输出设置为 0。当复位未使能且always 块被时钟的上升沿触发时----使用第一个 if 语句的 else 分支来处理这种情况。

第二个 if 语句用来实现多路选择器电路的功能---这是 verilog 中嵌套式 if 语句的示例。

当addr信号为0时,输入a的值将赋给触发器的输出,嵌套 if 语句的第一个分支将用来捕获此情况。然后,嵌套 if 语句的 else 分支被用来捕获 addr 信号为 1 的情况。

当然也可以在这里使用 else-if 类型的语句,但是 else 语句更简洁。这两种情况下的行为是相同的,因为在真实电路中信号只能是 0或 1。

2、Verilog Case语句

verilog中的case 语句根据设计中给定信号的值选择要执行的代码块。在 verilog 中编写 case 语句时,先要指定了一个要进行判断的输入信号,然后将此信号的值与 case 语句的每个分支中指定的值进行比较。一旦找到该值的匹配项,就执行该值关联的代码分支。

Verilog case 语句和C语言等编程语言中的 switch 语句功能类似。

下面的代码片段展示了 verilog 中 case 语句的一般语法。

case (<variable>)
  <value1> : begin
    //当<variable> = <value1>时执行这条语句
  end
  <value2> : begin
    //当<variable> = <value2>时执行这条语句
  end
  default : begin
    //其他条件是执行这条语句
  end
endcase

可以不使用语句的default分支----但不推荐。如果不使用语句的default分支,就应该把<variable>所有有效值都列举出来

与 if 语句一样,与每个分支关联的代码可以包含任何有效的 verilog 代码。这包括下一级的顺序语句,例如 if 或 case 语句。同样,设计者也应该尽量限制嵌套语句的数量,不然设计的时序要求会是个问题。

Case语句示例

为了更好地演示在 verilog 中使用 case 语句的方式,请考虑这样的一个基本示例----简单的4选1多路选择器电路

case 语句经常被用来在 verilog 中实现大型的多路选择器,因为它产生的代码比基于连续赋值的实现方式更具可读性

下面的电路图展示了本例中所使用的电路。

下面的代码片段展示了如何使用 case 语句来实现这个电路。

always @(*) begin
  case (addr)
    2'b00 : begin
      q = a;
    end
    2'b01 : begin
      q = b;
    end
    2'b10 : begin
      q = c;
    end
    default : begin
      q = d;
    end
  endcase
end

此示例展示了使用 verilog 中的 case 语句实现多路选择器是多么简单的一件事。事实上,case 语句是在 verilog 中实现多路选择器的最直观方法。

在这个例子中要注意的是使用了阻塞赋值,这样做的原因是要实现组合逻辑电路,非阻塞赋值则通常会导致在设计中生成触发器。要注意的另一件事是这个例子中可以删除 default 关键字----但应该显式地列出输出 d 值所需的所有潜在的 addr 值。


  • 📣您有任何问题,都可以在评论区和我交流📃

  • 📣您的支持是我持续创作的最大动力!如果本文对您有帮助,还请多多点赞👍、评论💬和收藏


以上是关于VERILOG中IF和CASE 语句的互换问题的主要内容,如果未能解决你的问题,请参考以下文章

verilog中用if语句替换case D idea: one: two: three: end case

verilog中if else中能套if else吗,有啥错误啊,为啥??? case中能套if else吗 case中能套case吗

verilog要用到的if else太多怎么办

关于verilog中 if else 的问题

verilog中if else中能套if else吗,有啥错误啊,为啥??? case中能套if else吗 case中能套case吗

verilog语法,有关case语句