Gokong Space | 行空空间 - Verilog
type: channel
link: https://gokong.space/tag/Verilog/
items: Verilog 学习笔记（14）：More Circuits
items: Verilog 学习笔记（13）：Shift Registers
items: Verilog 学习笔记（12）：Counters
items: Verilog 学习笔记（11）：Latches and Flip-Flops
items: Verilog 学习笔记（9）：Arithmetic Circuits
items: Verilog 学习笔记（8）：Multiplexers
items: Verilog 学习笔记（7）：Basic Gates
items: Verilog 学习笔记（6）：More Verilog Features
items: Verilog 学习笔记（5）：Procedures
items: Verilog 学习笔记（4）：Modules Hierarchy

Verilog 学习笔记（14）：More Circuits
type: item
date: 2025-07-26T23:50:00+08:00
description: Rule 90.数组的异或规则是对应分量两两异或，得到一个新的数组。 Solutionmodule top_module( input clk, input load, input [511:0] data, output [511:0] q ); always @(posedge clk) begin if (load) //别忘了先加载 q <= data; else q <= {1'b0,q[511:1]} ^ {q[510:0],1'b0}; end endmodule Rule 110将左、中、右状态组合为 3 位索引，查表（Rule 110 的转移表）得到下一状态。将左、中、右分别作为三个变量（含有512个分量的数组），作卡诺图：L\C R000111100011110101于是，$C^{(n+1)} = \bar{C}R +\bar{L}C+C\bar{R}$ Solutionmodule top_module( input clk, input load, input [511:0] data, output [511:0] q ); wire [511:0] L,C,R; assign L = {1'b0,q[511:1]}; assign C = q; assign R = {q[510:0],1'b0}; always @(posedge clk) begin if(load) q <= data; else q <= (~C & R) | (~L & C) | (C & ~R); end endmodule Conway's Game of Life 16x16题意生命游戏是二维元胞自动机，每个细胞（cell）状态为1（活）或0（死），下一状态由8 个邻居的存活数决定：邻居存活数细胞下一状态0-1 个死亡（变 0）2 个保持当前状态3 个复活（变 1，即使之前是死的）≥4 个死亡（变 0）索引转换由一维索引转换到二维索引：行号 i：用idx 除以 16取整（舍去余数）；等效于： idx >> 4（右移 4 位 = 除以 2⁴）。列号 j：j = idx % 16（取模运算，即余数）；等效于按位与：idx & 15（15 的二进制是 1111，按位与之后达到保留低 4 位（即余数）的效果）。由二维索引转换到一维索引： (i, j) 的一维索引为 i * 16 + j.右移位运算符>> 是 右移位运算符：逻辑右移（>>）将二进制数向右移动，左侧空出的位用 0 填充，不考虑符号位。 语法：A >> N（将 A 右移 N 位）。算术右移（>>>）将二进制数向右移动，左侧空出的位用符号位填充（即保持负数的符号）。 语法：A >>> N（将 A 右移 N 位）。Solutionmodule top_module( input clk, input load, input [255:0] data, output [255:0] q ); reg [255:0] q_reg; // 模块级寄存器存储当前状态 assign q = q_reg; // 输出直接映射到寄存器 always @(posedge clk) begin // ------- 步骤1：声明过程块内的变量（必须放在块的开头）--------- reg [255:0] next_q; //存储下一状态（局部reg） integer idx; //当前细胞的一维索引 integer dr; //相对于当前细胞的行偏移（Delta Row） integer dc; //相对于当前细胞的列偏移（Delta Column） integer i; //当前细胞的二维行索引 integer j; //当前细胞的二维列索引 integer r; //邻居的绝对坐标的行索引 integer c; //邻居的绝对坐标的列索引 integer neighbor_idx; //邻居的一维索引 integer cnt; //邻居的存活数目 if (load) begin // 加载模式：直接赋值 q_reg <= data; end else begin // --------- 步骤2：遍历每个细胞，计算下一状态 ------------ for (idx = 0; idx < 256; idx = idx + 1) begin i = idx >> 4; // 计算当前细胞的行号（0~15） j = idx & 15; // 计算当前细胞的列号（0~15） cnt = 0; // 邻居存活数初始化 // 遍历8个邻居（dr, dc ∈ {-1, 0, 1}，左右位移只能取1或-1，所以待会需要跳过自身） for (dr = -1; dr <= 1; dr = dr + …

Verilog 学习笔记（13）：Shift Registers
type: item
date: 2025-07-26T09:40:00+08:00
description: 4-bit shift register异步复位的优先级：areset为高时，立即复位（不管时钟和其他信号）。加载 vs 移位的优先级：若load为 1，无论和ena为何值，加载优先（先判断load）。右移操作的行为：右移时，q[3]补 0，q[0]被移出（例如：q=1010右移后变为0101）。Solutionmodule top_module( input clk, input areset, // async active-high reset to zero input load, input ena, input [3:0] data, output reg [3:0] q); always @(posedge clk or posedge areset) begin if (areset) begin q <= 4'b0000; end else begin if (load) begin q <= data; end else if(ena) begin q <= {1'b0,q[3:1]}; end end end endmodule Left/right rotatorSolutionmodule top_module( input clk, input load, input [1:0] ena, input [99:0] data, output reg [99:0] q); always @(posedge clk) begin if (load) // load q <= data; else if (ena) begin case(ena) 2'b00 : q <= q; // 其实这一行永远不会被执行！所以else分支可以被简化，见下方。 2'b01 : q <= {q[0],q[99:1]}; // 右旋转 （采用分块组合要比使用循环更简便） 2'b10 : q <= {q[98:0],q[99]};// 左旋转 2'b11 : q <= q; default q <= q; endcase end else begin // 当ena为0时执行 保持不变 q <= q; end end endmodule 简化else之后：always @(posedge clk) begin if (load) q <= data; else if (ena == 2'b01) q <= {q[0],q[99:1]}; // 右旋转 else if (ena == 2'b10) q <= {q[98:0],q[99]}; // 左旋转 // 其他情况（ena=2'b00或2'b11）保持不变 endLeft/right arithmetic shift by 1 or 8A 5-bit number 11000 arithmetic right-shifted by 1 is 11100, while a logical right shift would produce 01100. However, there is no difference between logical and arithmetic left shifts. Solutionmodule top_module( input clk, input load, input ena, input [1:0] amount, input [63:0] data, output reg [63:0] q); always @(posedge clk) begin if (load) begin q <= data; end else if (ena) begin case (amount) 2'b00: q <= {q[62:0],1'b0}; 2'b01: q <= {q[55:0],8'b0}; 2'b10: q <= {q[63],q[63:1]}; 2'b11: q <= {{8{q[63]}},q[63:8]}; //注意：位拼接语法 default: q <= q; endcase end end endmodule 5-bit LFSR线性反馈移位寄存器（LFSR） linear feedback shift register LFSR 是一种通过移位寄存器和反馈逻辑生成伪随机序列的电路。 Galois 型 LFSR 的特点：反馈逻辑通过 异或（XOR） 连接特定 “抽头”（tap）位，生成下一个状态的最低位（或最高位，依结构而定）。最大长度 LFSR（maximal-length）的抽头位置经过精心选择，可遍历 $2^n-1$ 个状态（n为位数，全零状态永远不会出现）。在本题中：位数：5 位（输出q[4:0]，q[4]是最高…

Verilog 学习笔记（12）：Counters
type: item
date: 2025-07-25T08:00:00+08:00
description: Four-bit binary counterSolutionmodule top_module ( input clk, input reset, // Synchronous active-high reset output [3:0] q); always @(posedge clk) begin if(reset == 1) q <= 4'b0000; else if(q == 4'b1111) q <= 4'b0000; else q <= q + 1; end endmodule Decade counterSolutionmodule top_module ( input clk, input reset, // Synchronous active-high reset output [3:0] q); always @(posedge clk) begin if(reset == 1) q <= 4'b0000; else if(q == 4'b1001) q <= 4'b0000; else q <= q + 1; end endmodule Decade counter againSolutionmodule top_module ( input clk, input reset, output [3:0] q); always @(posedge clk) begin if(reset == 1) q <= 4'b0001; else if(q == 4'b1010) q <= 4'b0001; else q <= q + 1; end endmodule Slow decade counter暂停功能：仅当 slowena 为高电平时，计数器才会在时钟上升沿递增；否则保持当前值。 Solutionmodule top_module ( input clk, input slowena, input reset, output [3:0] q); always @(posedge clk) begin if(reset == 1) q <= 4'd0; else if(slowena) begin if(q == 4'd9) q <= 4'd0; else q = q + 1; end else q <= q; end endmodule Counter 1-12同步复位：reset 高电平时，时钟上升沿将计数器同步复位到 1。使能控制：enable 高电平时，计数器运行（计数）；enable 低电平时，计数器保持当前值（暂停）。**load 的核心作用:- **立即覆盖当前值**：当 `load=1` 时，无论计数器当前状态如何，都会在下一个时钟上升沿将 `d` 端口的值加载到计数器输出 `Q`。 - **优先级高于 `enable`**：即使 `enable=0`（计数器暂停），只要 `load=1`，计数器仍会加载 `d` 的值。 计数器的四种状态：loadenable计数器行为1X加载 d 的值（例如复位到 1 或回绕到 1）01正常计数（Q = Q + 1）00保持当前值（暂停）10仍加载 d 的值（load 优先级更高）已知：module count4( input clk, input enable, input load, input [3:0] d, output reg [3:0] Q ); Solutionmodule top_module ( input clk, input reset, input enable, output [3:0] Q, output c_enable, output c_load, output [3:0] c_d ); assign c_enable = enable; assign c_load = reset | (Q == 4'd12 && enable); assign c_d = c_load ? 4'b1 : 4'b0; count4 the_counter ( .clk(clk), .enable(c_enable), .load(c_load), .d(c_d), .Q(Q) ); endmoduleCounter 1000题中给出了一个十进制的模块，所以需要使用三次以达到把1000Hz降到1Hz. 已知：module bcdcount ( input clk, input reset, input enable, output reg [3:0] Q );Solutionmodule top_module ( input clk, input reset, output OneHertz, output [2:0] c_enabl…

Verilog 学习笔记（11）：Latches and Flip-Flops
type: item
date: 2025-07-24T14:30:00+08:00
description: D flip-flopClocked always blocks should use non-blocking assignments: <=.Solutionmodule top_module ( input clk, // Clocks are used in sequential circuits input d, output reg q );// // Use a clocked always block // copy d to q at every positive edge of clk always @(posedge clk) begin q <= d; end endmodule D flip-flopsSolutionmodule top_module ( input clk, input [7:0] d, output [7:0] q ); always @(posedge clk) begin q <= d; end endmoduleDFF with resetSolutionmodule top_module ( input clk, input reset, // Synchronous reset input [7:0] d, output [7:0] q ); always @(posedge clk) begin if (reset) begin //复位 q <= 8'b0; end else begin q <= d; end end endmodule DFF with reset value正触发: posedge 负触发: negedgeSolutionmodule top_module ( input clk, input reset, input [7:0] d, output [7:0] q ); always @(negedge clk) begin if (reset) begin q <= 8'h34; end else begin q <= d; end end endmodule DDF with asynchronous reset异步复位The only difference in code between synchronous and asynchronous reset flip-flops is in the sensitivity list——将复位信号写入敏感列表中。 Solutionmodule top_module ( input clk, input areset, // active high asynchronous reset input [7:0] d, output [7:0] q ); always @(posedge clk, posedge areset) begin if (areset) q <= 0; else q <= d; end endmodule DFF with byte enablewire vs. reg特性wirereg存储功能无存储功能，数值由驱动源决定有存储功能，能保持当前值直至下一次赋值赋值方式只能使用连续赋值（如assign语句）只能在initial或always块内赋值使用场景用于连线、组合逻辑输出用于时序逻辑（如触发器）、组合逻辑中的中间变量默认初始值默认值为z（高阻态）默认值为x（未知状态）下面通过两段代码示例，直观展示wire和reg的使用差异：// wire的使用示例 module wire_example; reg a, b; // 输入信号定义为reg类型 wire out; // 输出信号定义为wire类型 // 连续赋值，out的值会随着a和b的变化而立即改变 assign out = a & b; initial begin a = 1'b0; b = 1'b0; #10 a = 1'b1; #10 b = 1'b1; end endmodule// reg的使用示例 module reg_example; reg clk, rst, in; reg out; // 输出信号定义为reg类型，因为在always块中被赋值 // 时序逻辑：在时钟上升沿更新out的值 always @(posedge clk or posedge rst) begin if (rst) begin out <= 1'b0; // 复位时将out置为0 end else begin out <= in; // 时钟上升沿时将in的值赋给out end end initial begin clk = 1'b0; forever #5 clk = ~clk; // 生成周期为10的时钟信号 end …

Verilog 学习笔记（9）：Arithmetic Circuits
type: item
date: 2025-07-16T18:00:00+08:00
description: Half adderSolutionmodule top_module( input a, b, output cout, sum ); assign cout = a & b; assign sum = a ^ b; endmodule A half adder adds two bits (with no carry-in) and produces a sum and a carry-out.Full adderSolutionmodule top_module( input a, b, cin, output cout, sum ); assign sum = a ^ b ^ cin; assign cout = (a & b) | (a & cin) | (b & cin); endmodule 3-bit binary adder三位加法器需 3 个全加器级联，将低位的进位输出连接到高位的进位输入，形成进位链。 Solutionmodule top_module( input [2:0] a, b, input cin, output [2:0] cout, output [2:0] sum ); assign sum[0] = a[0] ^ b[0] ^ cin; assign cout[0] = (a[0] & b[0]) | (b[0] & cin) | (a[0] & cin); assign sum[1] = a[1] ^ b[1] ^ cout[0]; assign cout[1] = (a[1] & b[1]) | (b[1] & cout[0]) | (a[1] & cout[0]); assign sum[2] = a[2] ^ b[2] ^ cout[1]; assign cout[2] = (a[2] & b[2]) | (b[2] & cout[1]) | (a[2] & cout[1]); endmodule AdderSolutionmodule top_module ( input [3:0] x, input [3:0] y, output [4:0] sum); wire cout0,cout1,cout2; FullAdder FA1 (x[0],y[0],1'b0,cout0,sum[0]); FullAdder FA2 (x[1],y[1],cout0,cout1,sum[1]); FullAdder FA3 (x[2],y[2],cout1,cout2,sum[2]); FullAdder FA4 (x[3],y[3],cout2,sum[4],sum[3]); endmodule //直接用一下全加器 module FullAdder( input a, b, cin, output cout, sum ); assign sum = a ^ b ^ cin; assign cout = (a & b) | (a & cin) | (b & cin); endmoduleSigned addition overflowA signed overflow occurs when adding two positive numbers produces a negative result, or adding two negative numbers produces a positive result.In addition，正数和负数相加时，因和的范围天然被补码覆盖，故无需判断溢出，必然无溢出。 BTW：// 加法运算 wire [7:0] sum = a + b; // 执行数值相加，考虑进位 // 按位与操作 wire [7:0] and_result = a & b; // 逐位AND，不考虑进位Solutionmodule top_module ( input [7:0] a, input [7:0] b, output [7:0] s, output overflow ); // assign s = ... // assign overflow = ... assign s = a + b; //仅需要考虑最高位（符号位）即可 assign overflow = (a[7] && b[7] && ~s[7] ) || (~a[7] && ~b[7] && s[7]); endmodule 100-bit binary adderSolutionmodule top_module( input [99:0] a, b, input cin, output cout, output [99:0] sum ); //assign sum = a ^ b ^ cin;…

Verilog 学习笔记（8）：Multiplexers
type: item
date: 2025-07-14T16:50:00+08:00
description: 2-to-1 multiplexerSolutionmodule top_module( input a, b, sel, output out ); assign out = sel ? b : a; endmodule 2-to-1 bus multiplexerSolutionmodule top_module( input [99:0] a, b, input sel, output [99:0] out ); assign out = sel ? b : a; //每一位允许自动匹配 endmodule 9-to-1 multiplexerSolutionmodule top_module( input [15:0] a, b, c, d, e, f, g, h, i, input [3:0] sel, output [15:0] out ); always @(*) begin case (sel) 4'b0000:out = a; 4'b0001:out = b; 4'b0010:out = c; 4'b0011:out = d; 4'b0100:out = e; 4'b0101:out = f; 4'b0110:out = g; 4'b0111:out = h; 4'b1000:out = i; //default:out = 1; //在输出端口16位宽的的时候不能直接写1 default: out = 16'hFFFF; // 设置默认值为全1 （16进制） endcase end endmodule 256-to-1 multiplexerVector indices can be variable, as long as the synthesizer can figure out that the width of the bits being selected is constant. In particular, selecting one bit out of a vector using a variable index will work. Solutionmodule top_module( input [255:0] in, input [7:0] sel, output out ); assign out = in[sel]; endmodule 256-to-1 4-bit multiplexerSolutionmodule top_module( input [1023:0] in, input [7:0] sel, output [3:0] out ); assign out = {in[4*sel+3],in[4*sel+2],in[4*sel+1],in[4*sel]}; //注意顺序应该是从高位到低位 endmodule

Verilog 学习笔记（7）：Basic Gates
type: item
date: 2025-07-12T20:50:00+08:00
description: 本节是一些练习巩固的习题。WireSolutionmodule top_module ( input in, output out); assign out = in; endmoduleGNDGND（Ground）： “地线” 或 “接地”。Solutionmodule top_module ( output out); assign out = 1'b0; endmoduleNORSolutionmodule top_module ( input in1, input in2, output out); assign out = ~(in1 | in2); //注意别忘了“非” endmoduleAnother gateSolutionmodule top_module ( input in1, input in2, output out); assign out = in1 & ~in2; endmoduleTwo gatesSolutionmodule top_module ( input in1, input in2, input in3, output out); wire m1; assign m1 = ~(in1 ^ in2); assign out = m1 ^ in3; endmoduleMore logic gatesSolutionmodule top_module( input a, b, output out_and, output out_or, output out_xor, output out_nand, output out_nor, output out_xnor, output out_anotb ); assign out_and = a & b; assign out_or = a | b; assign out_xor = a ^ b; //异或 assign out_nand = ~(a & b); assign out_nor = ~(a | b); assign out_xnor = ~(a ^ b); //同或 assign out_anotb = a & ~b; //a 和 非b endmodule7420 chipSolutionmodule top_module ( input p1a, p1b, p1c, p1d, output p1y, input p2a, p2b, p2c, p2d, output p2y ); assign p1y = ~(p1a & p1b & p1c & p1d); assign p2y = ~(p2a & p2b & p2c & p2d); endmoduleTruth tablesOne simple method to create a circuit that implements the truth table's function is to express the function in sum-of-products form. Sum (meaning OR) of products (meaning AND) means using one N-input AND gate per row of the truth table (to detect when the input matches each row), followed by an OR gate that chooses only those rows that result in a '1' output. 总结：推导 sum-of-products (SOP，积之和)的核心逻辑：用最小项 “标记” 所有输出为 1 的输入组合，再用 OR 运算 “汇总” 这些有效组合。由于最小项仅在唯一输入组合下为 1，OR 之后的表达式能精准复现真值表的输出逻辑。“找 1 行，写反 / 原变量乘积，再 OR”。 Solutionmodule top_module( input x3, input x2, input x1, // three inputs output f // one output ); assign f = (~x3 & x2 & ~x1) | (~x3 & x2 & x1) | (x3 & ~x2 & x1) | (x3 & x2 & x1); endmoduleTwo-bit equality通过直接比较两个 2 位输入 A 和 B 来判断它们是否相等，采用了 Verilog 的条件赋值语句即可。 Solutionmodule top_module ( input [1:0] A, input [1:0] B, output z ); as…

Verilog 学习笔记（6）：More Verilog Features
type: item
date: 2025-07-09T19:19:36+08:00
description: Conditional ternary operatorposedgeposedge 是 Verilog 中用于检测信号上升沿的关键字，表示信号从低电平变为高电平的瞬间。非阻塞赋值非阻塞赋值的特性执行机制并发执行：非阻塞赋值在当前时间步的所有语句计算完成后，才统一更新变量值。延迟生效：赋值语句不会立即改变变量值，而是 “计划” 在当前时间步结束时更新。代码示例always @(posedge clk) begin a <= b; // 计划在时间步结束时将b的值赋给a b <= a; // 计划在时间步结束时将a的原始值赋给b end上述代码中，a和b会在时钟上升沿同时更新值，因此交换了彼此的数据。特性非阻塞赋值 (<=)阻塞赋值 (=)执行顺序并发执行，时间步结束时统一更新顺序执行，立即更新变量值适用场景时序逻辑（触发器、状态机）组合逻辑（算术运算、条件判断）潜在问题无竞争条件时序逻辑中可能引发竞争和毛刺典型应用always @(posedge clk)always @(*) 或 assignassignassign语句是用于描述组合逻辑的基本方式，它会持续监控右侧表达式的变化，并立即将结果赋值给左侧的信号。这种赋值方式对应实际硬件中的逻辑门电路，适合实现组合逻辑功能。Solutionmodule top_module ( input [7:0] a, b, c, d, output [7:0] min);// // assign intermediate_result1 = compare? true: false; wire [7:0] m1 = a < b ? a : b; wire [7:0] m2 = m1 < c ? m1 : c; wire [7:0] m3 = m2 < d ? m2 : d; assign min = m3; endmoduleReduction operatorsThe _reduction_ operators (归约运算符) can do AND, OR, and XOR of the bits of a vector, producing one bit of output:& a[3:0] // AND: a[3]&a[2]&a[1]&a[0]. Equivalent to (a[3:0] == 4'hf) | b[3:0] // OR: b[3]|b[2]|b[1]|b[0]. Equivalent to (b[3:0] != 4'h0) ^ c[2:0] // XOR: c[2]^c[1]^c[0]Solutionmodule top_module ( input [7:0] in, output parity); assign parity = ^ in; endmoduleReduction: Even wider gatesSolutionmodule top_module( input [99:0] in, output out_and, output out_or, output out_xor ); assign out_and = & in; assign out_or = | in; assign out_xor = ^ in; endmoduleCombinational for-loop: Vector reversal 2Solution (Standard)module top_module ( input [99:0] in, output reg [99:0] out ); always @(*) begin for (int i=0;i<$bits(out);i++) // $bits() is a system function that returns the width of a signal. out[i] = in[$bits(out)-i-1]; // $bits(out) is 100 because out is 100 bits wide. end endmoduleSolution (2)module top_module( input [99:0] in, output [99:0] out ); // for语句会占用大量资源，因此也可以采用generate for语句 genvar i; generate for(i=0;i<100;i=i+1)begin:reverse_bit assign out[99-i] = in[i]; end endgenerate endmoduleCombinational for-loop: 255-bit population countSolutionmodule top_modul…

Verilog 学习笔记（5）：Procedures
type: item
date: 2025-07-08T11:34:35+08:00
description: Always blocks (combinational)Solution// synthesis verilog_input_version verilog_2001 module top_module( input a, input b, output wire out_assign, output reg out_alwaysblock ); assign out_assign = a & b; always @(*) out_alwaysblock = a & b; endmodule Always blocks (clocked)Solution// synthesis verilog_input_version verilog_2001 module top_module( input clk, input a, input b, output wire out_assign, output reg out_always_comb, output reg out_always_ff ); assign out_assign = a ^ b; always @(*) out_always_comb = a ^ b; always @(posedge clk) out_always_ff = a ^ b; endmodule There are three types of assignments in Verilog:Continuous assignments ( assign x = y; ). Can only be used when not inside a procedure ( "always block" ).Procedural blocking assignment: ( x = y; ). Can only be used inside a procedure.Procedural non-blocking assignment: ( x <= y; ). Can only be used inside a procedure.If statement语法格式：always @(*) begin if (condition) begin out = x; end else begin out = y; end end这等效于条件运算符的连续赋值：assign out = (condition) ? x : y;Solution// synthesis verilog_input_version verilog_2001 module top_module( input a, input b, input sel_b1, input sel_b2, output wire out_assign, output reg out_always ); always @(*) begin if (sel_b1 == 1 && sel_b2 == 1) begin // 注意：`=`是用于过程赋值的，而逻辑比较应该使用`==` out_always = b; end else begin out_always = a; end end assign out_assign = (sel_b1 == 1 && sel_b2 == 1) ? b : a; endmoduleIf statement latchesWhen designing circuits, you _must_ think first in terms of circuits:I want this logic gateI want a _combinational_ blob of logic that has these inputs and produces these outputsI want a combinational blob of logic followed by a set of flip-flopsWhat you _must not_ do is write the code first, then hope it generates a proper circuit.If (cpu_overheated) then shut_off_computer = 1;If (~arrived) then keep_driving = ~gas_tank_empty;在不提供 else clauses or a default value 的情况下，Verilog 将会 keep the outputs unchanged，这不是我们想要的。(因为本应 Combinational logic (e.g., logic ga…

Verilog 学习笔记（4）：Modules Hierarchy
type: item
date: 2025-07-07T13:26:25+08:00
description: ModulesThe code for module mod_a looks like this:module mod_a ( input in1, input in2, output out ); // Module body endmoduleBy position: mod_a instance1 ( wa, wb, wc ); By name: mod_a instance2 ( .out(wc), .in1(wa), .in2(wb) );Notice the period immediately preceding the port name in this syntax.在 top_module 中 按名称实例化子模块Solutionmodule top_module ( input a, input b, output out ); //mod_a 是已知的 mod_a u1 (.in1(a), .in2(b), .out(out)); endmodule Connecting ports by positionSolutionmodule top_module ( input a, input b, input c, input d, output out1, output out2 ); mod_a u1 (out1,out2,a,b,c,d); endmodule Connecting ports by nameSolutionmodule top_module ( input a, input b, input c, input d, output out1, output out2 ); mod_a u1(.out1(out1), .out2(out2), .in1(a), .in2(b), .in3(c), .in4(d)); endmodule Three modulesSolutionmodule top_module ( input clk, input d, output q ); wire q1; //别忘了写“；” my_dff u1 (clk,d,q1); wire q2; my_dff u2 (clk,q1, q2); my_dff u3 (clk,q2,q); endmoduleModules and vectorsSolutionmodule top_module ( input clk, input [7:0] d, input [1:0] sel, output [7:0] q ); wire [7:0] q1; my_dff8 u1 (clk, d, q1); wire [7:0] q2; my_dff8 u2 (clk, q1, q2); wire [7:0] q3; my_dff8 u3 (clk, q2, q3); always @(*) begin case (sel) 2'b00: q = d; 2'b01: q = q1; 2'b10: q = q2; 2'b11: q = q3; default: q = d; endcase end endmodule always @(*) 里的 (*) 是一种 隐式敏感列表 语法，用于自动推断组合逻辑的触发条件。 作用：当块内所有被读取的信号发生变化时，自动触发块内代码执行。 编写组合逻辑时优先使用 @(*)，避免敏感列表遗漏导致的错误。Adder 1Solutionmodule top_module( input [31:0] a, input [31:0] b, output [31:0] sum ); wire cout_low; add16 u1 (a[15:0], b[15:0],1'b0, sum[15:0],cout_low); add16 u2 (a[31:16], b[31:16],cout_low, sum[31:16]); endmoduleAdder 2Solutionmodule top_module ( input [31:0] a, input [31:0] b, output [31:0] sum ); wire cout_low; // 用 add1 链接 add16 是题目已知条件 add16 u1 ( .a(a[15:0]), .b(b[15:0]), .cin(1'b0), .sum(sum[15:0]), .cout(cout_low) ); add16 u2 ( .a(a[31:16]), .b(b[31:16]), .cin(cout_low), .sum(sum[31:16]), .cout() ); endmodule module add1 ( input a, inp…