Verilog基础语法(12)之控制块


Verilog有一套控制流块和机制来实现。它包括:

  • if-else
  • forever loop
  • repeat loop
  • while loop
  • for loop

if条件语句

这个条件语句用来决定是否应该执行某些语句。这与C语言中的if-else-if语句非常相似。如果表达式的值为真,那么第一条语句将被执行。如果表达式的值为false,并且如果存在一个else部分,那么else部分将被执行。

如果需要在if或者else部分内放置多条语句,则需要用 begin和end括起来。

语法表达式:

// if statement without else part
if (expression)
	[statement]

// Use "begin" and "end" blocks for more than 1 statements
if ([expression]) begin
	Multiple statements
end

// if statment with an else part
if (expression)
	[statement]
else
	[statement]

// if else for multiple statements should be
// enclosed within "begin" and "end"
if (expression) begin
	[multiple statements]
end 
else begin
	[multiple statements]
end

// if-else-if statement
if (expression)
	[statement]
else if (expression)
	[statement]
else
	[statement]

// if-else-if style to check for more expressions if the previous one doesn't match
if ([expression 1])
	Single statement
else if ([expression 2]) begin
	Multiple Statements
end 
else
	Single statement

单独if

if没有else部分,意味着对于任何不满足if内部表达式的条件,其值保持不变。
保持不变的硬件对应位锁存器,例:

module des (  input en,
              input d,
              output reg q);

    always @ (*)
        if (en)
            q = d;

endmodule

RTL原理图:
在这里插入图片描述

带有else的if

如果rstn为高电平,输出q将在时钟的上升沿得到输入d的值,并描述了D触发器的行为。

module dff (	input clk,
							input rstn,
							input d,
							output reg q);

	always @ (posedge clk) begin
		if (! rstn)
			q <= 0;
		else
			q <= d;
	end
endmodule

RTL原理图:
在这里插入图片描述
这个例子中是一个同步低电平复位,但从上图RTL原理图看出,仍然像是一个异步复位,因为复位信号的输出接到了触发器的rst端,这是什么情况呢?

在刚学习FPGA的时候我就遇到过这个一个问题,也就是综合的原理图(综合的情况应该和RTL原理图一致,只不过使用了某些器件的替换)和硬件语言描述的不一致问题。

原因:ISE软件中某些器件的D触发器自带了同步复位,所以看上去像异步复位!

在Verilog程序设计中,if_else语句和case语句都是选择语句,当满足某个条件是,就选择某一样状态,当然这两个语句也是有区别的。

if_else语句具有优先级,是顺序执行的语句,所以我们在写if_else语句时需要对优先级进行考量,不然就会产生和我们设计不符的结果,并且还不容易发现错误。

case语句不具有优先级,是一种并行执行的语句。在实际设计中,一般类别少时用if_else语句,类别多用case语句,if_else语句基本上可以处理所有的复杂判断条件,但是在实际电路中占用的资源较多,所以能用case语句尽量用case语句。

if-else-if

设计模块有一个4位输出q,当模式为1时递增,当模式为2时递减,使用if else结构。请注意,描述中没有说明如果模式为0或3时要做什么,这些都是2位变量的有效值。假设当模式为1和3时,电路什么都不做,但保持q的退出值,不建议在实际设计代码中留下这种含糊不清的地方,但在这里是为了强调这种可能性。

module des ( 
			input [1:0] mode,
            input clk,
            input rstn,
            output reg [3:0] q);

  always @ (posedge clk) begin
    if (! rstn)
      q <= 0;
    else begin
      if (mode == 1)
        q <= q + 1;
      else if (mode == 2)
        q <= q - 1;
    end
  end
endmodule

循环语句

foever

这将连续执行块内的语句,不可综合。

forever
	[statement]

forever begin
	[multiple statements]
end

这条语句常用于仿真中生成时钟信号,例如:

initial begin
clk = 0;
end

forever begin
#5 clk = ~clk;
end

repeat

这将执行固定次数的语句。如果表达式的值是X或Z,那么它将被视为零,根本不会被执行。不可综合。

repeat ([num_of_times]) begin
	[statements]
end

repeat ([num_of_times]) @ ([some_event]) begin
	[statements]
end
module my_design;
	initial begin
		repeat(4) begin
			$display("This is a new iteration ...");
		end
	end
endmodule

仿真结果:

This is a new iteration ...
This is a new iteration ...
This is a new iteration ...
This is a new iteration ...

while

只要表达式为真,就会执行语句,一旦条件为假,就会退出。如果条件从一开始就是假的,则根本不会执行语句。不可综合。

while (expression) begin
	[statements]
end
module my_design;
  	integer i = 5;

	initial begin
      while (i > 0) begin
        $display ("Iteration#%0d", i);
        i = i - 1;
      end
	end
endmodule

仿真结果:

Iteration#5
Iteration#4
Iteration#3
Iteration#2
Iteration#1

for

for循环是软件中使用最广泛的循环,但它主要用于复制Verilog中的硬件逻辑。for循环背后的思想是,只要给定的条件为真,就对循环内给定的一组语句进行迭代。这与while循环非常相似,但更多的是用在有迭代器的情况下,条件取决于这个迭代器的值。

for (<initial_condition>; <condition>; <step_assignment>) begin
	// Statements
end
  • 初始条件指定信号的初始值
  • 用于评估给定条件是否为真的检查。
  • 更新下一次迭代的控制变量

注:for循环使用得当,是可以综合的。
8为左移寄存器使用传统和for循环对比:
传统方法:

module lshift_reg (input 						clk,				// Clock input
                   input 						rstn,				// Active low reset input
                   input [7:0] 			load_val, 	// Load value
                   input 						load_en, 		// Load enable
                   output reg [7:0] op); 				// Output register value

	 always @ (posedge clk) begin
	    if (!rstn) begin
	      op <= 0;
	    end 
	    else begin
	    	if (load_en) begin
	      	op <= load_val;
	      end 
	      else begin
	        op[0] <= op[7];
	        op[1] <= op[0];
	        op[2] <= op[1];
	        op[3] <= op[2];
	        op[4] <= op[3];
	        op[5] <= op[4];
	        op[6] <= op[5];
	        op[7] <= op[6];
	      end
	    end
	  end
endmodule

for循环:

module lshift_reg (input 						clk,				// Clock input
                   input    				rstn,				// Active low reset input
                   input [7:0] 			load_val, 	// Load value
                   input 						load_en, 		// Load enable
                   output reg [7:0] op); 				// Output register value

	 integer i;
	 always @ (posedge clk) begin
	    if (!rstn) begin
	      op <= 0;
	    end 
	    else begin
	    	if (load_en) begin
	      	op <= load_val;
	      end 
	      else begin
            for (i = 0; i < 7; i = i + 1) begin
              op[i+1] <= op[i];
            end
            op[0] <= op[7];
	      end
	    end
	  end
endmodule
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值