Hardware Description Language_Structural Modelling
Tags: #◇Computer Science #◇CSARCH1 #◇Code Snippets #◇M4
◇Overview
This module covers the use of Verilog Hardware Description Language (HDL) for Structural Modelling in combinational circuits.
- Structural Modelling involves combining two or more modules to build a hierarchical description of a design.
- It can follow a top-down or bottom-up approach. In bottom-up design, building blocks are identified first and then combined to build the top-level block.
◇Code Implementation
NAND Implementation (Two-Level)
Example: F = AB + CD using NAND gates.
`timescale 1ns / 1ps
// Define 2-input NAND gate
module NAND_2(F, X, Y);
output F;
input X, Y;
assign F = ~(X & Y);
endmodule
// Structural implementation of F = AB + CD
module NAND_impl(F, A, B, C, D);
input A, B, C, D;
output F;
wire t1, t2;
NAND_2 N1(t1, A, B);
NAND_2 N2(t2, C, D);
NAND_2 N3(F, t1, t2);
endmodule
Non-structural equivalent:
`timescale 1ns / 1ps
module NAND(F, A, B, C, D);
input A, B, C, D;
output F;
assign F = ~((~(A & B)) & (~(C & D)));
endmodule
NOR Implementation (Two-Level)
Example: F = AB + CD = (A+C)(B+C)(A+D)(B+D) using NOR gates.
`timescale 1ns / 1ps
// 2-input NOR gate
module NOR_2(F, X, Y);
output F;
input X, Y;
assign F = ~(X | Y);
endmodule
// 4-input NOR gate
module NOR_4(F, A, B, C, D);
output F;
input A, B, C, D;
assign F = ~(A | B | C | D);
endmodule
// Structural implementation
module NOR_IMPL(F, A, B, C, D);
input A, B, C, D;
output F;
wire p1, p2, p3, p4;
NOR_2 Z1(p1, A, C);
NOR_2 Z2(p2, B, C);
NOR_2 Z3(p3, A, D);
NOR_2 Z4(p4, B, D);
NOR_4 Z5(F, p1, p2, p3, p4);
endmodule
Multiplexer Implementations (4x1 MUX)
Gate-Level Structural:
`timescale 1ns / 1ps
module mux41_gate(Y, I3, I2, I1, I0, S1, S0);
input I3, I2, I1, I0, S0, S1;
output Y;
wire S0_not, S1_not, T1, T2, T3, T4;
not G1 (S0_not, S0),
G2 (S1_not, S1);
and H1 (T1, S1_not, S0_not, I0),
H2 (T2, S1_not, S0, I1),
H3 (T3, S1, S0_not, I2),
H4 (T4, S1, S0, I3);
or (Y, T1, T2, T3, T4);
endmodule
Dataflow:
`timescale 1ns / 1ps
module mux41_data(Y, I3, I2, I1, I0, S1, S0);
input I3, I2, I1, I0, S1, S0;
output Y;
wire T1, T2, T3, T4;
assign T1 = (!S1) & (!S0) & I0;
assign T2 = (!S1) & (S0) & I1;
assign T3 = (S1) & (!S0) & I2;
assign T4 = (S1) & (S0) & I3;
assign Y = T1 | T2 | T3 | T4;
endmodule
Behavioral:
`timescale 1ns / 1ps
module mux41_behav(F, I3, I2, I1, I0, S1, S0);
input I3, I2, I1, I0, S1, S0;
output reg F;
always @*
case ({S1, S0})
2'b00: F = I0;
2'b01: F = I1;
2'b10: F = I2;
2'b11: F = I3;
endcase
endmodule
Advanced Structural Application
Implementing F = Σm(1,2,6,7) using a 4x1 MUX and Z as input:
module sommux41_behav(F, X, Y, Z);
input X, Y, Z;
output F;
wire Z_not;
not K1(Z_not, Z);
// Instantiate 4-to-1 multiplexer for sigma(1,2,6,7)
mux41_behav D1(F, 1'b1, 1'b0, Z_not, Z, X, Y);
endmodule
Testbench:
`timescale 1ns / 1ps
module mux41_behav_TB();
reg [2:0] t_I;
wire t_F;
integer i;
sommux41_behav dut(t_F, t_I[2], t_I[1], t_I[0]);
initial begin
t_I = 3'b000;
for (i=1; i<8; i=i+1) begin
#10 t_I = i;
end
end
initial begin
$display("Implement f=sigma(1,2,6,7) using 4x1 behav multiplexer");
$monitor("time=%0d, X=%b, Y=%b, Z=%b, F=%b ", $time, t_I[2], t_I[1], t_I[0], t_F);
$dumpfile("sommux41_behav.vcd");
$dumpvars();
end
endmodule
Production Deep-Dive: Hierarchical Structural 4-Bit Arithmetic Logic Unit (ALU)
A full industrial-style structural design decomposes a complex datapath into reusable primitive modules connected strictly through intermediate wire nets. Below is a complete 4-bit Arithmetic Logic Unit (ALU) supporting addition (ADD), subtraction (SUB), bitwise AND (AND), and bitwise OR (OR), along with 4 condition code status flags: Zero (Z), Carry (C), Overflow (V), and Negative (N).
Datapath Architecture Diagram
Operation Function Table
Opcode Op[1:0] | Operation | Arithmetic / Logic Function | Subtraction Mechanism (Op[0] = 1) |
|---|---|---|---|
2'b00 | ADD | , unaltered | |
2'b01 | SUB | , (Two's Complement) | |
2'b10 | AND | Bitwise conjunction | |
2'b11 | OR | Bitwise disjunction |
Complete Structural Verilog Implementation
`timescale 1ns / 1ps
// 1. Primitive 1-Bit Full Adder
module full_adder(
output wire sum,
output wire cout,
input wire a,
input wire b,
input wire cin
);
wire s1, c1, c2;
// Sum calculation: a ^ b ^ cin
xor g1 (s1, a, b);
xor g2 (sum, s1, cin);
// Carry calculation: (a & b) | (s1 & cin)
and g3 (c1, a, b);
and g4 (c2, s1, cin);
or g5 (cout, c1, c2);
endmodule
// 2. Structural 4-Bit Ripple Carry Adder with Overflow Detection
module rca_4bit(
output wire [3:0] sum,
output wire cout,
output wire overflow,
input wire [3:0] a,
input wire [3:0] b,
input wire cin
);
wire c0, c1, c2;
full_adder fa0 (sum[0], c0, a[0], b[0], cin);
full_adder fa1 (sum[1], c1, a[1], b[1], c0);
full_adder fa2 (sum[2], c2, a[2], b[2], c1);
full_adder fa3 (sum[3], cout, a[3], b[3], c2);
// Overflow for signed two's complement: Carry into MSB ^ Carry out of MSB
xor g_ovf (overflow, cout, c2);
endmodule
// 3. Structural 4-Bit Bitwise AND Module
module and_4bit(
output wire [3:0] out,
input wire [3:0] a,
input wire [3:0] b
);
and g0 (out[0], a[0], b[0]);
and g1 (out[1], a[1], b[1]);
and g2 (out[2], a[2], b[2]);
and g3 (out[3], a[3], b[3]);
endmodule
// 4. Structural 4-Bit Bitwise OR Module
module or_4bit(
output wire [3:0] out,
input wire [3:0] a,
input wire [3:0] b
);
or g0 (out[0], a[0], b[0]);
or g1 (out[1], a[1], b[1]);
or g2 (out[2], a[2], b[2]);
or g3 (out[3], a[3], b[3]);
endmodule
// 5. Structural 4-Bit 4-to-1 Multiplexer
module mux4_4bit(
output wire [3:0] out,
input wire [3:0] in0, // ADD
input wire [3:0] in1, // SUB
input wire [3:0] in2, // AND
input wire [3:0] in3, // OR
input wire [1:0] sel
);
wire sel0_n, sel1_n;
wire [3:0] w0, w1, w2, w3;
not n0 (sel0_n, sel[0]);
not n1 (sel1_n, sel[1]);
// Decode and route each bit slice structurally
genvar i;
generate
for (i = 0; i < 4; i = i + 1) begin : mux_slice
and a0 (w0[i], in0[i], sel1_n, sel0_n);
and a1 (w1[i], in1[i], sel1_n, sel[0]);
and a2 (w2[i], in2[i], sel[1], sel0_n);
and a3 (w3[i], in3[i], sel[1], sel[0]);
or o0 (out[i], w0[i], w1[i], w2[i], w3[i]);
end
endgenerate
endmodule
// 6. Top-Level Structural 4-Bit ALU with Status Flags
module alu_structural_4bit(
output wire [3:0] result,
output wire flag_z, // Zero flag
output wire flag_c, // Carry flag
output wire flag_v, // Overflow flag
output wire flag_n, // Negative flag
input wire [3:0] a,
input wire [3:0] b,
input wire [1:0] op // 00: ADD, 01: SUB, 10: AND, 11: OR
);
wire [3:0] b_operand;
wire [3:0] arith_res, and_res, or_res;
wire rca_cout, rca_ovf;
// Subtraction logic: if op[0] is 1, invert B using XOR
xor x0 (b_operand[0], b[0], op[0]);
xor x1 (b_operand[1], b[1], op[0]);
xor x2 (b_operand[2], b[2], op[0]);
xor x3 (b_operand[3], b[3], op[0]);
// Instantiate arithmetic and logic modules
rca_4bit adder_unit (
.sum(arith_res),
.cout(rca_cout),
.overflow(rca_ovf),
.a(a),
.b(b_operand),
.cin(op[0]) // Cin = 1 when subtracting (2's complement addition)
);
and_4bit and_unit (.out(and_res), .a(a), .b(b));
or_4bit or_unit (.out(or_res), .a(a), .b(b));
// Structural MUX to select datapath result
mux4_4bit out_mux (
.out(result),
.in0(arith_res),
.in1(arith_res),
.in2(and_res),
.in3(or_res),
.sel(op)
);
// Status Flags:
// Zero flag: NOR of all result bits
nor nor_z (flag_z, result[0], result[1], result[2], result[3]);
// Negative flag: Result MSB (sign bit in two's complement)
assign flag_n = result[3];
// Carry and Overflow flags valid only during arithmetic operations (~op[1])
assign flag_c = (~op[1]) & rca_cout;
assign flag_v = (~op[1]) & rca_ovf;
endmodule
Testbench with Timing Stimulus & Flag Verification
`timescale 1ns / 1ps
module tb_alu_structural_4bit();
reg [3:0] tb_a;
reg [3:0] tb_b;
reg [1:0] tb_op;
wire [3:0] tb_result;
wire tb_z, tb_c, tb_v, tb_n;
// Instantiate Unit Under Test (UUT)
alu_structural_4bit uut (
.result(tb_result),
.flag_z(tb_z),
.flag_c(tb_c),
.flag_v(tb_v),
.flag_n(tb_n),
.a(tb_a),
.b(tb_b),
.op(tb_op)
);
initial begin
$dumpfile("alu_structural.vcd");
$dumpvars(0, tb_alu_structural_4bit);
$display("=== 4-Bit Structural ALU Verification ===");
$monitor("Time=%0t | Op=%b | A=%b (%d) | B=%b (%d) | Res=%b (%d) | Z=%b C=%b V=%b N=%b",
$time, tb_op, tb_a, $signed(tb_a), tb_b, $signed(tb_b), tb_result, $signed(tb_result),
tb_z, tb_c, tb_v, tb_n);
// Test 1: ADD with normal sum (3 + 2 = 5)
tb_op = 2'b00; tb_a = 4'b0011; tb_b = 4'b0010; #10;
// Test 2: ADD with signed overflow (7 + 2 = 9 -> -7 in 4-bit 2's complement)
tb_op = 2'b00; tb_a = 4'b0111; tb_b = 4'b0010; #10;
// Test 3: SUB producing zero (5 - 5 = 0, Z flag high)
tb_op = 2'b01; tb_a = 4'b0101; tb_b = 4'b0101; #10;
// Test 4: SUB producing negative number (2 - 5 = -3, N flag high)
tb_op = 2'b01; tb_a = 4'b0010; tb_b = 4'b0101; #10;
// Test 5: Bitwise AND
tb_op = 2'b10; tb_a = 4'b1100; tb_b = 4'b1010; #10;
// Test 6: Bitwise OR
tb_op = 2'b11; tb_a = 4'b1100; tb_b = 4'b1010; #10;
$display("=== All Test Vectors Completed Successfully ===");
$finish;
end
endmodule
◇References & Navigation
- Previous Topic: ◇Combinational Circuit - Tri state gates
- Next Topic: ◇Introduction to Sequential Circuit
- Related Notes: ◇Introduction to Hardware Description Language, ◇Summary of Verilog Syntax
ACTIVE RECALL VERIFICATION
Select an answer to verify conceptual comprehension and reveal the technical rationale.
What does structural modeling in Verilog HDL involve?
In a bottom-up design approach for structural modeling, what is the first step?
How are individual gates or sub-modules added to a structural model in Verilog?
Which keyword is used to declare internal connections between instantiated modules in structural modeling?
In structural modelling, can a testbench instantiate the top-level module?