[Verilog17]HDLBits习题_More Verilog Features

HDLBits习题讲解_More Verilog Features

条件运算符

  • verilog中有跟c语言类似的三目运算符,这可以用于在一行中根据条件选择两个值中的一个,而不用在组合always块中使用if-else。
信号 = 条件?表达式1:表达式2;  //即当条件成立时,信号取表达式1的值,反之取表达式2的值。

Conditional ternary operator

  • 题目要求,给定4个无符号数,求最小值。无符号数可以用比较运算符(a < b)进行比较。代码如下:
module top_module (
    input [7:0] a, b, c, d,
    output [7:0] min);

    wire [7:0] mintemp1,mintemp2;
    assign mintemp1 = (a<b)? a:b;
    assign mintemp2 = (c<mintemp1)?c:mintemp1;
    assign min = (d<mintemp2)?d:mintemp2;
    
endmodule

缩减运算符

  • 缩位运算符可以对向量的各个位进行和、或和异或操作,产生1位的输出。例如:
b = &a; // 等效于b = ((a[0] & a[1]) & a[2]) & a[3];
/////////////////////////////////////////////////////////
A = 5'b11001;
&A;  //值等于0, 只有A的各位都为1时,其与缩减运算的值才为1
|A; //值等于1, 只有A的各位都为0时,其或缩减运算的值才为0

Reduction operators

  • 奇偶校验经常被用作传输数据时检测错误的简单方法。题目要求,创建一个电路,为一个8位字节计算一个奇偶校验位(它将在1个字节的基础上增加1位)。我们将使用偶校验,其中偶校验位是8个数据位的异或(XOR)。代码如下:
module top_module (
    input [7:0] in,
    output parity); 
	assign parity = ^ in;
endmodule

Reduction: Even wider gates

  • 题目要求,构建一个组合电路,包括一个100位输入,in[99:0];三个输出:
  1. out_and:输出100个输入和门。
  2. out_or:输出100个输入或门。
  3. out_xor:输出100个输入XOR门。
  • 代码如下:
module top_module( 
    input [99:0] in,
    output out_and,
    output out_or,
    output out_xor 
);
	assign out_and = &in;
    assign out_or = |in;
    assign out_xor = ^in;
endmodule

循环语句

  1. for语句
for(循环变量赋初值;循环结束条件; 循环变量增值) 执行语句;
  • 先给控制循环次数的变量赋初值。再判定控制循环的表达式的值, 如为假则跳出循环语句,如为真则执行指定的语句后,执行一条赋值语句来修正控制循环变量次数的变量的值,然后再次判断。
  1. repeat语句
repeat(循环次数表达式) 语句;
// or
repeat(循环次数表达式)begin……end;
  • 连续执行一条语句或者一个语句块 n 次。
  1. while语句
while(循环执行条件表达式) 语句;
// or
while(循环执行条件表达式) begin……end;
  • 执行一条语句直到某个条件不满足。如果一开始条件即不满足(为假),则语句一次也不能被执行。
  1. forever语句
forever 语句;
// or
forever begin……end;
  • forever循环语句连续不断地执行后面的语句或语句块,常用来产生周期性的波形,作为仿真激励信号。它与always语句的不同之处在于它一般用在initial语句块中。若要用它进行模块描述,可用disable语句进行中断。

Combinational for-loop: Vector reversal 2

  • 题目要求,给定一个100位的输入向量[99:0],将其逐位倒置。代码如下:
module top_module( 
    input [99:0] in,
    output [99:0] out
);
	reg [99:0] out_r;
    integer i;
    always @(*) begin
        for(i=0;i<100;i++) begin
            out_r[i]=in[99-i];
        end
    end
    assign out=out_r;
endmodule

Combinational for-loop: 255-bit population count

  • 题目要求,对一个255为的输入向量设计一个计数器电路,计数向量中1的个数。代码如下:
module top_module( 
    input [254:0] in,
    output [7:0] out );
    integer i;
    reg [7:0] out_r;
    always @(*) begin
        out_r = 8'd0;
        for(i=0;i<255;i++) begin
            out_r = out_r + in[i];
        end
    end
    assign out=out_r;
endmodule
  • __tips:__需要注意,在此处代码中,会产生锁存器电路,在实际应用中应酌情使用。如不希望产生锁存器则需要通过遍历所有种可能(2^255),在代码书写上具有较大的代码量。

生成语句

  • 循环生成的主要目的是简化我们的代码书写,利用循环生成语句我们可以将之前需要写很多条比较相似的语句才能实现的功能用很简短的循环生成语句来代替。
  1. 循环生成语句
  • 基本语法如下:
///////generate-for语句///////
generate
    genvar <var1>;
    for (<var1> = 0 ; <var1> < num ; <var1>=<var1>+1)   
    begin: <label_1>
        <code>;
    end
endgenerate
  1. 条件生成语句
  • 基本语法如下:
///////generate-if语句///////
generate
	if (<condition>) begin: <label_1>
		<code>;
	end 
    else if (<condition>) begin: <label_2>
		<code>;
	end 
    else begin: <label_3>
		<code>;
	end
endgenerate

///////generate-case语句///////
generate
    case (<constant_expression>)
        <value>: begin: <label_1>
            <code>
        end
        <value>: begin: <label_2>
            <code>
        end
		……
        default: begin: <label_N>
            <code>
        end
    endcase
endgenerate

Generate for-loop: 100-bit binary adder 2

  • 题目要求,通过实例化100个全加器,创建一个100位的进位加法器。代码如下:
module top_module( 
    input [99:0] a, b,
    input cin,
    output [99:0] cout,
    output [99:0] sum );
    
    assign{cout[0],sum[0]}=a[0]+b[0]+cin;//最低位需要进位,单独书写
    generate
        genvar i; //定义循环变量i
        for(i=1;i<100;i++)
        begin:adder //给循环生成模块命名
            assign{cout[i],sum[i]}=a[i]+b[i]+cout[i-1];//高位均采用循环生成语句
        end
    endgenerate
endmodule

Generate for-loop: 100-digit BCD adder

  • 题目提供了一个名为bcd_fadd的BCD一位加法器,它的输入为两个BCD数字和进位输入信号,并生成求和输出和进位输出信号。
module bcd_fadd {
    input [3:0] a,
    input [3:0] b,
    input     cin,
    output   cout,
    output [3:0] sum );
  • 要求实例化100个bcd_fadd模块,以创建一个100位的BCD进位加法器。代码如下:
module top_module( 
    input [399:0] a, b,
    input cin,
    output cout,
    output [399:0] sum );
    
    wire cout_temp[99:0];
    bcd_fadd u_bcd_fadd_0(
        .a(a[3:0]),
        .b(b[3:0]),
        .cin(cin),
        .cout(cout_temp[0]),
        .sum(sum[3:0])
    );
    generate 
        genvar i;
        for(i=1;i<100;i=i+1)
        begin:u_bcd_fadd
            bcd_fadd u_bcd_fadd(
                .a(a[4*i+3 : 4*i]),
                .b(b[4*i+3 : 4*i]),
                .cin(cout_temp[i-1]),
                .cout(cout_temp[i]),
                .sum(sum[4*i+3 : 4*i])
            );
        end
    endgenerate
    assign cout = cout_temp[99];
endmodule

参考:
HDLBits
HDLBits答案(5)_Generate实例化模块