wiki:UnconventionalHDLProgramming

Version 1 (modified by nakasato, 14 years ago) (diff)

--

VHDLの生成

FP加算器のclass定義

class FPadd < FPop
  def initialize(nf = 32, nm = 23)
    super(nf, nm, 4)
    @narg = 3
    @name = gen_name(:add)

    @nadder = nm + 1 + 3 + 1
    @swap   = addcomponent Swap.new(nf)
    @rshift = addcomponent Rshift.new(nm+1,@nexp+1)
    @sbit   = addcomponent Extractsbit.new(nm+1, @nexp+1)

    @sadd   = addcomponent INTsadder.new(@nadder+1) ## 2
    @test   = addcomponent FPaddtest.new(nf, nm, @nadder) ## 1
    @uflow  = addcomponent Underflow.new(@nman+1,@nexp)

    @delay1 = addcomponent(Delay.new(1,2))
    @delay2 = addcomponent(Delay.new(@nexp,2))

    @delay3 = addcomponent(Delay.new(1,3))
    @delay4 = addcomponent(Delay.new(@nexp,3))
    @delay5 = addcomponent(Delay.new(@nexp+1,3))
    if @nexp == @nman then
      @delay6 = @delay5
    else
      @delay6 = addcomponent(Delay.new(@nman+1,3))
    end
  end

  def run
    super('float_add.vhd.erb')
  end
end

FP加算器のソース

-------------------------------------------------------------------------------
% defineIO :in,  :x,   @nfloat
% defineIO :in,  :y,   @nfloat
% defineIO :out, :z,   @nfloat
% defineIO :in,  :clk, 1
-------------------------------------------------------------------------------
% nfloat = @nfloat
% nman = @nman
% nexp = @nexp
%
% width_nf = "#{nfloat-1} downto 0"
% width_nm = "#{nman-1} downto 0"
% width_ne = "#{nexp-1} downto 0"
-------------------------------------------------------------------------------
<%= generate_header %>

<%= generate_entity %>

architecture source of <%= @name %> is

<%= generate_components %>

signal signz,sz : std_logic;
signal manz,mz : std_logic_vector(<%= nman %> downto 0);
signal expz,ez : std_logic_vector(<%= width_ne %>);
signal ex0, ey0            : std_logic_vector(<%= nexp %> downto 0);

signal xx, yy : std_logic_vector(<%= width_nf %>);
signal sx, sy : std_logic;
signal mx, my : std_logic_vector(<%= nman %> downto 0);
signal ex, ey : std_logic_vector(<%= width_ne %>);

signal dx   : std_logic_vector(<%= nexp %> downto 0);
signal dy   : std_logic_vector(<%= nexp %> downto 0);
signal diff : std_logic_vector(<%= nexp %> downto 0);

--
signal res0   : std_logic_vector(<%= nman %> downto 0);
signal expz0  : std_logic_vector(<%= width_ne %>);
signal signz0 : std_logic;
signal ulp0, rbit0, sbit0 : std_logic;

signal res1   : std_logic_vector(<%= nman %> downto 0);
signal expz1  : std_logic_vector(<%= width_ne %>);
signal signz1 : std_logic;
signal ulp1, rbit1, sbit1 : std_logic;

--
signal o1 : std_logic_vector(<%= @nadder - 1 %> downto 0);
signal o2 : std_logic_vector(<%= @nadder - 1 %> downto 0);
signal r1, r2, r3 : std_logic;

signal a0, a1 : std_logic_vector(<%= @nadder %> downto 0);
signal b0, b1 : std_logic_vector(<%= @nadder %> downto 0);
signal res : std_logic_vector(<%= @nadder %> downto 0);
signal resn : std_logic_vector(<%= @nadder %> downto 0);

signal zf   : std_logic;

--
signal dd : std_logic_vector(<%= nexp + 1 %> downto 0);
signal d0 : std_logic_vector(<%= nexp + 1 %> downto 0);
signal manzz : std_logic_vector(<%= nman %> downto 0);
signal expzz : std_logic_vector(<%= width_ne %>);
signal ulp, rbit, sbit : std_logic;

signal zz : std_logic_vector(<%= width_nf %>);

signal expz0_reg   : std_logic_vector(<%= width_ne %>);
signal expz0_regg  : std_logic_vector(<%= width_ne %>);
signal r1_reg, r2_reg, r3_reg : std_logic;
signal diff_reg : std_logic_vector(<%= nexp %> downto 0);
signal res0_reg   : std_logic_vector(<%= nman %> downto 0);
signal signz0_reg : std_logic;
signal signz1_reg : std_logic;
signal ulp0_reg, rbit0_reg, sbit0_reg : std_logic;
signal zf_reg : std_logic;

begin
  ex0 <= '0'&x(<%= nfloat - 2 %> downto <%= nman %>);
  ey0 <= '0'&y(<%= nfloat - 2 %> downto <%= nman %>);

  dx <= ex0 - ey0;
  dy <= ey0 - ex0;

-- swap
  s0 : <%= @swap %> port map ( f => dx(<%= nexp %>), x => x, y => y, xs => xx, ys => yy);

  with dx(<%= nexp %>) select
    diff <= dy when '1',
            dx when others;

  e0 : <%= @fextract %> port map ( x => xx, s => sx, m => mx, e => ex);
  e1 : <%= @fextract %> port map ( x => yy, s => sy, m => my, e => ey);

--------------------------------------------------------------------
-- if diff > <%= nman + 1 %>
  res0 <= mx;
  expz0  <= ex;
  signz0 <= sx;
  ulp0  <= res0(0);
  rbit0 <= '0';
  sbit0 <= '1';
-- else
-- o1
  o1 <= "00"&mx&"00";

-- o2
  shift0 : <%= @rshift %> port map (c => diff, i => my, o => o2);

  r1 <= o2(1);
  r2 <= o2(0);

-- r3
  sb0 : <%= @sbit %> port map (c => diff, i => my, s => r3);

----
  a0 <= o1(<%= @nadder - 1 %> downto 0)&'0';
  b0 <= o2(<%= @nadder - 1 %> downto 0)&r3;

--
  add: <%= @sadd %> port map (x => a0, sx => sx, y => b0, sy => sy,
                              z => resn, sz => signz1, clk => clk);

  d1 : <%= @delay1 %> port map (i => r1, o => r1_reg, clk => clk);
  d2 : <%= @delay1 %> port map (i => r2, o => r2_reg, clk => clk);
  d3 : <%= @delay1 %> port map (i => r3, o => r3_reg, clk => clk);
  d4 : <%= @delay2 %> port map (i => expz0, o => expz0_reg, clk => clk);

-- flag zf if res == 0
  with resn select
    zf <= '1' when "<%= 0.to_b(@nadder+1) %>",
          '0' when others;
----
  f0 : <%= @test %> port map ( tmp => resn(<%= @nadder - 1 %> downto 0),
                               exp => expz0_reg, r1 => r1_reg, r2 => r2_reg, r3 => r3_reg,
                               res => res1, expz => expz1, ulp => ulp1, rbit => rbit1, sbit => sbit1, clk => clk);

  process(clk) begin
   if(clk'event and clk='1') then
     signz1_reg <= signz1;
     zf_reg <= zf;
   end if;
  end process;

--sadd 2   signz1, resn
--test 3   res1, expz1, ulp1, rbit1, sbit1

  d5  : <%= @delay3 %> port map (i => signz0, o => signz0_reg, clk => clk);
  d6  : <%= @delay3 %> port map (i => ulp0,  o => ulp0_reg, clk => clk);
  d7  : <%= @delay3 %> port map (i => rbit0, o => rbit0_reg, clk => clk);
  d8  : <%= @delay3 %> port map (i => sbit0, o => sbit0_reg, clk => clk);
  d9  : <%= @delay4 %> port map (i => expz0, o => expz0_regg, clk => clk);
  d10 : <%= @delay5 %> port map (i => diff, o => diff_reg, clk => clk);
  d11 : <%= @delay6 %> port map (i => res0, o => res0_reg, clk => clk);

--------------------------------------------------------------------
  d0 <= '0'&diff_reg;
  dd <= "<%= (nman + 1).to_b(nexp+1) %>" - d0;

  uf : <%= @uflow %> port map (f => dd(<%= nexp %>),
                               m1 => res0_reg, e1 => expz0_regg, u1 => ulp0_reg, r1 => rbit0_reg, s1 => sbit0_reg,
                               m2 => res1,     e2 => expz1,      u2 => ulp1,     r2 => rbit1,     s2 => sbit1,
                               m => manzz, e => expzz, u => ulp, r => rbit, s => sbit );

  with dd(<%= nexp %>) select
    signz <= signz0_reg when '1',
             signz1_reg when others;

  r0 : <%= @frounding %> port map ( m => manzz, e => expzz, u => ulp, r => rbit, s => sbit,
                                   mout => manz, eout=> expz);

  with zf_reg select
    sz <= signz when '0',
          '0' when others;

  with zf_reg select
    mz <= manz when '0',
          "<%= 0.to_b(@nman+1) %>" when others;

  with zf_reg select
    ez <= expz when '0',
          "<%= 0.to_b(@nexp) %>" when others;

  c0 : <%= @fcompose %> port map (s => sz, m => mz, e => ez, z => z, clk => clk);
end source;
-------------------------------------------------------------------------------
<%= generate_components_body %>
-------------------------------------------------------------------------------