Here write a directory title
Source: https://hdlbits.01xz.net/wiki/wire4
assign left_side = right_side // "Continuous assignment"
In addition to “Continuous Assignment”, Verilog also has three other types of assignment types for program blocks, two of which are comprehensive. We will not use them before starting using program blocks.
When you have multiple assignment statements, the order that they appear in the code is not important. Unlike the programming language, the assignment statement (“continuous assignment”) describes the connection between things, rather than copying the value from one thing to another.
VERILOG has different presses not (~) and logic not (!) The operator is like C. Because we only use one here, it is not important to choose which one.
assign out = ~in;
“assign” declaration will drive logic levels to the wire. One wire cannot have multiple drivers (if so, what is its logic level?)
Verilog has separate bitwise-AND (&) and logical-AND (&&) operators, like C. Since we’re working with a one-bit here, it doesn’t matter which we choose.
assign out = a && b;
assign out = ~(a|b);
assign out = (a & b)|(~a & ~b);
// or
assign out = ~a^b; // ^Different or
// or assign out = (~ a)^b;
Please note that the wire is only driven by one source (output of the door), but it can provide multiple inputs.
module top_module(input a,input b,input c,input d,output out,output out_n);
wire or_in_1;
wire or_in_2;
assign or_in_1 = a&b;
assign or_in_2 = c&d;
assign out = or_in_1|or_in_2;
assign out_n = ~out;
endmodule
module top_module (input p1a, p1b, p1c, p1d, p1e, p1f,output p1y,input p2a, p2b, p2c, p2d,output p2y);
wire p1_1;
wire p1_2;
assign p1_1 = p1a&p1b&p1c;
assign p1_2 = p1d&p1e&p1f;
assign p1y = p1_1|p1_2;
wire p2_1;
wire p2_2;
assign p2_1 = p2c&p2d;
assign p2_2 = p2a&p2b;
assign p2y = p2_1|p2_2;
endmodule
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 o0 = vec[0];
assign o1 = vec[1];
assign o2 = vec[2];
assign outv = vec;
endmodule
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; //bit wire where b [0] is the most-significant bit.
/// Note that the corresponding relationship between the minimum valid bit and the bidding
hidden network (Implicit Nets):
The
hidden NetEase causes BUG. If the variable is not declared, but is defined (assign), it will be declared as 1 bit wire (in fact, you plan to declare it as a vector). By adding the `default_nettype None macro meaning, the hidden declaration function will be turned off, so if it is not declared an error, it is no longer just warning.
wire [2:0] a, c; // Two vectors
assign a = 3'b101; // a = 101
assign b = a; // b = 1 IMPLICITLY-CREATED WIRE (hidden type definition)
assign c = b; // c = 001 <-- bug
my_module i1 (d,e); // d and e are implicitly one-bit wide if not declared.
// This could be a bug if the port was intended to be a vector.
Unpacked vs. Packed Arrays
from the vector as an array of elements, the array length is after the variable name.
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.
Vector part of the choice
In assigning the value operation, if the level of the signal between the left and right sides is different, the interception or zero -zero operation will be performed.
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] // Two lowest bits of z
b[3:0] // illegal. Vector Part-SELECT MATCH The DIREATION of the Declaration.
b[0:3] // The *upper* 4 bits of b.
assign w[3:0] = b[0:3]; // Assign upper 4 bits of b to lower 4 bits of w. w[3]=b[0], w[2]=b[1], etc.
/// There is a problem here. If two "vector directions" have the same vector, one segment is assigned to another vector, then what should I do?
`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
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
As mentioned earlier, it is mentioned by the position and logical operation. When using a vector, the difference between the two operations types becomes important. Copy the computing of the two N position vectors to copy the operation of each bit of the vector, and generate N bits output, and the logical operation regards the entire vector as the Boolean value (True = non -zero, false = zero), and generate 1 1 Bit output.
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:3] = ~b;
assign out_not[2:0] = ~a;
endmodule
Construct a 4 input combination logic circuit: in [3: 0],
There are 3 outputs:
· out_and: output of a 4-input AND gate.
· out_or: output of a 4-input OR gate.
· out_xor: output of a 4-input XOR gate.
module top_module(input [3:0] in,output out_and,output out_or,output out_xor);
assign out_and = ~((~in)&&1);
assign out_or = in&&1;
assign out_xor = in[3]^in[2]^in[1]^in[0];
endmodule
/// or using a reduction operator:
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
{
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
Connection needs to know the level of each element. Connects can be used as a left or right value.
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.
Practice:
module top_module (input [4:0] a, b, c, d, e, f,output [7:0] w, x, y, z ); assign { ... } = { ... };
// in 5-bit, out 8-bit
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'd3};
endmodule
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
or
module top_module(input [7:0] in,output [7:0] out);
always @(*) begin
for (int i=0; i<8; i++) // int is a SystemVerilog type. Use integer for pure Verilog.
out[i] = in[8-i-1];
end
endmodule
or
module top_module(input [7:0] in,output [7:0] out);
generate
genvar i;
for (i=0; i<8; i = i+1) begin: my_block_name
assign out[i] = in[8-i-1];
end
endgenerate
endmodule
Among them, look at the original text:
/*
// I know you're dying to know how to use a loop to do this:
// Create a combinational always block. This creates combinational logic that computes the same result
// as sequential code. for-loops describe circuit *behaviour*, not *structure*, so they can only be used
// inside procedural blocks (e.g., always block).
// The circuit created (wires and gates) does NOT do any iteration: It only produces the same result
// AS IF the iteration occurred. In reality, a logic synthesizer will do the iteration at compile time to
// figure out what circuit to produce. (In contrast, a Verilog simulator will execute the loop sequentially
// during simulation.)
always @(*) begin
for (int i=0; i<8; i++) // int is a SystemVerilog type. Use integer for pure Verilog.
out[i] = in[8-i-1];
end
// It is also possible to do this with a generate-for loop. Generate loops look like procedural for loops,
// but are quite different in concept, and not easy to understand. Generate loops are used to make instantiations
// of "things" (Unlike procedural loops, it doesn't describe actions). These "things" are assign statements,
// module instantiations, net/variable declarations, and procedural blocks (things you can create when NOT inside
// a procedure). Generate loops (and genvars) are evaluated entirely at compile time. You can think of generate
// blocks as a form of preprocessing to generate more code, which is then run though the logic synthesizer.
// In the example below, the generate-for loop first creates 8 assign statements at compile time, which is then
// synthesized.
// Note that because of its intended usage (generating code at compile time), there are some restrictions
// on how you use them. Examples: 1. Quartus requires a generate-for loop to have a named begin-end block
// attached (in this example, named "my_block_name"). 2. Inside the loop body, genvars are read only.
generate
genvar i;
for (i=0; i<8; i = i+1) begin: my_block_name
assign out[i] = in[8-i-1];
end
endgenerate
*/
can also refer to Zhihu: https://zhuanlan.zhihu.com/p/58315855