The Euclid Algorithm

From Gezel2

Jump to: navigation, search

This design implements Euclid's Greatest Common Divisor algorithm with a single FSMD. The module euclid is connected to a testbench that provides two constant inputs.

euclid.fdl

dp euclid(in  m_in, n_in : ns(16);
          out gcd        : ns(16)) {
  reg m, n               : ns(16);
  reg done               : ns(1);
  reg factor             : ns(16); 

  sfg init    { m = m_in; n = n_in; factor = 0; done = 0; gcd = 0;
                $display("cycle=", $cycle, " m=", m_in, " n=", n_in); }
  sfg shiftm  { m = m >> 1; }
  sfg shiftn  { n = n >> 1; }
  sfg reduce  { m = (m >= n) ? m - n : m;  
                n = (n >  m) ? n - m : n; }
  sfg shiftf  { factor = factor + 1; } 
  sfg outidle { gcd = 0; done = ((m == 0) | (n == 0)); }
  sfg complete{ gcd = ((m > n) ? m : n) << factor;
                $display("cycle=", $cycle, " gcd=", gcd); }
}

fsm euclid_ctl(euclid) {
  initial s0;
  state s1, s2; 

  @s0 (init) -> s1;
  @s1 if (done)               then (complete)          -> s2;
      else if ( m[0] &  n[0]) then (reduce, outidle)   -> s1;
      else if ( m[0] & ~n[0]) then (shiftn, outidle)   -> s1;
      else if (~m[0] &  n[0]) then (shiftm, outidle)   -> s1;
                              else (shiftn, shiftm, 
                                    shiftf, outidle)   -> s1;
  @s2 (outidle) -> s2;
} 

//--- Testbench
dp test_euclid(out m, n : ns(16)) {
  always {
    m = 2322;
    n = 654;
  }    
}

dp euclid_sys {
   sig m, n, gcd : ns(16);
   use euclid(m, n, gcd);
   use test_euclid(m, n);
}

system S {
  euclid_sys;
}

Simulation Output

>fdlsim euclid.fdl 30
cycle=0 m=912 n=28e
cycle=22 gcd=6