HDLBits第五章练习及答案

1、三元条件运算符

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 )

练习:

给定四个无符号数,找出最小值。无符号数可以与标准比较运算符 (a < b) 进行比较。使用条件运算符创建两路最小电路,然后组合其中的一些来创建 4 路最小电路。您可能需要一些用于中间结果的向量。

代码实现:

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

    wire [7:0]min1,min2;
    assign min1 = (a > b)? b : a;
    assign min2 = (c > d)? d : c;
    assign min = (min1 > min2)? min2 : min1;

endmodule

验证结果:
在这里插入图片描述

2、归约运算符

你已经熟悉两个值之间的按位运算,例如a & b或a ^ b。有时,你想创建一个宽门,操作一个向量的所有位,如(a[0] & a[1] & a[2] & a[3]…),如果向量很长,就会变得很乏味。
归约运算符可以对向量的位进行“与”、“或”和“异或”运算,产生一位输出。

& 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])。

练习:

奇偶校验经常被用作通过不完善的信道传输数据时检测错误的一种简单方法。创建一个电路,该电路将计算一个8位字节的奇偶校验位(将增加第9位字节)。我们将使用“偶数”奇偶校验,其中奇偶校验位就是所有8个数据位的异或。

代码实现:

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

验证结果:
在这里插入图片描述

3、归约:更宽的门

在[99:0]中建立一个有100个输入的组合电路。

有3个输出:
①out_and: 100输入与门的输出。
②out_or: 100输入OR门的输出。
③out_xor: 100输入异或门的输出。

代码实现:

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

验证结果:
在这里插入图片描述在这里插入图片描述

4、组合for循环:向量反转2

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

代码实现:

module top_module( 
    input [99:0] in,
    output [99:0] out
);

    integer i;
    always@(*) begin
        for( i = 0 ;i <= 99;i = i + 1 ) begin
            out[i] = in[99-i];
    	end
    end
    
endmodule

验证结果:
在这里插入图片描述

5、组合for循环:255位总体计数

“总体计数”电路计算输入向量中“1”的个数。为255位输入向量构建总体计数电路。

代码实现:

module top_module( 
    input [254:0] in,
    output [7:0] out );
	
    integer i;
    always@(*) begin
        out = 8'b0;
        for(i = 0;i <= 254;i = i + 1) begin
            out = out + in[i];
        end
    end
    
endmodule

验证结果:
在这里插入图片描述

6、生成for循环:100位二进制加法器2

通过实例化 100 个全加器来创建一个 100 位二进制行波进位加法器。加法器将两个 100 位数字和一个进位相加,以产生 100 位总和并进位。为了鼓励您实际实例化全加器,还要输出行波进位加法器中每个全加器的进位。cout[99] 是最后一个全加器的最后一个进位,也是你经常看到的进位。

拓展:

generate语法

(1)定义genvar,作为generate种的循环变量。
(2)generate语句中定义的for语句,必须要有begin,为后续增加标签做准备。
begin必须要有名称,也就是必须要有标签,因为标签会作为generate循环的实例名称。
(3)可以使用在generate语句中的类型主要有:
① module(模块)
②UDP(用户自定义原语)
③ 门级原语
④ 连续赋值语句
⑤ initial或always语句

generate基本结构如下:

genvar 循环变量名;
generate

    // generate循环语句
    // generate 条件语句
    // generate 分支语句
    // 嵌套的generate语句

endgenerate

代码实现:

module top_module( 
    input [99:0] a, b,
    input cin,
    output [99:0] cout,
    output [99:0] sum );
	
    genvar i;
	generate
        for( i = 0 ; i < 100; i = i + 1 )
            begin:adder
                if(i==0)
                   	begin
                        assign {cout[i],sum[i]} = a[i] + b[i] + cin;
                	end
                else
                    begin
                        assign {cout[i],sum[i]} = a[i] + b[i] + cout[i-1];
                    end  
            end
	endgenerate
    
endmodule

验证结果:
在这里插入图片描述

7、生成for循环:100位BCD加法器

为您提供了一个名为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行波进位加法器。您的加法器应该将两个100位BCD数字(打包成400位向量)和一个进位相加,以产生一个100位的和并进行运算。

代码实现:

module top_module( 
    input [399:0] a, b,
    input cin,
    output cout,
    output [399:0] sum );

    wire [99:0]cout1;
    genvar i;
	generate
        for( i = 0 ; i < 100; i = i + 1 )
            begin:adder
                if(i==0)
                    bcd_fadd U0( .a(a[3:0]), .b(b[3:0]), .cin(cin), .cout(cout1[0]), .sum(sum[3:0]));
                else
                    bcd_fadd U1( .a(a[4*i+3:4*i]), .b(b[4*i+3:4*i]), .cin(cout1[i-1]), .cout(cout1[i]), .sum(sum[4*i+3:4*i]));
            end
    assign cout = cout1[99];
	endgenerate
    
endmodule

验证结果:
在这里插入图片描述

  • 5
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值