HDLBits学习------Problem 10~18

参考连接:HDLBits导学


Problem 10 : Vectors

        概述:什么是 Verilog 中的向量(vector)?向量是一组 wire 信号的集合,通过赋予这一组信号的集合一个名称,以便于访问其中的 wire 信号。

向量类似于总线,一般将向量视为位宽超过 1 位的 wire 信号,不是特别在意向量这个概念本身。

        问题:构造一个电路,拥有 1 个 3 bit 位宽的输入端口,4 个输出端口。其中一个输出端口直接输出输入的向量,剩下 3 个输出端口分别各自输出 3 bit 中的 1 bit

         解决:

module top_module ( 
    input wire [2:0] vec,
    output wire [2:0] outv,
    output wire o2,
    output wire o1,
    output wire o0  ); // Module body starts after module declaration
    
    assign outv = vec;
	assign o2 = vec[2];
	assign o1 = vec[1];
	assign o0 = vec[0];

endmodule

Problem 11 : Vector in more detail

        问题:创建一个模块输出16位输入信号的高8位和低8位

        解决:

`default_nettype none     // Disable implicit nets. Reduces some types of bugs.
module top_module( 
    input wire [15:0] in,
    output wire [7:0] out_hi,
    output wire [7:0] out_lo );
    
    assign out_hi = in[15:8];
    assign out_lo = in[7:0];

endmodule

        注意:向量的比特顺序(endianness)信息,比特顺序取决于向量的 LSB 是向量的高位还是地位。比如声明为 [3:0] w 的向量,LSB 是 w[0],如果声明为 [0:3] w,那么 w[3] 是 LSB 。LSB 指的是二进制数中权值最低的一位。

       隐式声明的问题,隐式声明的例子

wire [2:0] a, c;    // Two vectors 
assign a = 3'b101;  // a = 101 
assign b = a;       // b =   1  隐式声明并定于了 b
wire assign c = b;  // c = 001  <-- bug 来了 b 被 coder 默认为和 a 相同的 3'b101,但其实 b 只有 1bit宽
my_module i1 (d,e); // d e 都被隐式声明为 1bit wire
                    //如果模块期望的是 vector 那么 BUG 就产生了

        通过添加 `default_nettype none 宏定义会关闭隐式声明功能,那么这样一来,使用未声明的变量就会变成一个 Error 而不再只是 Warning。

        声明向量数组

reg [7:0] mem [255:0];   // 256 unpacked elements, each of which is a 8-bit packed vector of reg.
reg mem2 [28:0];         // 29 unpacked elements, each of which is a 1-bit reg.

        赋值截断补零操作

        在 assign 赋值操作中,如果等号左右两侧信号的位宽不同,那么就会进行截断或者补零操作。

        左侧信号位宽大于右侧信号位宽,右值的低位赋予左值对应的低位,左值高位的部分赋零

        左侧信号位宽小于右侧信号位宽,右值的低位赋予左值对应的低位,右值高位的部分直接被截断。即保留右值的低位。

        片选例子

w[3:0]      // Only the lower 4 bits of w
x[1]        // The lowest bit of x
x[1:1]      // ...also the lowest bit of x
z[-1:-2]    // Z 最低两位
b[3:0]      // 如果 b 在声明时 声明为 wire [0:3] b;则不能使用 b [3:0]进行选择
b[0:3]      // b的高四位.
assign w[3:0] = b[0:3];    // 将 b 的高位赋予 w 的低位 w[3]=b[0], w[2]=b[1], etc.
//经测试不能这样做

Problem 12 : Vector part select

        问题:一个 32 位的向量可以看做由 4 个字节组成(bits[31:24],[23:16],等等)。构建一个电路,将输入向量的字节顺序颠倒,也就是字节序大小端转换。

AaaaaaaaBbbbbbbbCcccccccDddddddd => DdddddddCcccccccBbbbbbbbAaaaaaaa

        解决:

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

    // assign out[31:24] = ...;
    assign out[31:24] = in[7:0];
    assign out[23:16] = in[15:8];
    assign out[15:8] = in[23:16];
    assign out[7:0] = in[31:24];

endmodule

        注意:不能把方向搞反了 会报错的

b[3:0]      // 如果 b 在声明时 声明为 wire [0:3] b;则不能使用 b [3:0]进行选择

Problem 13 : Bitwise operators

        问题:模块有两个 3bit 宽的输入变量 a,b ,要求输出 a,b 逐位或的,a,b 逻辑或以及 a,b 按位取反的结果,其中 b 在高位

         解决:

module top_module( 
    input [2:0] a,
    input [2:0] b,
    output [2:0] out_or_bitwise,
    output out_or_logical,
    output [5:0] out_not
);

    assign out_or_bitwise = a | b;
	assign out_or_logical = a || b;
	assign out_not[2:0] = ~a;
	assign out_not[5:3] = ~b;
    
endmodule

Problem 14 : Four-input gates

        问题:构建一个4输入的与门、或门和异或门

        解决:

module top_module( 
    input [3:0] in,
    output out_and,
    output out_or,
    output out_xor
);
	
    //第一种解决方法
	assign out_and = in[0] & in[1] & in[2] & in[3];
	assign out_or = in[0] | in[1] | in[2] | in[3];
	assign out_xor = in[0] ^ in[1] ^ in[2] ^ in[3];

    //第二种解决方法
    assign out_and = & in;
    assign out_or  = | in;
    assign out_xor = ^ in;
	
endmodule

Problem 15 : Vector concatenation operator

        问题:给定几个输入向量,将它们连接在一起,然后将它们分成几个输出向量。

        思路:可以看出a,b,c,d,e,f 都是5位的,然后使用拼接操作

        解决:

module top_module (
    input [4:0] a, b, c, d, e, f,
    output [7:0] w, x, y, z );//

    // assign { ... } = { ... };
    assign z = {e[0],f,2'b11};
	assign y = {d[3:0],e[4:1]};
    assign x = {b[1:0],c,d[4]};
	assign w = {a,b[4:2]};

endmodule

        注意:拼接操作符

{3'b111, 3'b000} => 6'b111000
{1'b1, 1'b0, 3'b101} => 5'b10101
{4'ha, 4'd10} => 8'b10101010     // 4'ha and 4'd10 are both 4'b1010 in binary

        连接操作符的基本语法使用 { } 将较小的向量括起来,每个 { } 内的向量使用逗号作为间隔。

        连接运算符中的向量务必需要标注位宽,不然综合器怎么能知道你的结果需要多宽的位宽。因此 { 1,2,3 } 这样的操作是非法的,并会产生一个 Error:unsized constants are not allowed in concatenations.

        拼接用在左侧和右侧都可以

input [15:0] in;
output [23:0] out;
assign {out[7:0], out[15:8]} = in;         // Swap two bytes. Right side and left side are both 16-bit vectors.
assign out[15:0] = {in[7:0], in[15:8]};    // This is the same thing.
assign out = {in[7:0], in[15:8]};       // This is different. The 16-bit vector on the right is extended to
                                        // match the 24-bit vector on the left, so out[23:16] are zero.
                                        // In the first two examples, out[23:16] are not assigned.

Problem 16 : Vector reversal 1

        问题:给定一个 8bit 输入向量,将其反向输出

        思路:拼接的办法 把地位依次放在高位进行拼接

        解决:

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

    //第一种方式 位数大了就很难写了	
    assign out = {in[0],in[1],in[2],in[3],in[4],in[5],in[6],in[7]};

    //第二种方式 for循环
    integer i;
    always @(*) begin	
     for (i=0; i<8; i++)	//Use integer for pure Verilog.
	     out[i] = in[8-i-1];
    end
    
endmodule

Problem 17 : Replication operator

       概述:连接操作符允许我们将短小的向量连接在一起构成更宽的向量。很方便,但有的时候需要将多个重复的向量连接在一起,诸如 assign a = {b,b,b,b,b,b}; 这样的语句写多了是非常让人忧愁的。而重复操作符语法就可以在这种情况下帮到你,允许你将一个向量重复多次,并将它们连接在一起,语法是这样:{ 重复次数 { 向量 } }。

例子:

{5{1'b1}}           // 5'b11111 (or 5'd31 or 5'h1f)
{2{a,b,c}}          // The same as {a,b,c,a,b,c}
{3'd5, {2{3'd6}}}   // 9'b101_110_110. It's a concatenation of 101 with
                    // the second vector, which is two copies of 3'b110.

        问题:重复操作符的应用场景之一是在有符号数的扩展。有符号数的扩展是将符号位填充待扩展的比特。比如要将 4bit 的 4'b0101 有符号数扩展为 8bit ,0 是符号位,那么扩展之后为 8'b0000 0101.

现在要求你构建一个电路,将一个 8bit 有符号数扩展为 32bit 数。

        思路:输入高位为1的时候则为负数,此时需要将输出高位置1,反之则需要将输出高位置0(虽然说不置也是0)。开始想用if else,还写错了。然后参考了大佬写的,真不错~~~

        解决:

module top_module (
    input [7:0] in,
    output [31:0] out );//

    // assign out = { replicate-sign-bit , the-input };
    assign out = {{24{in[7]}},in};
    
endmodule

        注意:重复次数必须是一个常量,而且请特别注意重复操作符有两对 { }.外层的 {} 不能少。


Problem 18 : More Replication

        问题:将 5 个 1bit 信号分别组成下图中两个 25 bit 信号,输出向量为这两个 25bit 向量的逐位操作的结果。如果两个待比较信号某比特相同,则结果向量对应的该比特位 1 。

        out[24] = ~a ^ a; // a == a, so out[24] is always 1.
        out[23] = ~a ^ b;
        out[22] = ~a ^ c;
        ...
        out[ 1] = ~e ^ d;
        out[ 0] = ~e ^ e

        解决:

module top_module (
    input a, b, c, d, e,
    output [24:0] out );//

    // The output is XNOR of two vectors created by 
    // concatenating and replicating the five inputs.
    // assign out = ~{ ... } ^ { ... };
    
    wire [24:0] x1 = {{5{a}},{5{b}},{5{c}},{5{d}},{5{e}}};
	wire [24:0] x2 = {5{a,b,c,d,e}};
	assign out = ~ (x1 ^ x2);

endmodule

        注意:

//有多个的时候每一个都需要用两个{}括起来,数字不能漏在外面
wire [24:0] x1 = {{5{a}},{5{b}},{5{c}},{5{d}},{5{e}}};

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值