pipe_mult.hcc


//  pipe_mult.hcc

/*  Pipelined multiplier, adapted from Handel-C Reference Manual,
 *  pp 146-147 and 229-230.  This version generates a full-width
 *  product.
 *
 *    The simulation version can be single-stepped in the DK
 *    simulator so the behavior can be traced.  The evaluation
 *    version fakes I/O through the expansion header so the
 *    performance can be compared to a multiplier that uses the
 *    multiplication operator.
 *
 *    Author: C. Vickery
 *    Fall 2003
 */

#ifdef USE_SIM
#define PAL_TARGET_CLOCK_RATE 1000000
#endif
#if (defined USE_RC200 || USE_RC200E)
#define PAL_TARGET_CLOCK_RATE 50000000
#include <pal_rc200.hch>
#endif
#include <pal_master.hch>
#include <stdlib.hch>

//  Parameters
macro expr multiplicand_width = 4;
macro expr multiplier_width   = 4;
macro expr product_width      = multiplier_width + multiplicand_width;
macro expr pipeline_depth     = multiplier_width;

//  Pipeline registers
unsigned product_width        a[pipeline_depth];
unsigned multiplier_width     b[pipeline_depth];
unsigned product_width        sum[pipeline_depth];

//  stage()
//  ------------------------------------------------------------------
/*
 *    Each stage of the pipeline.  Implements basic add-shift
 *    multiplication algorithm.
 */
  macro proc stage( level )
  {
    par
    {
      sum[level] = 
        sum[level - 1] + ((b[level][0] == 0) ? 0 : 0@a[level]);
      a[level] = a[level - 1] << 1;
      b[level] = b[level - 1] >> 1;
    }
  }


//  Simulation Version
//  ==================================================================
#ifdef USE_SIM
chanin input_a with { infile = "input_a.dat" };
chanin input_b with { infile = "input_b.dat" };
chanout output with { outfile = "output.dat" };


//  main()
//  ------------------------------------------------------------------
/*
 *    Do an endless stream of multiplicatins
 */
  void main( void )
  {
    par
    {
      //  Get A values
      while ( TRUE )
      {
        input_a ? a[0];
      }
      
      //  Get B values
      while ( TRUE )
      {
        input_b ? b[0];
      }

      //  Output products until end of simulated input files
      do
      {
        output ! sum[pipeline_depth - 1];
      } while ( (a[0] != 0) || (b[0] != 0) );

      //  The pipeline
      while ( TRUE )
      {
        par
        {
          sum[0] = ((b[0][0] == 0) ? 0 : 0@a[0]);
          par (i = 1; i < pipeline_depth; i++ )
          {
            stage( i );
          }
        }
      }
    }
  }
#endif


//  Evaluation Version
//  ==================================================================
#if (defined USE_RC200 || USE_RC200E)

//  Set up I/O through FPGA pins connected to RC200 expansion header

  interface  bus_in( unsigned multiplicand_width input_a ) ina()
    with
    {
      //  ATA IO0 - IO3
      data = { "N1", "M2", "M1", "R2" },
    };
  interface  bus_in( unsigned multiplier_width input_b ) inb()
    with
    {
      //  ATA IO4 - IO7
      data = { "M3", "P2", "P1", "N2" },
    };
  interface  bus_out() out( unsigned product_width out_c = sum[pipeline_depth - 1] )
    with
    {
      //  ATA IO8 - IO15
      data = { "T2", "R4", "R3", "P3", "P4", "N4", "N3", "M4" },
    };


//  main()
//  ------------------------------------------------------------------
/*
 *    Do an endless stream of multiplicatins
 */
  void main( void )
  {
    par
    {
      //  Get A values
      while ( TRUE )
      {
        a[0] = 0@ina.input_a;
      }
      
      //  Get B values
      while ( TRUE )
      {
        b[0] = inb.input_b;
      }

      //  The pipeline
      while ( TRUE )
      {
        par
        {
          sum[0] = ((b[0][0] == 0) ? 0 : a[0]);
          par (i = 1; i < pipeline_depth; i++ )
          {
            stage( i );
          }
        }
      }
    }
  }