HDLbits2.1——Wire and Vectors
一、wire
1、创建一个具有一个输入和一个输出的模块,其行为类似于电线。
1)与物理线不同,Verilog 中的线(和其他信号)是有方向的。这意味着信息仅在一个方向上流动,从(通常是一个)源到接收器(源通常也称为驱动器,将值驱动到线路上)。在 Verilog “连续赋值” (
assign left_side = right_side;
) 中,右侧的信号值被驱动到左侧的导线上。赋值是“连续的”,右边的值发生变化,左边的值立刻发生变化2)模块上的端口也有方向(通常是输入或输出)。输入端口由模块外部的某些东西驱动,而输出端口由外部的某些东西驱动。从模块内部看,输入端口是驱动器或源,而输出端口是接收器。
1 module top_module( input in, output out ); 2 assign out=in; 3 endmodule
2、创建一个具有 3 个输入和 4 个输出的模块,其行为类似于进行这些连接的电线:
a -> w b -> x b -> y c -> z
1)下图说明了电路的每个部分如何对应 Verilog 代码的每一位。从模块外部看,有三个输入端口和四个输出端口。
2)当您有多个分配语句时,它们在代码中出现的顺序无关紧要。与编程语言不同,赋值语句(“连续赋值”)描述事物之间的联系,而不是将值从一个事物复制到另一个 事物的动作。
3)现在也许应该澄清一个潜在的混淆来源:这里的绿色箭头代表电线之间的连接,但它们本身并不是电线。模块本身已经声明了 7 根线(命名为 a、b、c、w、x、y 和 z)。这是因为除非
input
另有output
说明,否则声明实际上声明了一条线。写法input wire a
同理input a
。因此,这些assign
语句不是在创建连线,而是在创建已经存在的 7 条连线之间的连接。
1 module top_module( 2 input a,b,c, 3 output w,x,y,z ); 4 assign w=a,x=b, y=b,z=c; 5 6 endmodule
3、创建一个实现非门的模块。
1)这个电路类似于电线,但略有不同。当从电线连接到电线
in
时,out
我们将使用“非门”而不是普通电线。2)使用分配语句。该
assign
语句将连续驱动inon的逆out
。
1 module top_module( input in, output out ); 2 assign out=!in; 3 endmodule
4、创建一个实现与门的模块。
1)该电路现在有三根导线(
a
、b
和out
)。电线a
和b
已经有输入端口驱动到它们的值。但是电线out
目前不是由任何东西驱动的。编写一个用信号和的 ANDassign
驱动的语句。
2)将信号描述为被驱动(具有由附加的东西决定的已知值)或不被某物驱动。
Input wires
由模块外部的东西驱动。assign
语句会将逻辑电平驱动到线路上。如您所料,一条线不能有多个驱动程序(如果有,它的逻辑级别是多少?),没有驱动程序的线将有一个未定义的值(在综合硬件时通常被视为 0)。
1 module top_module( 2 input a, 3 input b, 4 output out ); 5 assign out=a&b; 6 endmodule
5、创建一个实现 NOR 门(或非门)的模块。
1 module top_module( 2 input a, 3 input b, 4 output out ); 5 assign out=!(a|b); 6 endmodule
6、创建一个实现 XNOR 门(异或非门,也就是同或门)的模块。
1 module top_module( 2 input a, 3 input b, 4 output out ); 5 assign out=a^~b; 6 endmodule
7、实现以下电路。
1)创建两条中间线(命名为您想要的任何名称)将 AND 和 OR 门连接在一起。
2)请注意,馈入 NOT 门的线实际上是 wire out,因此您不必在此处声明第三条线。
3)请注意电线是如何由一个源(门的输出)驱动的,但可以馈送多个输入。
1 module top_module( 2 input a, 3 input b, 4 input c, 5 input d, 6 output out, 7 output out_n ); 8 wire wire1,wire2; 9 assign wire1=a&b,wire2=c&d; 10 assign out=wire1|wire2; 11 12 assign out_n=~(wire1|wire2); 13 14 endmodule
8、7458 是具有四个与门和两个或门的芯片,创建一个与 7458 芯片功能相同的模块。
1)它有 10 个输入和 2 个输出。您可以选择使用
assign
语句来驱动每条输出线,2)或者您可以选择声明(四)条线用作中间信号,其中每条内部线由一个与门的输出驱动。
3)如需额外练习,请尝试两种方式。
1 module top_module ( 2 input p1a, p1b, p1c, p1d, p1e, p1f, 3 output p1y, 4 input p2a, p2b, p2c, p2d, 5 output p2y ); 6 wire w1,w2,w3,w4; 7 assign w1=p2a&p2b,w2=p2c&p2d,w3=p1a&p1c&p1b,w4=p1f&p1e&p1d; 8 assign p2y=w1|w2,p1y=w3|w4; 9 10 11 endmodule
二、Vectors
1、构建一个具有一个 3 位输入的电路,然后输出相同的向量,并将其拆分为三个单独的 1 位输出。将输出连接o0
到输入向量的位置 0。
向量用于使用一个名称对相关信号进行分组,以便于操作。例如,wire [7:0] w;声明一个名为w的 8 位向量,它在功能上等同于具有 8 条单独的连线。
1 module top_module ( 2 input wire [2:0] vec, 3 output wire [2:0] outv, 4 output wire o2, 5 output wire o1, 6 output wire o0 ); // Module body starts after module declaration 7 assign outv=vec; 8 assign o2=vec[2],o1=vec[1],o0=vec[0]; 9 endmodule
2、构建一个组合电路,将输入半字(16 位, [15:0] )拆分为低 [7:0] 和高 [15:8] 字节。
1 `default_nettype none // Disable implicit nets. Reduces some types of bugs. 2 module top_module( 3 input wire [15:0] in, 4 output wire [7:0] out_hi, 5 output wire [7:0] out_lo ); 6 assign out_hi=in[15:8],out_lo=in[7:0]; 7 endmodule
3、一个 32 位向量可以被视为包含 4 个字节(位 [31:24]、[23:16] 等)。构建一个将反转4 字节字 的字节顺序的电路。
AaaaaaaaBbbbbbbbCcccccccDdddddddd => DddddddCcccccccBbbbbbbbAaaaaaaaa
1 module top_module( 2 input [31:0] in, 3 output [31:0] out );// 4 5 // assign out[31:24] = ...; 6 assign out[7:0]=in[31:24]; 7 assign out[15:8]=in[23:16]; 8 assign out[23:16]=in[15:8]; 9 assign out[31:24]=in[7:0]; 10 endmodule
4、构建一个具有两个 3 位输入的电路,用于计算两个向量的按位或、两个向量的逻辑或以及两个向量的逆 (NOT)。
将 out_not的 [5:3]存放b
的反,将 out_not下半部分存放a的反。
1 module top_module( 2 input [2:0] a, 3 input [2:0] b, 4 output [2:0] out_or_bitwise, 5 output out_or_logical, 6 output [5:0] out_not 7 ); 8 assign out_or_bitwise=a|b; 9 assign out_or_logical=a||b; 10 assign out_not[5:3]=~b; 11 assign out_not[2:0]=~a; 12 13 endmodule
5、构建一个具有四个输入的组合电路in[3:0]。
有3个输出:
- out_and:4 输入与门的输出。
- out_or:4 输入或门的输出。
- out_xor:4 输入异或门的输出。
1 module top_module( 2 input [3:0] in, 3 output out_and, 4 output out_or, 5 output out_xor 6 ); 7 assign out_and=∈ 8 assign out_or=|in; 9 assign out_xor=^in; 10 endmodule
6、给定几个输入向量,将它们连接在一起,然后将它们分成几个输出向量。
有六个 5 位输入向量:a、b、c、d、e 和 f,总共 30 位输入。
有四个 8 位输出向量:w、x、y 和 z,用于 32 位输出。
输出应该是输入向量的串联,后跟两个1位:
1 module top_module ( 2 input [4:0] a, b, c, d, e, f, 3 output [7:0] w, x, y, z );// 4 5 // assign { ... } = { ... }; 6 assign {w,x,y,z}={a,b,c,d,e,f,1'b1,1'b1}; 7 8 endmodule
7、给定一个 8 位输入向量 [7:0],反转其位顺序
介绍generate语法
https://blog.csdn.net/woshiyuzhoushizhe/article/details/90453189
1 module top_module( 2 input [7:0] in, 3 output [7:0] out 4 ); 5 generate 6 genvar i; 7 for(i=0;i<=7;i=i+1) 8 begin:name 9 assign out[i]=in[7-i]; 10 end 11 endgenerate 12 13 endmodule
8、构建一个将 8 位数字符号扩展为 32 位的电路。这需要连接 24 个符号位副本(即复制位 [7] 24 次),然后是 8 位数字本身。
看到复制运算符的一个常见地方是,将较小的数字符号扩展为较大的数字,同时保留其符号值。这是通过将较小数字的符号位(最高有效位)复制到左侧来完成的。例如,将4'b 0 101 (5) 符号扩展至 8 位会产生8'b 0000 0101 (5),而将4'b 1 101 (-3) 符号扩展至 8 位会产生8'b 1111 1101 (-3)。
1 module top_module ( 2 input [7:0] in, 3 output [31:0] out );// 4 5 // assign out = { replicate-sign-bit , the-input }; 6 assign out={{24{in[7]}},in}; 7 8 endmodule
9、给定五个 1 位信号(a、b、c、d 和 e),计算 25 位输出向量中的所有 25 个成对的一位比较。如果被比较的两位相等,则输出应为 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;
1 module top_module ( 2 input a, b, c, d, e, 3 output [24:0] out );// 4 5 // The output is XNOR of two vectors created by 6 // concatenating and replicating the five inputs. 7 // assign out = ~{ ... } ^ { ... }; 8 assign out=~{{5{a}},{5{b}},{5{c}},{5{d}},{5{e}}}^{5{a,b,c,d,e}}; 9 endmodule