Arithmetic Logic Fundamentals
Single-Bit Adder Architectures
Fundamental arithmetic processing relies on basic building blocks capable of handling binary summation.
Half-Adder Logic
A half-adder performs addition on two single-bit operands without considering any incoming carry from a less significant position.
Inputs:
- Operand 1 ($A$)
- Operand 2 ($B$)
Outputs:
- Sum ($S$)
- Carry-out ($C_{out}$)
The logical behavior is defined by: $$ S = A \oplus B $$ $$ C_{out} = A \cdot B $$
Full-Adder Architecture
To handle cascading operations, a full-adder incorporates an input carry ($C_{in}$) alongside the primary operands. This allows for multi-bit accumulation where the carry propagates through the chain.
Equations derived via Karnaugh Maps: $$ S = A \oplus B \oplus C_{in} $$ $$ C_{out} = (A \oplus B) \cdot C_{in} + (A \cdot B) $$
Multi-Bit Addition Techniques
Ripple-Carry Limitations
In a standard ripple-carry structure, each stage must wait for the previous carry signal to resolve before calculating its own sum. This sequential dependency creates a bottleneck proportional to the number of bits, significantly impacting propagation delay in wider word sizes.
Carry-Lookahead Optimization
Integrated circuits like the 74HC283 utilize look-ahead logic to bypass the sequential waiting period. Instead of waiting for $C_{i-1}$, each bit's carry generation depends on internal generate ($G_i$) and propagate ($P_i$) signals calculated directly from inputs $A_i$ and $B_i$.
Intermediate Definitions:
- Generate: $G_i = A_i \cdot B_i$
- Propagate: $P_i = A_i \oplus B_i$
The resulting carry equations become parallel expressions: $$ C_0 = G_0 + P_0 \cdot C_{in} $$ $$ C_1 = G_1 + P_1 \cdot G_0 + P_1 \cdot P_0 \cdot C_{in} $$ This reduces delay to constant time relative to circuit depth rather than bit-width.
Subtraction via Complements
Binary subtraction ($A - B$) is typically implemented using addition circuits by converting the subtrahend into its complement form.
Formula: $$ A - B = A + (-B) $$ Using 2's complement representation for negative numbers: $$ A - B = A + (\text{not}(B) + 1) $$
If the final carry-out indicates no overflow, the result is positive and represents the absolute difference. If the carry is zero (indicating underflow), the result requires inversion and addition of one to retrieve the magnitude of the negative value.
Programmable Logic Devices
Programmable Logic Devices (PLDs) allow hardware designers to implement custom combinational logic without fixed gate arrays.
Device Classification
- Low Density ( < 1000 gates): Includes PROM, PLA, PAL, GAL.
- High Density (> 1000 gates): Includes CPLD and FPGA structures.
Array Configurations
Logic realization often involves AND and OR planes. The programmability of these planes defines the device type:
- PROM: Fixed AND array, programmable OR array.
- PAL: Programmable AND array, fixed OR array.
- PLA: Both AND and OR arrays are fully programmable.
These architectures enable efficient mapping of Sum-of-Products expressions into physical silicon.
Verilog HDL Modeling Approaches
Hardware Description Languages provide abstract mechanisms to describe digital systems at varying levels of granularity.
Gate-Level Modeling
At the lowest abstraction, designs are instantiated using primitive logic gates provided by the language library (e.g., and, or, xor).
Example: 2-to-4 Decoder
module decoder_gate(input en, input [1:0] sel, output reg [3:0] out);
wire n_en, n_sel0, n_sel1;
not inst_nen(n_en, en);
not inst_nsel0(n_sel0, sel[0]);
not inst_nsel1(n_sel1, sel[1]);
assign out[0] = ~(n_sel1 & n_sel0 & n_en);
assign out[1] = ~(n_sel1 & sel0 & n_en);
assign out[2] = ~( sel1 & n_sel0 & n_en);
assign out[3] = ~( sel1 & sel0 & n_en);
endmodule
Example: Tri-State Multiplexer
Tri-state buffers allow multiple sources to drive a single net when enabled selectively.
module mux_tri(input data_a, input data_b, input sel, output tri L);
bufif1 out_b(L, data_b, sel); // Enable if high
bufif0 out_a(L, data_a, ~sel); // Enable if low
endmodule
Dataflow Modeling
Dataflow modeling uses continuous assignment statements (assign) to map Boolean algebra directly to nets. This approach offers higher readability and better synthesis automation.
Example: 4-Bit Binary Adder
module adder_dataflow(
input [3:0] operand_a,
input [3:0] operand_b,
input cin,
output [3:0] sum_out,
output cout
);
assign {cout, sum_out} = operand_a + operand_b + cin;
endmodule
Behavioral Modeling
Behavioral descriptions focus on algorithmic functionality rather than physical topology. always blocks define sensitivity lists and procedural assignments.
Conditionals and Case Statements
Procedural assignment requires registers (reg). Conditional logic determines flow based on runtime values.
Example: 4-to-1 Mux Implementation
module mux_behavioral(
input [3:0] data_in,
input [1:0] select_sig,
input enable,
output reg result
);
always @(*) begin
if (!enable)
result = 1'bx;
else
case (select_sig)
2'b00: result = data_in[0];
2'b01: result = data_in[1];
2'b10: result = data_in[2];
2'b11: result = data_in[3];
default: result = 1'b0;
endcase
end
endmodule
Testbench Verification Pattern
Validation is performed using initial blocks to drive stimulus vectors over simulated time steps.
module tb_mux_behavioral;
reg [3:0] data_in;
reg [1:0] select_sig;
reg enable;
wire result;
parameter WAIT_TIME = 50;
// Instantiate Design Under Test
mux_behavioral dut(.data_in(data_in), .select_sig(select_sig), .enable(enable), .result(result));
initial begin
// Initialize Signals
enable = 1'b0; data_in = 4'd0; select_sig = 2'd0;
#WAIT_TIME enable = 1'b1;
#WAIT_TIME select_sig = 2'b01;
#WAIT_TIME select_sig = 2'b10;
#WAIT_TIME select_sig = 2'b11;
#WAIT_TIME $finish;
end
initial begin
$display("Simulation Started");
$monitor($time, " EN=%b, SEL=%b, OUT=%b", enable, select_sig, result);
end
endmodule