Vectors

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

Vectors in more detail

Vectors must be declared:
type [ upper : lower ] vector_name;

There are some declaring vectors examples:

wire [7:0] w;         // 8-bit wire
reg  [4:1] x;         // 4-bit reg
output reg [0:0] y;   // 1-bit reg that is also an output port (this is still a vector)
input wire [3:-2] z;  // 6-bit wire input (negative ranges are allowed)
output [3:0] a;       // 4-bit output wire. Type is 'wire' unless specified otherwise.
wire [0:7] b;         // 8-bit wire where b[0] is the most-significant bit.(0 是最高位)

3'b101的含义

assign a = 3'b101; // a = 101  
  • 3':指定数值的位宽为 3 位。
  • b:表示后续数值为二进制(binary)格式。
  • 101:二进制数值本身,对应十进制的 5。

Implicit nets

wire [2:0] a, c; // Two vectors   
assign a = 3'b101; // a = 101   
assign b = a; // b = 1 implicitly-created wire  
assign c = b; // c = 001 

赋值过程

  • assign a = 3'b101; → a 的值为 101(十进制 5)。
  • assign b = a; → 隐式创建了 1 位 wire b,并将a的最低位(a[0])赋给b
    (Verilog 中,未声明的标识符会被隐式创建为 1 位 wire,且高位自动截断。)
  • assign c = b; → 将 1 位的b(值为1)扩展为 3 位赋值给c
    由于b只有 1 位,高位补零c的值变为 001(十进制 1)。

`default_nettype none 指令

功能:

  • 禁止隐式网络生成:在 Verilog 中,如果使用了未经声明的标识符,系统会默认将其创建为 1 位宽的 wire 类型。而default_nettype none指令会阻止这种隐式创建,一旦遇到未声明的标识符,编译器就会报错。
  • 提高代码可靠性:通过这种方式,可以有效避免因拼写错误或者变量未声明而引发的难以察觉的问题。

使用方法:

`default_nettype none // 后续代码   

module my_module(input a, input b, output c);   
    wire sum; // 必须显式声明  
    wire assign c = sum + b; // 如果sum未声明,编译器会报错   
    
endmodule

Unpacked vs. Packed Arrays

  • Blob = Binary Large Object(二进制大对象):
    这是计算机科学中的术语,指一组连续的二进制数据。在 Verilog 语境中,"blob" 强调:

    • 位的连续性:压缩数组的所有位在内存中是连续的,不可单独访问(例如不能只修改其中几位而不影响其他位)。
    • 不可分割性:在模拟器中,整个数组被视为一个整体,而非独立的位集合。
  • 与硬件的区别
    在硬件中,压缩数组可能映射到实际的寄存器或总线(例如 8 位寄存器),但 "blob" 的概念更侧重于模拟器中的表示方式,而非物理实现。
  1. 压缩数组(位宽声明在前)
wire [7:0] data;      // 8位压缩数组(1个8位寄存器)
reg [3:0][7:0] matrix; // 压缩多维数组(4个8位寄存器)
  • 解释

    • [7:0] 在变量名data前,声明一个 8 位向量,所有位连续存储。
    • matrix 的维度为[3:0][7:0],表示 4 个 8 位寄存器,在模拟器中视为一个 32 位的整体(4×8=32位)。
  1. 非压缩数组(维度声明在后)
reg [7:0] memory [0:255]; // 256个8位存储单元(非压缩)
wire [3:0] array [0:7];   // 8个4位元素
  • 解释

    • memory 是一个 256×8 位的存储器,[0:255] 在变量名后,表示有 256 个独立的 8 位存储单元。
    • 每个元素(如memory[0]memory[1])在硬件中可能对应不同的物理地址。

Accessing Vector Elements: Part-Select

位宽不匹配时的处理规则
当赋值语句左右两侧的位宽不一致时,Verilog 会按以下规则处理:

1. 右侧位宽 < 左侧位宽 → 零扩展(Zero-Extend)

  • 规则:在右侧向量的高位补零,使其位宽与左侧匹配。
  • 示例

    wire [7:0] w;  // 左侧:8位    
    wire [3:0] a;  // 右侧:4位
    assign w = a;  // 自动零扩展为8位:a[3:0] → w[7:0] = {4'b0, a}
  • a = 4'b1010,则w = 8'b0000_1010

2. 右侧位宽 > 左侧位宽 → 截断(Truncate)

  • 规则:丢弃右侧向量的高位,只保留与左侧位宽相同的低位部分。
  • 示例

    wire [3:0] w;  // 左侧:4位
    wire [7:0] a;  // 右侧:8位
    assign w = a;  // 自动截断为4位:a[7:0] → w[3:0] = a[3:0]
  • a = 8'b1111_1010,则w = 4'b1010(丢弃高位1111)。

3. 符号数的扩展(Signed Extension)

  • 规则:若右侧是有符号数(用reg signedwire signed声明),扩展时补符号位(而非零)。
  • 示例
 wire signed [3:0] a;    // 4位有符号数
 wire signed [7:0] w;    // 8位有符号数
 assign w = a;           // 符号扩展:a[3]为符号位
  • a = 4'b1010(十进制 - 6),则w = 8'b1111_1010(仍为 - 6)。

Solution

`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[7:0] = in[15:8];
    assign out_lo[7:0] = in[7:0];
    
endmodule

Vectors part select

Solution

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

Bitwise operators

Solution

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
);

    //实现 the bitwise-OR of the two vectors  
    assign out_or_bitwise[2] = a[2] | b[2];
    assign out_or_bitwise[1] = a[1] | b[1];
    assign out_or_bitwise[0] = a[0] | b[0];
    
    //实现 the logical-OR of the two vectors
    assign out_or_logical = (a[0] | b[0]) | (a[1] | b[1]) | (a[2] | b[2]);
    
    //Place the inverse of `b` in the upper half of `out_not` (i.e., bits [5:3]), and the inverse of `a` in the lower half.
    assign out_not[5] = ~b[2];
    assign out_not[4] = ~b[1];
    assign out_not[3] = ~b[0];
    assign out_not[2] = ~a[2];
    assign out_not[1] = ~a[1];
    assign out_not[0] = ~a[0];

endmodule

对于第三部分的6行,可以用更简洁的语法表示:

assign out_not = {~b, ~a};  

其中({})为拼接运算符

  • 功能:将多个向量按指定顺序连接成一个更长的向量。
  • 语法{向量1, 向量2, ...}
  • 规则

    • 从左到右:左侧向量放在结果的高位,右侧向量放在低位
    • 总位宽:结果的位宽等于所有拼接向量的位宽之和。
  • 示例

    a = 3'b101;    // 3位向量
    b = 3'b011;    // 3位向量
    {a, b} = 6'b101011;  // a在高位,b在低位
    {b, a} = 6'b011101;  // 顺序颠倒,结果不同

Four-input gates

用 Verilog 实现连续异或、同或:
若要处理的操作数位宽是固定的,直接使用按位取反异或运算符即可:

module xnor_reduction (   
    input [N-1:0] a, // 假设N是操作数的位宽   
    output y   
); 
    assign y = ^a; // 先进行异或缩减操作   
    assign y = ~y; // 再对结果取反,得到同或结果   
// 或者可以合并为:assign y = ~^a;   
endmodule

Vector concatenation operator

易错点:正确的做法应该是直接取拼接后的高 8 位(即 a 的全部 5 位 + b 的前 3 位 b[4:2],而不是后 3 位 b[2:0])。

Solution

module top_module ( 
    input [4:0] a, b, c, d, e, f,
    output [7:0] w, x, y, z 
); // 将所有输入向量连接为30位,再补两个1,形成32位 
    wire [31:0] combined = {a, b, c, d, e, f, 2'b11}; // 分割为四个8位输出   
    
    assign w = combined[31:24]; 
    assign x = combined[23:16]; 
    assign y = combined[15:8]; 
    assign z = combined[7:0]; 
endmodule

Vector reversal 1

Solution

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]};
endmodule

Replication operator

  • 符号扩展:

    • 在计算机中,有符号数(如负数)通常用二进制补码表示。当你需要将一个位数较少的有符号数(如 8 位)转换为位数更多的有符号数(如 32 位)时,必须保持其数值不变
    • 符号扩展的规则是:用原数的符号位(最高位)填充扩展后的高位
  • 为什么符号扩展有效?

    • 对于正数,符号位为 0,高位补 0 不改变数值。
    • 对于负数,符号位为 1,高位补 1 保持补码的数值不变(例如 - 1 的补码是全 1)。

    通过这种方式,扩展后的 32 位数与原始 8 位数在数值上完全相等。

Solution

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

More replication

Solution

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] top;
    wire [24:0] bottom;
    assign top = {{5{a}},{5{b}},{5{c}},{5{d}},{5{e}}};
    assign bottom = {5{{a,b,c,d,e}}};

    //Error
   /* integer p = 24;
    for (integer i = 0; i < 5; i = i + 1) begin 
        for (integer j = 0; j < 5; j = j + 1) begin 
            assign out[p] = ~top[i] ^ bottom[j];  
            assign p = p - 1;
            end
    end*/
    
    assign out = ~(top ^ bottom);
endmodule