verilog if(0) if(1) 小技巧

  本文主要介绍verilog if(0),if(1)给verilog进行语法修正的功能。 code

  verilog的语法太简单,一直是咱们诟病的地方所在,想实现一个功能有的时候必须敲上大段功能重复的代码段,有的时候只是其中的某个参量发生变化。这个时候懒惰的咱们就会想出一种解决方案,好在verilog标准里(1995,2001)标准里都有对宏的支持。众所周知,宏的做用就是生成代码,有了宏的帮助咱们就能够将大量重复的功能放入宏中,而后在程序中直接写上一句宏便可。这样作的好处是,对咱们总体代码以及综合后的结果没有任何影响,由于宏在编译的时候就已展开。 编译

  ok利用宏已经能够解放咱们少量工做量了。我模拟了下面这样的一个场景。 class

 

always @(posedge clk)
    begin
        case(counter)
        32'd1: begin answer=1/3; signal=0;signal=1;end
        32'd2: begin answer=2/3; signal=0;signal=1;end
        32'd3: begin answer=3/3; signal=0;signal=1;end
        ...
        32'd16: begin answer=16/3;signal=0;signal=1;end
        endcase
    end
不要去想这个例子的功能是什么,这个不是咱们的重点,我想制造的就是每一个case里面包含多句,可是每一个case有规律的差别的一个场景。

  好了,上面这段代码怎么样,若是你接触过其余语言,那么你必定看不惯这种写法,(好吧我认可是我本身看不惯)。 sed

 接下来咱们用咱们强大的帮手宏哥哥来帮咱们减小工做量。 语法

  

always @(posedge clk)
begin
	case(counter)
	32'd1: `div(1)
	32'd2: `div(2)
	32'd3: `div(3)
	...
	32'd15: `div(16)
	endcase
end
宏的定义为
`define div(x) 	begin signal=0; \
	answer=x/3; \
	signal=1; \
	end
一个很简单的参数宏。

  可是看到上面那个宏的使用真的能让咱们知足吗?那个div(1)的分号哪去了?  有人会告诉我说,verilog里宏就是一个简单的替代,你若在`div(x)后面加一个分号,那么展开后将会是 程序

 

begin signal=0;
answer=x/3;
signal=1;
end;
在end;后面加上分号语法是不对的,因此本篇文章的做用就会出来了,本篇就是给这样不能加分号的宏进行语法修正。有人会吐嘈我说至于这样吗,何须呢,就跟我刚开始看到c语言里do{ ... }while(0) 同样。若是你还不明白为何这样作,那么就搜一下do while(0)了解一下背景。

 利用if(1),if(0)进行语法修正后的宏以下所示 d3

`define div(x) 	if(1) \
	begin signal=0; \
	answer=x/3; \
	signal=1; \
	end  \
	else if(0)
 这样,咱们使用代码就变成为

always @(posedge clk)
begin
	case(counter)
	32'd1: `div(1);
	32'd2: `div(2);
	32'd3: `div(3);
	...
	32'd16: `div(16);
	endcase
end
这样就符合通常性语法了。有趣的是,当我用iverilog -E查看其宏展开的时候发现居然在展开的时候就把if(1),if(0)给去掉了,因此咱们修正后的宏没有给电路形成一丝影响,仅仅是方便了咱们人类的书写习惯,以及阅读习惯。