[例]:
例5.1
case (select[1:2])
2'b00: result = 0;
2'b01: result = flaga;
2'b0x,
2'b0z: result = flaga? 'bx : 0;
2'b10: result = flagb;
2'bx0,
2'bz0: result = flagb? 'bx : 0;
default: result = 'bx;
endcase
例5.2
case(sig)
1'bz: $display("signal is floating");
1'bx: $display("signal is unknown");
default: $display("signal is %b",sig);
endcase
例5.3
reg [7:0] ir;
casez(ir)
8'b1???????: instruction1(ir);
8'b01??????: instruction2(ir);
8'b00010???: instruction3(ir);
8'b000001??: instruction4(ir);
endcase
例5.4
reg [7:0] r,mask;
mask = 8'bx0x0x0x0;
casex(r'mask)
8'b001100xx: stat1;
8'b1100xx00: stat2;
8'b00xx0011: stat3;
8'bxx001100: stat4;
endcase
通过以上三个例子比较case , casex , casez的区别。casez将高阻值z的情况视为不必关心的情况。casex将高阻值z和不定值x视为不必关心的情况。所谓不必关心的情况,即在表达式进行比较时,不将该位的状态考虑在内。
例5.5
//第一类条件语句,没有else。
//其后的语句执行或不执行
if (!lock) buffer = data;
if (enable) out = in;
//第二类条件语句,有一个else。
//根据表达式的值,决定执行ture或false。
if (number_queued < MAX_Q_DEPTH)
begin
data_queue = data;
number_queued = number_queued + 1;
end
else
$display("Queue Full. Try again.");
//第三类条件语句,嵌套的if_else_if
//根据不同的算术逻辑单元控制信号,只有一条执行。
if (alu_control == 0)
y = x + z ;
else if (alu_control == 1)
y = x - z ;
else if (alu_control == 2)
y = x * z ;
else
$display("Invalid ALU control signal.");
通过上面的例子熟悉Verilog三种条件语句。
例5.6
使用case语句实现四选一多路选择器。
module mux4_to_1 (out,i0,i1,i2,i3,s1,s0);
//声明输入输出端口
output out;
input i0,i1,i2,i3,s1,s2;
//定义寄存器变量用于always块。
reg out;
always @(s1 or s0 or i0 or i1 or i2 or i3)
begin
case ({s1,s0})
2'b00: out = i0;
2'b01: out = i1;
2'b10: out = i2;
2'b11: out = i3;
endcase
end
endmodule
通过上面的例子熟悉多路分支case的使用。
例5.8
parameter size = 8,longsize = 16;
reg [size:1] opa , opb;
reg [longsize:1] result;
begin:mult
integer bindex;;
result = 0;
for (bindex = 1; bindex <= size; bindex = bindex + 1)
if(opb[bindex])
result = result + (opa << (bindex - 1));
end
//for语句循环变量增值表达式可以不必是一般的常规加减法,如:
begin: countls
reg [7:0] tempreg;
count = 0;
for(tempreg = rega; tempreg; tempreg = tempreg >> 1)
if (tempreg[0])
count = count + 1;
end
通过以上例子熟悉循环语句的用法。
例5.9
顺序块:
reg x,y;
reg [1:0] z,w;
initial
begin
x = 1'b0;
#5 y = 1'b1;
#10 z = {x,y};
#20 w = {y,x};
end
例5.10
并行块:
reg x,y;
reg [1:0] z,w;
initial
fork
x = 1'b0;
#5 y = 1'b1;
#10 z = {x,y};
#20 w = {y,x};
join
通过以上两个例子区别顺序块和并行块的区别。
例5.11
嵌套块:
initial
begin
x = 1'b0;
fork
#5 y = 1'b1;
#10 z = {x,y};
join
#20 w = {y,x};
end
顺序块,并行块可以互相随意嵌套。
例5.12
命名块:
module top;
initial
begin: block1
integer i;
...
...
end
initial
fork: block2
reg i;
...
...
join
例5.13
命名块的禁用。
//在(矢量)标志寄存器的各个位中从低有效位开始找寻第一个值为1的位。
reg [15:0] flag;
integer i;
initial
begin
flag = 16'b0010_0000_0000_0000;
i = 0;
begin: block1
while (i < 16)
begin
if (flag[i])
begin
$display("Encountered a TRUE bit at element number %d",i);
disable block1;
end
i = i + 1;
end
end
end
通过以上例子熟悉利用$disable禁用已经命名的块。
例5.14 循环生成语句
对两个N位总线变量进行按位异或。
//本模块生成两条N位总线变量的按位异或
module bitwise_xor (out , i0 , i1) ;
//参数声明语句,参数可以重新定义
parameter N = 32 ;
//默认的总线位宽为32位。
//端口声明语句
output [N-1:0] out ;
input [N-1:0] i0 , i1 ;
//声明一个临时循环变量
genvar j ;
//用一个单循环生成按位异或的异或门xor
generate
for (j = 0; j < N; j = j + 1)
begin : xor_loop
xor g1 (out[j] , i0[j] , i1[j]);
end
endgenerate
endmodule
//另一种编写方式,用always块代替异或门xor。
reg [N-1:0] out;
generate
for (j = 0 ; j < N ; j = j + 1)
begin : bit
always @ (i0[j] or i1[j])
out[j] = i0[j] ^ i0[j] ;
end
endgenerate
用上述例子学习循环生成语句的写法。
例5.16 使用条件生成语句实现参数化乘法器。
//本模块实现一个参数化乘法器
module multiplier (product , a0 , a1) ;
//参数声明,该参数可以被重新定义。
parameter a0_width = 8 ;
parameter a1_width = 8 ;
//本地参数声明。本地参数不能用参数重新定义修改。
localparam product_width = a0_width + a1_width ;
//端口声明语句
output [product_width - 1:0] product ;
input [a0_width - 1:0] a0 ;
input [a1_width - 1:0] a1 ;
//有条件的调用不同类型的乘法器
//根据参数a0_width和a1_width的值,在调用时引用相对应的乘法器实例。
generate
if (a0_width < 8)||(a1_width < 8)
cal_multiplier # (a0_width , a1_width) m0 (product , a0 , a1) ;
else
tree_multiplier # (a0_width , a1_width) m0 (product , a0 , a1) ;
endgenerate
endmodule
用上面的例子熟悉条件生成语句。
例5.17 case生成语句
//本模块生成N位的加法器
module adder (co , sum , a0 , a1 , ci);
//参数声明
parameter N = 4;
//默认总线位宽为4。
//端口声明
output [N - 1:0] sum ;
output co ;
input [N - 1:0] a0 , a1 ;
input ci ;
//根据总线的位宽,调用相应的加法器。
generate
case(N)
1 : adder_1bit adder1 (co , sum , a0 , a1 , ci) ;
//1位的加法器
2 : adder_2bit adder2 (co , sum , a0 , a1 , ci) ;
//2位的加法器
default : adder_cla #(N) adder3(co , sum , a0 , a1 , ci) ;
endcase
endgenerate
endmodule
用上面的例子熟悉case生成语句。