Objective: To design a sequential multiplier using ASM methodology in Verilog simulate functionality.
Tool Used: Xilinx Vivado Software
An Arithmetic State Machine (ASM) is a sequential digital system that performs arithmetic operations like addition or subtraction in a step-by-step manner using states. It combines the concept of a Finite State Machine (FSM) with arithmetic processing, where each state represents a specific operation and transitions occur based on clock and input conditions.
The core circuitry of an ASM consists of state registers, combinational logic, and arithmetic units. State registers (flip-flops) store the present state, while combinational logic determines the next state. Arithmetic units such as adders or subtractors perform required operations on data stored in registers.
Another important concept is the data path and control path. The data path includes registers and arithmetic circuits that handle data processing, whereas the control path (FSM) generates signals to control operations and data movement. Multiplexers and buses are often used for efficient data transfer.
Data Path Code :
module PIP01 (
input [15:0] din,
input load, clk,
output reg [15:0] dout
);
always @(posedge clk) begin
if (load)
dout <= din;
end
endmodule
module PIP02 (
input [15:0] din,
input load, clr, clk,
output reg [15:0] dout
);
always @(posedge clk) begin
if (clr)
dout <= 16'b0;
else if (load)
dout <= din;
end
endmodule
module counter (
input [15:0] din,
input load, dec, clk,
output reg [15:0] dout
);
always @(posedge clk) begin
if (load)
dout <= din;
else if (dec)
dout <= dout - 16'b1;
end
endmodule
module adder (
input [15:0] in1, in2,
output reg [15:0] out
);
always @(*) begin
out = in1 + in2;
end
endmodule
module comparator (
input [15:0] data,
output eqz
);
// The instructor mentioned using a reduction NOR, or an equality check
//assign eqz = (data == 16'b0);
// Inside the comparator module
assign eqz = (data == 16'b1);
endmodule
module MUL_datapath (
input [15:0] data_in,
input loadA, loadB, loadP, clrP, decB, clk,
output eqz
);
// Internal buses connecting the components
wire [15:0] X, Y, Z, B_out;
// Instantiate Register A
PIP01 A_reg (.din(data_in), .load(loadA), .clk(clk), .dout(X));
// Instantiate Product Register P (Takes output of Adder 'Z' as input)
PIP02 P_reg (.din(Z), .load(loadP), .clr(clrP), .clk(clk), .dout(Y));
// Instantiate Counter B
counter B_reg (.din(data_in), .load(loadB), .dec(decB), .clk(clk), .dout(B_out));
// Instantiate Adder (Adds A_out and P_out)
adder add_block (.in1(X), .in2(Y), .out(Z));
// Instantiate Comparator (Checks B_out for zero)
comparator comp_block (.data(B_out), .eqz(eqz));
endmodule
Control Path Code:
module MUL_controller (
input clk, start, eqz,
output reg loadA, loadB, loadP, clrP, decB, done
);
reg [2:0] state;
// Parameterized states for readability
parameter S0 = 3'b000, S1 = 3'b001, S2 = 3'b010, S3 = 3'b011, S4 = 3'b100;
// Sequential Block: State Transitions
always @(posedge clk) begin
case (state)
S0: if (start) state <= S1;
S1: state <= S2;
S2: state <= S3;
S3: if (eqz) state <= S4;
else state <= S3; // Remain in S3 (loop) until B == 0
S4: state <= S4; // Stop and remain in S4
default: state <= S0;
endcase
end
// Combinational Block: Control Signal Generation
always @(state) begin
// Initialize all signals to zero by default to prevent latches
loadA = 0; loadB = 0; loadP = 0; clrP = 0; decB = 0; done = 0;
case (state)
S0: ; // Wait state, everything remains 0
S1: loadA = 1;
S2: begin
loadB = 1;
clrP = 1;
end
S3: begin
loadP = 1;
decB = 1;
end
S4: done = 1;
endcase
end
endmodule
Test Bench
module mult_test;
// Testbench variables
reg [15:0] data_in;
reg clk, start;
wire done;
// Internal wires acting as the handshake between Datapath and Controller
wire loadA, loadB, loadP, clrP, decB, eqz;
// Instantiate the Datapath
MUL_datapath DP (
.data_in(data_in),
.loadA(loadA), .loadB(loadB), .loadP(loadP), .clrP(clrP), .decB(decB), .clk(clk),
.eqz(eqz)
);
// Instantiate the Controller
MUL_controller CON (
.clk(clk), .start(start), .eqz(eqz),
.loadA(loadA), .loadB(loadB), .loadP(loadP), .clrP(clrP), .decB(decB),
.done(done)
);
// Clock Generation
initial begin
clk = 0;
forever #5 clk = ~clk; // 10ns clock period
end
// Test Sequence
initial begin
start = 0;
#3 start = 1; // Activate start signal slightly after t=0
#500 $finish; // End simulation at t=500
end
// Apply Input Data
initial begin
#17 data_in = 16'd17; // Apply Multiplicand (A)
#10 data_in = 16'd5; // Apply Multiplier (B) 10ns later
end
// Monitor Output
initial begin
$display("Time | Product(Y) | Done");
$display("--------------------------");
// The instructor points out you can hierarchically access internal datapath wires
// using dot notation (DP.Y) to monitor the product register directly.
$monitor("%0t | %d | %b", $time, DP.Y, done);
end
endmodule
Conclusion: The Arithmetic State Machine was successfully designed and simulated, demonstrating controlled execution of arithmetic operations through state transitions. The results verified correct sequencing and output behavior. Simulation in Xilinx Vivado confirmed proper working of the FSM-based design.

