- Asked 3/19
- 2069 Bhadra · 8 marks
- 2071 Bhadra · 3+5 marks
- 2073 Bhadra · 2+6 marks
GCD processor algorithm and VHDL
Short answer
The GCD processor uses Euclid’s subtraction: load a and b; while a≠b and both nonzero, subtract the smaller from the larger; result is max(a,b). Implemented as an FSMD with states IDLE, CHECK, SUBA, SUBB, DONE. VHDL uses a state machine with registers A,B, comparators, and subtractors.
Write an algorithm and VHDL code (finite state machine, with state diagram) for a custom processor that calculates Greatest Common Divisor (GCD) of two numbers.
A GCD processor is a custom (single-purpose) processor built as an FSMD: a datapath (registers, comparator, subtractors) controlled by a finite state machine. It uses Euclid's subtraction method.
Algorithm
read a, b
while (a != b and a != 0 and b != 0)
if a > b then a = a - b
else b = b - a
gcd = max(a, b) -- = a if a = b, or the non-zero one
Example: gcd(48,18): (48,18) -> (30,18) -> (12,18) -> (12,6) -> (6,6) so gcd = 6.
Datapath (FSMD)
a_in -->[Reg A]--+--> [ =, >, =0 comparators ]--+
b_in -->[Reg B]--+ status
^load ^A-B ^load ^B-A |
| | | | v
+-----+-----+-----+<-- control --+------------+
result <-- max(A,B) | FSM |<- start
| controller |-> done
+------------+
State diagram
start=0 (wait)
+----+
v |
( IDLE )
| start=1 : A<=a_in, B<=b_in
v
+-----( CHECK )-----+
| a>b | | a<b | a=b or a=0 or b=0
| v v v
| ( SUBA ) ( SUBB ) ( DONE ) done=1
| A<=A-B B<=B-A | start=0
| | | v
+----+---------+ ( IDLE )
(SUBA, SUBB return to CHECK)
State table
| State | Condition | Datapath action | Next state | done |
|---|---|---|---|---|
| IDLE | start = 0 | none | IDLE | 0 |
| IDLE | start = 1 | A <= a_in, B <= b_in | CHECK | 0 |
| CHECK | a = b, or a = 0, or b = 0 | none | DONE | 0 |
| CHECK | a > b | none | SUBA | 0 |
| CHECK | a < b | none | SUBB | 0 |
| SUBA | - | A <= A - B | CHECK | 0 |
| SUBB | - | B <= B - A | CHECK | 0 |
| DONE | start = 0 | none | IDLE | 1 |
| DONE | start = 1 | none | DONE | 1 |
VHDL code
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity gcd is
port (
clk : in std_logic;
reset : in std_logic; -- asynchronous, active high
start : in std_logic; -- pulse to begin
a_in : in unsigned(7 downto 0);
b_in : in unsigned(7 downto 0);
done : out std_logic; -- '1' when result is valid
result : out unsigned(7 downto 0)
);
end entity gcd;
architecture fsmd of gcd is
type state_t is (S_IDLE, S_CHECK, S_SUBA, S_SUBB, S_DONE);
signal state : state_t;
signal a, b : unsigned(7 downto 0); -- datapath registers
begin
process (clk, reset)
begin
if reset = '1' then
state <= S_IDLE;
a <= (others => '0');
b <= (others => '0');
elsif rising_edge(clk) then
case state is
when S_IDLE =>
if start = '1' then
a <= a_in; -- load operands
b <= b_in;
state <= S_CHECK;
end if;
when S_CHECK =>
if a = b or a = 0 or b = 0 then
state <= S_DONE; -- finished
elsif a > b then
state <= S_SUBA;
else
state <= S_SUBB;
end if;
when S_SUBA =>
a <= a - b; -- a := a - b
state <= S_CHECK;
when S_SUBB =>
b <= b - a; -- b := b - a
state <= S_CHECK;
when S_DONE =>
if start = '0' then -- wait for start to be released
state <= S_IDLE;
end if;
end case;
end if;
end process;
done <= '1' when state = S_DONE else '0';
result <= a when a >= b else b; -- max(a,b): gcd, also right if one operand is 0
end architecture fsmd;
Notes: the code was analysed and simulated with GHDL (gcd(48,18) = 6, gcd(7,5) = 1, gcd(0,9) = 9, gcd(100,75) = 25). Registers A and B hold the datapath state; result is max(A,B), which is the GCD when the machine reaches DONE.
✓ Answer checked by Claude Opus 5.5 (high effort)
Related questions
- LCM processor algorithm and VHDL · Embedded System, chapter 9 · asked 2×
- Sequence detector 1011 state diagram and VHDL · Embedded System, chapter 9
- Two categories of semi-custom IC · Embedded System, chapter 8 · asked 2×
- Greatest and smallest of ten numbers · Computer Programming, chapter 11
- Differentiate Finite State Machine and Automata · Discrete Structure, chapter 2 · asked 2×