Verilog language-Vector

Problem 10:Vectors

向量。

向量是一组 wire 信号的集合。类似于总线,一般将向量视为位宽超过 1 位的 wire 信号。

举例

wire [7:0] w;//声明一个8bit位宽的向量,向量名为w,等于8个1bit位宽的wire信号
	     //声明向量时,位宽位于向量之前
wire [7:0] x,y;//声明两个8bit位宽的向量x,y
assign w_0=w[0];//取出向量中最低位的wire信号

module top_module(
	input [2:0] vec, 
	output [2:0] outv,
	output o2,
	output o1,
	output o0
);

	assign outv = vec;

	// This is ok too: assign {o2, o1, o0} = vec;
	assign o0 = vec[0];
	assign o1 = vec[1];
	assign o2 = vec[2];

endmodule
  • python 中的切片语法在 Verilog 中的体现
assign w=vec[1:0];//将vec向量中低两位输入到w中

Problem 11:vector in more detail

关于声明向量

原则:

type [upper:lower] vector_name;//type一般是reg或者wire,如果向量为模块的输入输出端口,则可以在type中添加input/output定义

举例

wire [7:0] w;         // 8-bit wire
reg  [4:1] x;         // 4-bit reg
output reg [0:0] y;   // 1-bit reg  output port (但仍然是一个向量)
input wire [3:-2] z;  // 6-bit wire input (在位宽中使用负数作为 index 是可以的,代表倒数第二位)
output [3:0] a;       // 4-bit output wire. wire 为默认定义,在没有显式声明的情况下
wire [0:7] b;         // 8-bit wire b[0]是这个向量的 最高位 MSB(most-significant bit)
			//向量的比特顺序,比特顺序取决于向量的LSB(最低位)

关于向量数组

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=a;//通过向量名可以获取右边整个向量,此处w获得了a向量所有信号
		//左侧信号位宽大于右侧信号位宽,左值高位部分补零,其余正常赋值
		//左侧信号位宽小于右侧信号位宽,右值高位的部分直接被截断,即保留右值的低位部分
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

字节顺序大小转换。

aaaaaaaabbbbbbbbccccccccdddddddd => ddddddddccccccccbbbbbbbbaaaaaaaa

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

	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
  • 使用 {} 位拼接符
assign out = {in[7-:8],in[15-:8],in[23-:8],in[31-:8]};

Problem 13:Bitwise operators

逐位运算符和逻辑运算符。

逐位运算符:输入 N 比特的向量,对其进行逐位比较,产生一个 N 比特长的输出向量

逻辑运算符:任何类型的输入向量都会被视作布尔值,将布尔值进行逻辑比较后,输出一个 1 比特的结果

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[5:0]=~{b,a};
/*也可以这样写
assign out_not[2:0] = ~a;  // Part-select on left side is o.
assign out_not[5:3] = ~b;  //Assigning to [5:3] does not conflict with [2:0]
*/
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;//按位逻辑运算符默认全部按位进行逻辑运算
    assign out_or  = | in;
    assign out_xor = ^ in;
endmodule

4 输入逻辑门,转换为 Verilog 的思想是将 4 个输入变量进行逻辑操作,得到 1 比特结果,在本题中,最简单的写法是

assign out_and = in[3] & in[2] & in[1] & in[0];

Problem 15:Vector concatenation operator

片选操作符是取出向量的一部分比特

连接操作符是将几个向量合并成一个大向量。

{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

位连接符可以在赋值语句的右侧,也可以在左侧

assign {cout,sum} = a + b + cin;//在全加器中使用一句assign语句实现结果和进位的赋值
input [15:0] in;
output [23:0] out;
assign {out[7:0], out[15:8]} = in;         // 连接符用于赋值语句左侧,交换了字节的顺序
assign out[15:0] = {in[7:0], in[15:8]};    // 连接符用于赋值语句右侧,交换了字节的顺序
assign out = {in[7:0], in[15:8]};       // 此语句作用上与上两句相同交换了字节顺序,但不同的是赋值语句右侧为16位
//赋予左值后,右值扩展为24位,高8位赋零,前两句中,高8位为未赋值状态 

上图上方的方格表示模块 32 位输入向量,按照上下对应关系,输出为下方的 4 个 8 比特向量。

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

    // assign { ... } = { ... };
    assign w = {a,b[4:2]};
    assign x = {b[1:0],c,d[4]};
    assign y = {d[3:0],e[4:1]};
    assign z = {e[0],f,2'b11};//规定了bit位,赋值语句的顺序无关紧要
endmodule

Problem 16:Vector reversal 1

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

  • 笨办法
module top_module (
	input [7:0] in,
	output [7:0] out
);
	assign {out[0],out[1],out[2],out[3],out[4],out[5],out[6],out[7]} = in;
endmodule
  • 使用 组合逻辑 always 块实现
integer i;
always @(*) begin
	for (i=0;i<8;i++)
		out[i]=in[8-i-1];
end

for 循环语句只是代码层面的循环,无法被翻译成电路,真正的电路不存在循环

  • 使用 generate 生成块
generate
	genvar i;
	for(i=0;i<8;i=i+1)
		begin :my_block_name 
			assign out[i]=in[8-i-1];
		end 
endgenerate

generate 生成块主要用于动态生成语句,与上述的过程块循环语句不同,其中的 for 并不是描述电路的一种行为。它将其例化,在电路综合过程中,动态生成代码

Problem 17:Replication operator

重复连接操作符。

{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.
  • 2 对 {} 不能少

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

构建一个电路,将一个 8bit 有符号数扩展为 32bit 数

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

    // assign out = { replicate-sign-bit , the-input };
    assign out = {{24{in[7]}},in};//将符号位in[7]扩展为24位,后接原来的8bit数
endmodule

Problem 18:More Replication

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 = ~{ ... } ^ { ... };
    assign out = ~{{5{a}},{5{b}},{5{c}},{5{d}},{5{e}}} ^ {{5{a,b,c,d,e}}};
endmodule
posted @ 2021-11-24 17:31  heart-z  阅读(245)  评论(0)    收藏  举报