HDLBits-Verilog学习小结(六)More Verilog Features

1 Conditional

Verilog具有三元条件运算符(?:)就像C语言里面:

condition ? if_true : if_false

可以用于根据一行上的条件(多路复用器)选择两个值之一,而无需在组合的always块中使用if-then。
比如说:

(0 ? 3 : 5)     // This is 5 because the condition is false.
(sel ? b : a)   // A 2-to-1 multiplexer between a and b selected by sel.
always @(posedge clk)         // A T-flip-flop.
  q <= toggle ? ~q : q;

always @(*)                   // State transition logic for a one-input FSM
  case (state)
    A: next = w ? B : A;
    B: next = w ? A : B;
  endcase

assign out = ena ? q : 1'bz;  // A tri-state buffer

((sel[1:0] == 2'h0) ? a :     // A 3-to-1 mux
 (sel[1:0] == 2'h1) ? b :
                      c )

question:
给定四个无符号数字,找到最小值。可以将无符号数字与标准比较运算符(a <b)进行比较。使用条件运算符创建双向最小回路,然后组合其中的一些以创建四向最小回路。您可能需要一些线向量作为中间结果。

module top_module (
    input [7:0] a, b, c, d,
    output [7:0] min);//

    // assign intermediate_result1 = compare? true: false;
    wire [7:0] k1,k2;
    assign k1=(a<b)?a:b;
    assign k2=(c<d)?c:d;
    assign min=(k1<k2)?k1:k2;
    
endmodule

2 Reduction operators

2.1 Reduction operators

您已经熟悉两个值之间的按位运算,例如a&b或a ^ b。有时,您想创建一个对一个向量的所有位进行操作的宽门,例如(a [0]&a [1]&a [2]&a [3] …),如果向量很长。

约简运算符可以对向量的位进行AND,OR和XOR,产生一位输出:

& a[3:0]     // AND: a[3]&a[2]&a[1]&a[0]. Equivalent to (a[3:0] == 4'hf)
| b[3:0]     // OR:  b[3]|b[2]|b[1]|b[0]. Equivalent to (b[3:0] != 4'h0)
^ c[2:0]     // XOR: c[2]^c[1]^c[0]

这些是只有一个操作数的一元运算符(类似于NOT运算符!和〜)。您还可以反转这些输出以创建NAND,NOR和XNOR门,例如(〜&d [7:0])。

question:
通过不完善的通道传输数据时,奇偶校验通常用作检测错误的简单方法。创建一个电路,该电路将计算8位字节的奇偶校验位(这将在字节中添加第9位)。我们将使用“偶数”奇偶校验,其中奇偶校验位只是所有8个数据位的XOR。

solution:

module top_module (
    input [7:0] in,
    output parity); 
    
    assign parity = ^in[7:0];

endmodule

2.2 Reduction: Even wider gates

question:
用[99:0]构建一个具有100个输入的组合电路。
有3个输出:

  • out_and:100输入与门的输出。
  • out_or:100输入或门的输出。
  • out_xor:100输入XOR门的输出。

solution:

module top_module( 
    input [99:0] in,
    output out_and,
    output out_or,
    output out_xor 
);
    assign out_and = &in[99:0];
    assign out_or = |in[99:0];
    assign out_xor = ^in[99:0];

endmodule

3 Combinational for-loop

3.1 Vector reversal 2

question:
给定100位输入向量[99:0],请反转其位顺序。

for循环(在组合的always块或generate块中)在这里很有用。在这种情况下,这里可以使用always block,因为不需要模块实例化(需要生成块)。

solution:

module top_module( 
    input [99:0] in,
    output [99:0] out
);
    always @(*) begin
        for (int i=0;i<=99;i++)
            begin
                out[i] = in[99-i];
            end
    end

endmodule

anoter solution:

module top_module (
	input [99:0] in,
	output reg [99:0] out
);
	
	always @(*) begin
		for (int i=0;i<$bits(out);i++)		// $bits() is a system function that returns the width of a signal.
			out[i] = in[$bits(out)-i-1];	// $bits(out) is 100 because out is 100 bits wide.
	end
	
endmodule

3.2 255-bit population count

question:
“人口计数”电路对输入向量中的“ 1”进行计数。建立一个255位输入向量的填充计数电路。

solution:

module top_module( 
    input [254:0] in,
    output [7:0] out );
    always @(*) begin
        out = 8'b0000_0000; // noted:initial out
        for (int i=0;i<=254;i++)
            begin
                if (in[i] == 1'b1)
                    out=out+8'b1;
            end
    end
        
endmodule

another solution:

module top_module (
	input [254:0] in,
	output reg [7:0] out
);

	always @(*) begin	// Combinational always block
		out = 0;
		for (int i=0;i<255;i++)
			out = out + in[i];
	end
	
endmodule

4 Generate for-loop

4.1 100-bit binary adder 2

question:
通过实例化100个完整的加法器来创建一个100位的二进制纹波进位加法器。

加法器将两个100位数字和一个进位相加,以产生100位和。为了鼓励您实际实例化完全加法器,还请在脉动进位加法器中输出每个完全加法器的进位。

提示:有许多要实例化的完整加法器。实例数组或generate语句将在这里有所帮助。cout [99]是最后一个完整加法器的最终进位,并且是通常看到的进位。(注意:这里要一位一位进行运算)

solution:

module top_module( 
    input [99:0] a, b,
    input cin,
    output [99:0] cout,
    output [99:0] sum );
    
    assign cout[0] = a[0]&b[0] | a[0]&cin | b[0]&cin;
    assign sum[0] = a[0]^b[0]^cin;
    
    always @(*) begin
        for (int i=1;i<=99;i++)
            begin
                cout[i] = a[i]&b[i] | a[i]&cout[i-1] | b[i]&cout[i-1];
                sum[i] =  a[i]^b[i]^cout[i-1];
            end
    end
        
endmodule

4.2 100-digit BCD adder

question:
为您提供了一个名为bcd_fadd的BCD一位数字加法器,该加法器将两个BCD数字和进位相加,并产生总和和进位。bcd_fadd模块如下:
module bcd_fadd {
input [3:0] a,
input [3:0] b,
input cin,
output cout,
output [3:0] sum );

现在试着实例化100个bcd_fadd副本以创建一个100位的BCD纹波进位加法器。您的加法器应将两个100位的BCD编号(打包为400位向量)相加,并随身携带一个100位的总和并执行。

这道题与上一题类似,都需要先利用cin来初始化,但是不同的地方有两点:

  • 一个是cout这里没有指定长度,不妨假设一个temp当做中间变量来充当cout的中间值,整个过程我们将进行100次(0、4、8、…、396这99个数字);
  • 另一个是这里是使用模块进行实例化,那么就涉及到generate这个函数的问题,参考这里,我们知道:在本题中我们采用generate语句。

什么是generate语句?

​生成语句可以动态的生成verilog代码,当对矢量中的多个位进行重复操作时,或者当进行多个模块的实例引用的重复操作时,或者根据参数的定义来确定程序中是否应该包含某段Verilog代码的时候,使用生成语句能大大简化程序的编写过程。

​使用关键字generate 与 endgenerate来指定范围。generate语句有generate-for、generate-if、generate-case三种语句,本题中我们使用generate-for语句。generate-for语句:
(1) 必须有genvar关键字定义for语句的变量。
(2)for语句的内容必须加begin和end(即使就一句)。
(3)for语句必须有个名字。

solution:

module top_module( 
    input [399:0] a, b,
    input cin,
    output cout,
    output [399:0] sum );
    
    wire [99:0] temp;
    bcd_fadd bcd_1 (a[3:0],b[3:0],cin,temp[0],sum[3:0]);
    assign cout = temp[99];
    
    generate
        genvar i;
        for (i=4;i<=399;i=i+4)
            begin : bcdadd
                bcd_fadd bcd_2 (a[i+3:i],b[i+3:i],temp[(i-4)/4],temp[i/4],sum[i+3:i]);
            end
    endgenerate

endmodule
  • 4
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值