Lehre.EDS_ProgF6 (Struktur)


Beispielprogramme zu Foliensatz EDS-F6

CORDIC

  • Octave- (Matlab-) Programm zur Generierung der Konstantenvereinbarungen (Gleitkommadarstellung):
  • % Foliensatz EDS-F6, Abschnitt 1.2 CORDIC. Simulation des Algorithmus.
    % Matlab/Octave-Programm gen_const_real.m zur Erzeugung der Konstanten
    % letzte Aenderung: 29.06.2016
    % Autor: G. Kemnitz
    
    % Erzeugung der Konstantentabelle
    N=16;
    SCS = 1;
    printf('constant AtanTab: t_dat_array(0 to %d) := (', N-1);
    for idx=0:N-1
     atan_idx = atan(1.0*2^-idx);
     printf('%10.9f', atan_idx);
     if idx<N-1 printf(', ');
     else       printf(');\n');
     end;
     SCS = SCS * cos(atan_idx);
    end;
    printf('constant SCS: t_dat := %10.9f;\n', SCS);
    
    %Erzeugung der Testbeispiele
    N_test = 21;
    printf('constant test_dat: t_test_dat(1 to %d) := (\n', N_test);
    for idx=1:N_test
     phi = pi * (idx-11)/20;
     printf('%5d=>(%8.5f, %8.5f, %8.5f)', idx, phi, sin(phi), cos(phi)); 
     if idx<N_test printf(',\n');
     else          printf(');\n');
     end;
    end; 
    
    
  • Octave- (Matlab-) Programm zur Generiering der Konstantenvereinbarung (Festkommadarstellung):
  • % Foliensatz EDS-F6, Abschnitt 1.2 CORDIC. Simulation des Algorithmus.
    % Matlab/Octave-Programm gen_const_real.m zur Erzeugung der Konstanten
    % letzte Aenderung: 29.06.2016
    % Autor: G. Kemnitz
    
    % Erzeugung der Konstantentabelle
    N=15;
    SCS = 1;
    printf('constant AtanTab: t_dat_array(0 to %d) := (\n', N-1);
    for idx=0:N-1
     atan_idx = atan(1.0*2^-idx);
     printf('    x"%04x"', round(atan_idx*2^14));
     if idx<N-1 printf(', -- %6.5f\n', atan_idx);
     else       printf(');-- %6.5f\n', atan_idx);
     end;
     SCS = SCS * cos(atan_idx);
    end;
    printf('constant SCS: t_dat := x"%04x"; -- %6.4f\n', round(SCS*2^14), SCS);
    
    %Erzeugung der Testbeispiele
    N_test = 21;
    printf('constant test_dat: t_test_dat(1 to %d) := (\n', N_test);
    for idx=1:N_test
     w = pi * (idx-11)/20;
     v = 2^14 * w;      if v<0 v=v+2^16; end;
     s = 2^14 * sin(w); if s<0 s=s+2^16; end;
     c = 2^14 * cos(w); if c<0 c=c+2^16; end;
     printf('%5d=>(x"%04x", x"%04x", x"%04x")', idx, v, s, c); 
     if idx<N_test printf(', ');
     else          printf(');');
     end;
     printf(' --(%8.5f, %8.5f, %8.5f)\n', w, sin(w), cos(w));
    end; 
    
    
    
    
  • Package für die Simulation mit Gleitkommazahlen:
  • -- Foliensatz EDS-F6, Abschnitt 1.2 CORDIC. Simulation des Algorithmus.
    -- Package cordic_real_pack.vhd
    -- letzte Aenderung: 20.05.2016
    -- Autor: G. Kemnitz
    
    package cordic_real_pack is
     subtype t_dat is real range -2.0 to 2.0; 
     type t_dat_array is array (natural range <>) of t_dat;
     type t_test is record phi:t_dat; sin:t_dat; cos:t_dat; end record;
     type t_test_dat is array (natural range <>) of t_test;
    
     function str(x: t_dat) return string;
     function "sra"(a: t_dat; b: natural) return t_dat;
     
    
    constant AtanTab: t_dat_array(0 to 15) := (0.785398163, 
               0.463647609, 0.244978663, 0.124354995, 
               0.062418810, 0.031239833, 0.015623729, 
               0.007812341, 0.003906230, 0.001953123, 
               0.000976562, 0.000488281, 0.000244141, 
               0.000122070, 0.000061035, 0.000030518);
    constant SCS: t_dat := 0.607252935;
    
    
    constant test_dat: t_test_dat(1 to 21) := (
        1=>(-1.57080, -1.00000,  0.00000),
        2=>(-1.41372, -0.98769,  0.15643),
        3=>(-1.25664, -0.95106,  0.30902),
        4=>(-1.09956, -0.89101,  0.45399),
        5=>(-0.94248, -0.80902,  0.58779),
        6=>(-0.78540, -0.70711,  0.70711),
        7=>(-0.62832, -0.58779,  0.80902),
        8=>(-0.47124, -0.45399,  0.89101),
        9=>(-0.31416, -0.30902,  0.95106),
       10=>(-0.15708, -0.15643,  0.98769),
       11=>( 0.00000,  0.00000,  1.00000),
       12=>( 0.15708,  0.15643,  0.98769),
       13=>( 0.31416,  0.30902,  0.95106),
       14=>( 0.47124,  0.45399,  0.89101),
       15=>( 0.62832,  0.58779,  0.80902),
       16=>( 0.78540,  0.70711,  0.70711),
       17=>( 0.94248,  0.80902,  0.58779),
       18=>( 1.09956,  0.89101,  0.45399),
       19=>( 1.25664,  0.95106,  0.30902),
       20=>( 1.41372,  0.98769,  0.15643),
       21=>( 1.57080,  1.00000,  0.00000));
    
    end package;
    
    -- =====================================================
    package body cordic_real_pack is
    
     -- Textkonvertierung für Werte vom Typ t_dat 
     function str(x: t_dat) return string is
      variable s: string(1 to 7);
      variable v: t_dat := x;
     begin
      assert x>=-2.0 and x<=2.0 severity failure;
      if x<0.0 then
       s := integer'image(integer(1.0E4*(100.0-v)));
       s(1) := '-';
      else
       s := integer'image(integer(1.0E4*(100.0+v)));
       s(1) := '+';
      end if;
      s(2 to 3) := s(3) & ',';
      return s;
     end function;
    
     -- sra-Operator fuer t_dat
     function "sra"(a: t_dat; b: natural) return t_dat is
     begin
      return a/(2.0**b);
     end function;
    
    end package body;
    
  • Package für die Simulation mit Festkommazahlen:
  • -- Foliensatz EDS-F6, Abschnitt 1.3 CORDIC. Umstellung auf Festkommazahlen.
    -- Package cordic_fix_pack.vhd
    -- letzte Aenderung: 20.05.2016
    -- Autor: G. Kemnitz
    
    library ieee;
    use ieee.numeric_std.all;
    use ieee.std_logic_1164.all;
    
    package cordic_fix_pack is
     subtype t_dat is signed(15 downto 0); 
     type t_dat_array is array (natural range <>) of t_dat;
     type t_test is record phi:t_dat; sin:t_dat; cos:t_dat; end record;
     type t_test_dat is array (natural range <>) of t_test;
    
     function str(x: t_dat) return string;
     function "sra"(a: t_dat; b: natural) return t_dat;
     function mult_scs(a: t_dat) return t_dat;
    
     constant AtanTab: t_dat_array(0 to 14) := (
        x"3244", -- 0.78540
        x"1dac", -- 0.46365
        x"0fae", -- 0.24498
        x"07f5", -- 0.12435
        x"03ff", -- 0.06242
        x"0200", -- 0.03124
        x"0100", -- 0.01562
        x"0080", -- 0.00781
        x"0040", -- 0.00391
        x"0020", -- 0.00195
        x"0010", -- 0.00098
        x"0008", -- 0.00049
        x"0004", -- 0.00024
        x"0002", -- 0.00012
        x"0001");-- 0.00006
    	
    constant SCS: t_dat := x"26dd";      -- 0.6073
    constant const_0: t_dat := x"0000";  -- 0.0
    constant const_1: t_dat := x"4000";  -- 1.0
    
    constant test_dat: t_test_dat(1 to 21) := (
        1=>(x"9b78", x"c000", x"0000"),  --(-1.57080, -1.00000,  0.00000)
        2=>(x"a585", x"c0c9", x"0a03"),  --(-1.41372, -0.98769,  0.15643)
        3=>(x"af93", x"c321", x"13c6"),  --(-1.25664, -0.95106,  0.30902)
        4=>(x"b9a0", x"c6f9", x"1d0e"),  --(-1.09956, -0.89101,  0.45399)
        5=>(x"c3ae", x"cc39", x"259e"),  --(-0.94248, -0.80902,  0.58779)
        6=>(x"cdbc", x"d2be", x"2d41"),  --(-0.78540, -0.70711,  0.70711)
        7=>(x"d7c9", x"da61", x"33c6"),  --(-0.62832, -0.58779,  0.80902)
        8=>(x"e1d7", x"e2f1", x"3906"),  --(-0.47124, -0.45399,  0.89101)
        9=>(x"ebe4", x"ec39", x"3cde"),  --(-0.31416, -0.30902,  0.95106)
       10=>(x"f5f2", x"f5fc", x"3f36"),  --(-0.15708, -0.15643,  0.98769)
       11=>(x"0000", x"0000", x"4000"),  --( 0.00000,  0.00000,  1.00000)
       12=>(x"0a0d", x"0a03", x"3f36"),  --( 0.15708,  0.15643,  0.98769)
       13=>(x"141b", x"13c6", x"3cde"),  --( 0.31416,  0.30902,  0.95106)
       14=>(x"1e28", x"1d0e", x"3906"),  --( 0.47124,  0.45399,  0.89101)
       15=>(x"2836", x"259e", x"33c6"),  --( 0.62832,  0.58779,  0.80902)
       16=>(x"3243", x"2d41", x"2d41"),  --( 0.78540,  0.70711,  0.70711)
       17=>(x"3c51", x"33c6", x"259e"),  --( 0.94248,  0.80902,  0.58779)
       18=>(x"465f", x"3906", x"1d0e"),  --( 1.09956,  0.89101,  0.45399)
       19=>(x"506c", x"3cde", x"13c6"),  --( 1.25664,  0.95106,  0.30902)
       20=>(x"5a7a", x"3f36", x"0a03"),  --( 1.41372,  0.98769,  0.15643)
       21=>(x"6487", x"4000", x"0000")); --( 1.57080,  1.00000,  0.00000)
    
    end package;
    
    -- =====================================================
    package body cordic_fix_pack is
    
     -- Textkonvertierung für Werte vom Typ t_dat 
     function str(x: t_dat) return string is
      variable s: string(1 to 7);
      variable v: real := real(to_integer(x))/2.0**14;
     begin
      --report("*** v=" & real'image(v));
      assert v>=-20.0 and v<=20.0 severity failure;
      if v<0.0 then
       s := integer'image(integer(1.0E4*(100.0-v)));
       s(1) := '-';
      else
       s := integer'image(integer(1.0E4*(100.0+v)));
       s(1) := '+';
      end if;
      s(2 to 3) := s(3) & ',';
      return s;
     end function;
    
     -- sra-Operator fuer t_dat
     function "sra"(a: t_dat; b: natural) return t_dat is
      variable y: t_dat := (others=>a(15));
     begin
      assert b<16;
      y(15-b downto 0) := a(15 downto b);
      return y;
     end function;
    
     function mult_scs(a: t_dat) return t_dat is
      variable p: signed(31 downto 0) := a * SCS;
     begin
      return t_dat(p(29 downto 14));
     end function;
    
    end package body;
    
  • Simulationsmodell für den Algorithmus mit Gleitkommazahlen:
  • -- Foliensatz EDS-F6, Abschnitt 1.2 CORDIC. Simulation des Algorithmus.
    -- Programm test_cordic_real.vhd
    -- letzte Aenderung: 21.03.2018
    -- Autor: G. Kemnitz
    
    -- Simmulation mit Textausgabe:
    -- ghdl -a cordic_real_pack.vhd
    -- ghdl -a test_cordic_real.vhd
    -- ghdl -m test_cordic_real
    -- ghdl -r test_cordic_real
    
    use work.cordic_real_pack.all;
    
    entity test_cordic_real is end entity;
    
    architecture a of test_cordic_real is
      signal x, y, c, s, phi, phi_z: t_dat;
    begin
     process
      variable test: t_test;
     begin
      report(" Winkel (Delta)|Kosinus (Delta)|  Sinus (Delta)");
      for tnr in test_dat'range loop
       test := test_dat(tnr);
       phi_z <= test.phi;
       x<=1.0; y<=0.0; phi<=0.0;
       wait for 10 ns;
       for i in AtanTab'range loop
        if phi_z > phi then
         x <= x - (y sra i);  
         y <= y + (x sra i);
         phi<=phi + AtanTab(i);
        else
         x <= x + (y sra i);  
         y <= y - (x sra i);
         phi <= phi - AtanTab(i);
        end if;
        wait for 10 ns;
       end loop;
       c <= SCS * x; s <= SCS  *y; 
       wait for 10 ns;
    
       report(str(phi_z) & " " & str(phi_z-test.phi)
             & "|" & str(c)     & " " & str(c-test.cos)
             & "|" & str(s)     & " " & str(s-test.sin));
      end loop;
      wait;
     end process;
    end architecture;
    
  • Umstellung auf Festkommazahlen:
  • -- Foliensatz EDS-F6, Abschnitt 1.3 CORDIC. Umstellung auf Festkommazahlen.
    -- Programm test_cordic_real.vhd
    -- letzte Aenderung: 21.03.2018
    -- Autor: G. Kemnitz
    
    -- Simmulation mit Textausgabe:
    -- ghdl -a cordic_fix_pack.vhd
    -- ghdl -a test_cordic_fix.vhd
    -- ghdl -m test_cordic_fix
    -- ghdl -r test_cordic_fix
    
    use work.cordic_fix_pack.all;
    library ieee;
    use ieee.numeric_std.all;
    
    entity test_cordic_fix is end entity;
    
    architecture a of test_cordic_fix is
      signal x, y, c, s, phi, phi_z: t_dat;
    begin
     process
      variable test: t_test;
     begin
      report(" Winkel (Delta)|Kosinus (Delta)|  Sinus (Delta)");
      for tnr in test_dat'range loop
       test := test_dat(tnr);
       phi_z <= test.phi;
       x<=const_1; y<=const_0; phi<=const_0;
       wait for 10 ns;
       for i in AtanTab'range loop
        if phi_z > phi then
         x <= x - (y sra i);
         y <= y + (x sra i);
         phi<=phi + AtanTab(i);
        else
         x <= x + (y sra i);  
         y <= y - (x sra i);
         phi <= phi - AtanTab(i);
        end if;
    	wait for 10 ns;
       end loop;
       c <= mult_scs(x); s <= mult_scs(y); 
       wait for 10 ns;
    
       report(str(phi_z) & " " & str(phi_z-test.phi)
             & "|" & str(c)     & " " & str(c-test.cos)
             & "|" & str(s)     & " " & str(s-test.sin));
      end loop;
      wait;
     end process;
    end architecture;
    
  • Synthesefähiges Cordic-Rechenwerk:
  • -- Foliensatz EDS-F6, Abschnitt 1.4 CORDIC. Entwurf als Rechenwerk.
    -- Programm: cordic.vhd
    -- letzte Aenderung: 08.07.2016
    -- Autor: G. Kemnitz
    
    use work.cordic_fix_pack.all;
    library ieee;
    use ieee.numeric_std.all;
    use ieee.std_logic_1164.all;
    
    entity cordic is 
     port(
      T, I, Start: in std_logic;
      w: in t_dat;
      busy: out std_logic;
      s, c: out t_dat);
    end entity;
    
    architecture a of cordic is
     type t_state is (ws, cordic_op, m1, m2);
     signal state: t_state;
     signal ct: natural range(AtanTab'range);
     signal x, y, phi, phi_z: t_dat;
    begin
     process (T)
     begin
      if I='1' then
       state <= ws;
      elsif rising_edge(T) then
       case state is
        when ws =>     -- warte auf Start
         if Start = '1' then 
          ct <= AtanTab'low; phi<=const_0;
          x<=const_1; y<=const_0;
          state <= cordic_op; phi_z <= w;
         end if;
        when cordic_op =>
         if phi_z > phi then
          x <= x - (y sra ct);  
          y <= y + (x sra ct);
          phi<=phi + AtanTab(ct);
        else
         x <= x + (y sra ct);  
         y <= y - (x sra ct);
         phi <= phi - AtanTab(ct);
        end if;
        if ct=AtanTab'high-1 then state <= m1; 
        else ct <= ct +1; end if;
       when m1 => -- Abschlussmultiplikation Kosinus
        c <= mult_scs(x); state <= m2;
       when m2 => -- Abschlussmultiplikation Sinus	
    	s <= mult_scs(y); state <= ws;
       end case;
      end if;
     end process;
     
     process (state) begin
      if state=ws then busy <= '0';
      else             busy <= '1';
      end if;
     end process;
    end architecture;
    
  • Testrahmen für das Cordic-Rechenwerk:
  • -- Foliensatz EDS-F6, Abschnitt 1.4 CORDIC. Entwurf als Rechenwerk.
    -- Programm test_cordic.vhd
    -- letzte Aenderung: 08.07.2016
    -- Autor: G. Kemnitz
    
    -- Simmulation mit Textausgabe:
    -- ghdl -a cordic.vhd
    -- ghdl -a test_cordic.vhd
    -- ghdl -m test_cordic
    -- ghdl -r test_cordic --wave=test_cordic.ghw
    -- gtkview test_cordic.ghw test_cordic.sav
    
    
    
    use work.cordic_fix_pack.all;
    library ieee;
    use ieee.std_logic_1164.all;
    
    
    entity test_cordic is end entity;
    
    architecture a of test_cordic is
     signal T, I, Start, busy: std_logic := '0';
     signal w, s, c: t_dat;
    begin
     uut: entity work.cordic port map(T=>T, I=>I, 
     Start=>Start, busy=>busy, w=>w, s=>s, c=>c);
      
     process
     begin
      I <= '1', '0' after 20 ns;
      while now < 1 us loop
       wait for 5 ns; T <= not T;
      end loop;
      wait;
     end process;
     
     process
      variable test: t_test;
     begin
      for tnr in test_dat'range loop
       wait until busy='0'; wait for 3 ns;
       start<='1'; test:=test_dat(tnr);
       w <= test.phi; 
       wait until busy = '1';
       wait for 6 ns;
       start<='0';
      end loop;
      wait;
     end process;
    end architecture;
    
    

Minimalprozessor (MiPro)

  • Package mit den ausgabenspezifischen Datentypen und Funktionen:
  • -- Foliensatz RA-F1, Abschnitt ?.?
    -- Testrahmen fuer den Minimalprozessor
    -- letzte Aenderung: 21.03.2018
    -- Autor: G. Kemnitz
    
    package mipro_pack is
    
     -- Instruction set                          || format / built function
     type t_cmd is (noop,                        -- nop
                   jump,                         -- jump(imm8, cond:=non)
                   call, load, stor, ld_i, comp, -- cmd(<cmd> rd, imm8)
                   cmpc, addi, adci, subi, sbci,
                   andi, or_i, xori,
                   retu,                         -- ret(rd)
                   move, ld_r, st_r, sh_l, sh_r, -- cmd(<cmd> rd ra)
                   rotl, rotr, notr, 
                   addr, adcr, subr, sbcr,       -- cmd(<cmd> rd ra rb)
                   andr, or_r, xorr);
     
    -- register definition
     type t_reg is (r0, r1, r2, r3, r4, r5, r6, r7);
    -- jump condition
     type t_cond is (nev, -- junp never  
                     alw, -- jump allways
                     gth, -- jump greater than        (cy=1)
                     leq, -- jump if less or equal    (cy=0)
                     equ, -- jump if equal            (z =1)
                     neq, -- jump if not equal        (z =0) 
                     geq, -- jump if greater or equal (cy=1 or  z=1) 
                     lth);-- jump if less than        (cy=0 and z=0) 
    
     type t_imem is array (natural range<>) of bit_vector(15 downto 0);
     type t_dmem is array (natural range<>) of bit_vector(7 downto 0);
    
     type t_proc_state is record
      PC  : bit_vector( 7 downto 0); -- Program Counter
      IReg: bit_vector(15 downto 0); -- Instruction Register
      cy:   bit;                     -- cary flag
      z:    bit;                     -- zero flag
      RSet: t_dmem(0 to 7);          -- Register Set
     end record;
    
     constant c_proc_state: string :=
     "PC|Befehl assem.: hex|r0 r1 r2 r3 r4 r5 r6 r7|c|z|";
    
    -- ========= string conversion ===============================================
    -- data => hex. strings, e.g. 6F
     function hex(dat: bit_vector) return string;
    
     -- sector of data memeory => to string of hex. numbers
    -- e.g. A3 56 12 9A 43 19 7B CA
     function str(w: t_dmem) return string; 
    
     -- register adress, notation r<nr>, e.g. r4
     function str_reg(w:bit_vector(2 downto 0)) return string;
    
     -- instruction in assemly language, e.g. addc r1 r4 r5
     function str_ir(w: bit_vector(15 downto 0)) return string;
    
    -- processor state (length 55 character), e.g.
    --PC | Befehl assem.: hex | r0 r1 r2 r3 r4 r5 r6 r7 |c|z|
    --03 | ld_i r3,13,..:2A13 | A3 56 12 9A 43 19 7B CA |0|1| 
     function str(ps: t_proc_state) return string;
    
    -- ==========function to built binary machine instructions====================
    -- no operation instruction is a constant
     constant nop:bit_vector(15 downto 0) := x"0000";
    
     -- jump instructions has target adress and condition as operands
     function jmp(tgadr: bit_vector(7 downto 0); cond: t_cond:=alw) return bit_vector;
    
     -- instructions with one register adress und an 8 bit imidiate value
     function cmd(w: t_cmd; rd:t_reg; imm: bit_vector(7 downto 0)) return bit_vector;
    
     -- instructions with one to three registers adresses
     function cmd(w: t_cmd; rd:t_reg; ra, rb: t_reg:=r0) return bit_vector;
    
    -- =========convertion from t_reg to bit_vector===============================
     function reg(w: t_reg) return bit_vector;
    
    -- =========convertion from bit_vector to unsigned integer====================
     function uint(w: bit_vector) return natural;
    
    -- ========= convertion from unsigned integer to bit_vector===================
     function to_bitvec(w: natural; b: positive) return bit_vector;
    
    -- =========addition of two bit vectors and cary ===============================
     function add(a, b: bit_vector(7 downto 0); cy: bit) return bit_vector;
    
    -- ========= increment of a bit vector =======================================
     function inc(a: bit_vector) return bit_vector;
    
    -- ========= test, if bit vector is zero =====================================
      function is_zero(bv: bit_vector(7 downto 0)) return bit;
    
    -- ========= test jump condition =============================================
     function test_jmp_cond(cond: bit_vector(2 downto 0); cy, z: bit) return boolean;
    
    end package;
    -- ===========================================================================
    
    
    package body mipro_pack is
    
    -- ===========================================================================
    -- ========= string conversion ===============================================
    -- data => hex. strings, e.g. 6f
     function hex(dat: bit_vector) return string is
      constant c: string := "0123456789abcdef";
      constant w: bit_vector(dat'length-1 downto 0) := dat;
      variable val, i, j: natural := 0;
      variable k: positive := 1;
      variable s: string(1 to (w'length-1)/4+1) := (others=>'.');
     begin
      while i < w'length loop
       if w(i)='1' then 
        val := val + k;
       end if;
       if k=8 then
        s(s'high-j):=c(val+1);
        j:=j+1; k:=1; val:= 0;
       else
        k:=2*k;
       end if;
       i:=i+1;
      end loop;
      if s'high > j then s(s'high-j):=c(val+1); end if;
      return s;
     end function;
    -- ===========================================================================
    -- sector of data memeory => to string of hex. numbers
    -- e.g. A3 56 12 9A 43 19 7B CA
     function str(w: t_dmem) return string is
      variable s: string(1 to 3*w'length-1) :=(others=>' ');
     begin
      for i in w'low to w'high loop
       s(3*(i-w'low)+1 to 3*(i-w'low)+2) := hex(w(i));
      end loop;
      return s;
     end function;
    -- ===========================================================================
    -- register adress, notation r<nr>, e.g. r4, rx for invalid
     function str_reg(w:bit_vector(2 downto 0)) return string is
     begin
      return 'r' & hex(w);
     end function;
    
    -- ===========================================================================
    -- instruction => assemly language string, e.g. addc r1 r4 r5
     function str_ir(w: bit_vector(15 downto 0)) return string is
      variable s: string(1 to 13) := "xxxx ..,..,..";
      variable inr: natural;
     begin
       inr := uint(w(15 downto 11));
       --report("inr=" & integer'image(inr));
       s(1 to 4) := t_cmd'image(t_cmd'val(inr));
       if inr >=  t_cmd'pos(addr) then           -- addr 
        s( 6 to  7) := str_reg(w(10 downto 8));  -- addr rd
        s( 9 to 10) := str_reg(w( 7 downto 5));  -- addr rd rs 
        s(12 to 13) := str_reg(w( 4 downto 2));  -- addr rd rs rs 
       elsif inr >=  t_cmd'pos(move) then        -- move
        s( 6 to  7) := str_reg(w(10 downto 8));  -- move rd
        s( 9 to 10) := str_reg(w( 7 downto 5));  -- move rd rs 
       elsif inr >=  t_cmd'pos(retu) then        -- retu
        s( 6 to  7) := str_reg(w(10 downto 8));  -- retu rd
       elsif inr >=  t_cmd'pos(call) then        -- call
        s( 6 to  7) := str_reg(w(10 downto 8));  -- call rd
        s( 9 to 10) := hex(w(7 downto 0));       -- call rd imm8 
       elsif inr  =  t_cmd'pos(jump) then        -- jump
        s( 6 to  7) := hex(w(7 downto 0));       -- jump a3
        s( 9 to 11) := t_cond'image(t_cond'val(uint(w(10 downto 8)))); 
       end if; 
      return s;
     end function;
    
     function str(w: bit) return character is
     begin
      if w='0' then return '0';
      else          return '1';
      end if;
     end function;
    -- ===========================================================================
    -- processor state (length 55 character), e.g.
    --PC | Befehl assem.: hex | r0 r1 r2 r3 r4 r5 r6 r7 |c|z|
    --03 | ld_i r3,13,..:2A13 | A3 56 12 9A 43 19 7B CA |0|1| 
     function str(ps: t_proc_state) return string is
     begin
      return hex(ps.PC) & "|" & str_ir(ps.IReg)& ':' & hex(ps.IReg) &  "|" & str(ps.RSet)
           & "|" & str(ps.cy) & "|" & str(ps.z) & "|";
     end function;
    -- ===========================================================================
    -- ==========function to built binary machine instructions====================
    -- jump instructions has target adress and condition as operands
     function jmp(tgadr: bit_vector(7 downto 0); cond: t_cond:=alw) return bit_vector is
     begin
      --report("jump");
      return to_bitvec(t_cmd'pos(jump), 5) & 
             to_bitvec(t_cond'pos(cond), 3) & tgadr;
     end function;
    -- ===========================================================================
    -- instructions with one register adress und an 8 bit imidiate value
     function cmd(w: t_cmd; rd:t_reg; imm: bit_vector(7 downto 0)) return bit_vector is
      variable n: natural := t_cmd'pos(w);
     begin
      assert n >= t_cmd'pos(call) and  n <= t_cmd'pos(xori)
      report t_cmd'image(w) & " not format cmd rd imm8"
      severity failure;
      --report(t_cmd'image(w));
      return to_bitvec(t_cmd'pos(w), 5)  &
             to_bitvec(t_reg'pos(rd), 3) & imm;
     end function;
    -- ===========================================================================
    -- instructions with one to three registers adresses
     function cmd(w: t_cmd; rd:t_reg; ra, rb: t_reg:=r0) return bit_vector is
      variable n: natural := t_cmd'pos(w);
     begin
      assert  n >= t_cmd'pos(retu)
      report t_cmd'image(w) & " not format cmd rd [rs [rs]]"
      severity failure;
      --report(t_cmd'image(w));
      return to_bitvec(t_cmd'pos(w  ), 5) &  
             to_bitvec(t_reg'pos(rd ), 3) &
             to_bitvec(t_reg'pos(ra), 3) &
             to_bitvec(t_reg'pos(rb), 3) & "00";
     end function;
    -- ===========================================================================
    -- =========convertion from t_reg to bit_vector===============================
     function reg(w: t_reg) return bit_vector is
     begin 
      return to_bitvec(t_reg'pos(w), 3);
     end function;
    
    -- ========= convertion from bit_vector to unsigned integer===================
     function uint(w: bit_vector) return natural is
      variable n: natural;
      variable bv: bit_vector(w'length-1 downto 0) := w;
     begin
      for idx in 0 to bv'high loop
       if bv(idx)='1' then
        n := n + (2**idx);
       end if;
      end loop;
      return n;
     end function;
    
    -- ========= convertion from unsigned integer to bit_vector===================
     function to_bitvec(w: natural; b:positive) return bit_vector is
      variable bv: bit_vector(b-1 downto 0);
      variable s: string(b-1 downto 0):=(others=>'0');
      variable val: natural := w;
     begin
      --report("w=" & integer'image(w) & " 2**b=" & integer'image(2**b));
      assert w < (2**b)
      report "w=" & integer'image(w) & " too large for bv(" & integer'image(b-1) & " downto 0)"
      severity failure;
      for idx in 0 to b-1 loop
       if (val rem 2) = 1 then
        bv(idx) := '1';
        s(idx)  :=  '1';
       end if;
       val := val/2;
       --report("val=" & integer'image(val) & " bv=" & s);
      end loop;
      return bv;
     end function;
      
    -- =========addion of two bit vector with cary ===============================
     function add(a, b: bit_vector(7 downto 0); cy: bit) return bit_vector is
      variable c: bit := cy;
      variable s: bit_vector(7 downto 0);
     begin
      for idx in  0 to 7 loop
       s(idx) := a(idx) xor b(idx) xor c;
       c := (a(idx) and b(idx)) or (c and (a(idx) or b(idx)));
       -- report("idx=" & integer'image(idx) & 
                                           -- " a(idx)=" & bit'image(a(idx)) & 
                                           -- " b(idx)=" & bit'image(b(idx)) & 
                                           -- " c_out="  & bit'image(c) & 
                                           -- " s(idx)=" & bit'image(s(idx)));
      end loop;
      return c & s;
     end function;
    
    -- ========= increment of a bit vector =======================================
     function inc(a: bit_vector) return bit_vector is
      variable s: bit_vector(a'length-1 downto 0);
      variable c: bit:='1';
     begin
      assert a'right = 0
      report "a is not bit_vector(n downto 0)"
      severity failure;
      for idx in  0 to s'high loop
       s(idx) := a(idx) xor c;
       c := a(idx) and c;
      end loop;
      return s;
     end function;
    
    -- ========= test, if bit vector is zero =====================================
      function is_zero(bv: bit_vector(7 downto 0)) return bit is
       variable z: bit :='1';
      begin
       for idx in 0 to bv'high loop
        if bv(idx) = '1' then z := '0';
        end if;
       end loop;
       return z;
      end function;
    
    -- ========= test jump condition =============================================
     function test_jmp_cond(cond: bit_vector(2 downto 0); cy, z: bit) return boolean is
     begin
      return (cond(0) xor ((cond(1) and cy) or (cond(2) and z)))='1';
     end function;
    
    end package body;
    
    
  • Beschreibung des Prozessors:
  • -- Foliensatz RA-F1, Abschnitt ?.?
    -- Funktionsbeschreibung des Minimalprozessors
    -- letzte Aenderung: 21.03.2018
    -- Autor: G. Kemnitz
    
    use work.mipro_pack.all;
    
    entity mipro is
     port (
      T, I: bit;
      imem: in t_imem;
      dmem: inout t_dmem;
      trace: out t_proc_state;
      dmem_wr: out boolean);
    end entity;
     
    architecture a of mipro is
    begin
    
     process(T, I)
      variable cmd: t_cmd;
      variable res: bit_vector(8 downto 0);
      variable imm, PC: bit_vector(7 downto 0);
      variable cond: bit_vector(2 downto 0);
      variable rd, ra, rb: natural range 0 to 7;
      variable ps: t_proc_state;
      type t_res_type is (non, rcz, rncz, ncz, rz);
      variable res_type: t_res_type;
    
     begin
      if I='1' then
       ps.PC := x"00";
      elsif T'event and T='1' then
      
       -- Befehlswort holen und in Bestandteile aufteilen
       ps.IReg := imem(uint(ps.PC)); 
       PC  := inc(ps.PC);
       cmd := t_cmd'val(uint(ps.IReg(15 downto 11)));
       cond:= ps.IReg(10 downto 8);
       rd  := uint(ps.IReg(10 downto 8));
       ra  := uint(ps.IReg( 7 downto 5));
       rb  := uint(ps.IReg( 4 downto 2));
       imm := ps.IReg( 7 downto 0);
    
       -- Fallunterscheidung nach Befehl  
       dmem_wr <=false;   
       res_type := non;
       case cmd is  
         -- branch instructions
         when jump  => 
          if test_jmp_cond(cond, ps.cy, ps.z) then
           PC := imm;
          end if;
         when call => 
          ps.RSet(rd) := PC;
          PC  := imm;
         when retu =>  
          PC  := ps.RSet(rd);
    	  
         -- load, store and move instruction
         when load => -- load from constant adress
    	  ps.RSet(rd) := dmem(uint(imm));
    	  --report("load:" & str(ps) & "rd:" & integer'image(rd));
         when ld_r => -- load from variable adress
    	  ps.RSet(rd) := dmem(uint(ps.RSet(ra)));
    	  --report("ld_i:" & str(ps));
         when ld_i => -- load constant
    	  ps.RSet(rd) := imm;
         when stor => -- load from constant adress
    	  dmem(uint(imm)) <= ps.RSet(rd); dmem_wr <= true;
         when st_r => -- load from variable adress
    	  dmem(uint(ps.RSet(ra))) <= ps.RSet(rd); dmem_wr <= true;
         when move => -- copy from ra to rd
    	  ps.RSet(rd) := ps.RSet(ra);
    	  
         -- arithmetic and compare instructions
         when addr => res_type := rcz;
          res := add(ps.RSet(ra), ps.RSet(rb), '0');
         when addi => res_type := rcz;
          res := add(imm, ps.RSet(rd), '0');
         when adcr => res_type := rcz;
          res := add(ps.RSet(ra), ps.RSet(rb), ps.cy);
         when adci => res_type := rcz;
          res := add(imm, ps.RSet(rd), ps.cy);
         when subr => res_type := rncz;
          res := add(ps.RSet(ra), not(ps.RSet(rb)), '1');
         when subi => res_type := rncz;
          res := add(imm, not(ps.RSet(rd)), '1');
         when sbcr => res_type := rncz;
          res := add(ps.RSet(ra), not(ps.RSet(rb)),  not(ps.cy));
         when sbci => res_type := rncz;
          res := add(imm, not(ps.RSet(rd)),  not(ps.cy));
         when comp => res_type := ncz;
          res := add(imm, not(ps.RSet(rd)), '1');
         when cmpc => res_type := ncz;
          res := add(imm, not(ps.RSet(rd)), not(ps.cy));
    	  
    	-- shift instruction
    	 when sh_l => res_type := rcz;
          res :=  ps.RSet(ra) & '0';
         when rotl => res_type := rcz;
          res :=  ps.RSet(ra) & ps.cy;
         when sh_r => res_type := rcz;
          res := '0' & ps.RSet(ra);
    	    res := res(0)&res(8 downto 1);
         when rotr => res_type := rcz;
          res := ps.cy & ps.RSet(ra);
    	    res := res(0)&res(8 downto 1);
    	
    	-- logical instruction  
         when notr => res_type := rz; 
          res(7 downto 0) := not ps.RSet(ra);
         when andr => res_type := rz;
          res(7 downto 0) := ps.RSet(ra) and ps.RSet(rb);
         when andi => res_type := rz;
          res(7 downto 0) := imm and ps.RSet(rd);
         when or_r => res_type := rz;
          res(7 downto 0) := ps.RSet(ra) or ps.RSet(rb);
         when or_i => res_type := rz;
          res(7 downto 0) := imm or ps.RSet(rd);
         when xorr => res_type := rz;
          res(7 downto 0) := ps.RSet(ra) xor ps.RSet(rb);
         when xori => res_type := rz;
          res(7 downto 0) :=  imm xor ps.RSet(rd);
         when others => res_type := non;
       end case;
    
       -- fuer Befehle, die auch Flags beeinflussen   
       case res_type is
        when rcz => -- addr, addi, adcr, adci, sh_l, rotl, sh_r, rotr
     	  ps.RSet(rd) := res(7 downto 0);
          ps.cy  := res(8);
    	  ps.z := is_zero(res(7 downto 0));
        when rncz => -- subr, subi, sbcr, sbci, 
     	  ps.RSet(rd) := res(7 downto 0);
          ps.cy  := not res(8);
    	  ps.z := is_zero(res(7 downto 0));
        when ncz => -- comp, cmpc
          ps.cy  := not res(8);
    	  ps.z := is_zero(res(7 downto 0));
        when rz => -- notr, andr, andi, or_r, or_i, xorr, xori
     	  ps.RSet(rd) := res(7 downto 0);
    	  ps.z := is_zero(res(7 downto 0));
    	when others => null;
       end case;
       
       -- Trace-Ausgabe und Befehlszhler aktualisieren
       trace <= ps;
       ps.PC := PC;
      end if;
     end process;
    
    end architecture;
    
    
    
  • Testrahmen für Logikbefehlen:
  • -- Foliensatz RA-F1, Abschnitt ?.?
    
    -- Testbeispiel mit Logikoperationen 
    -- r4 = (r1 & 0xF0) | (r2 & 0x0F)
    -- r5 = r4 ^ r4 (r5=0 und Z=1)
    
    -- letzte Aenderung: 21.03.2018
    -- Autor: G. Kemnitz
    
    --PC | Befehl assem.: hex | r0 r1 r2 r3 r4 r5 r6 r7 |c|z|
    --00 | ld_i r1,4a,..:294a | 00 4a 00 00 00 00 00 00 |0|0|
    --01 | ld_i r0,73,..:2873 | 73 4a 00 00 00 00 00 00 |0|0|
    --02 | move r2,r0,..:8200 | 73 4a 73 00 00 00 00 00 |0|0|
    --03 | move r3,r1,..:8320 | 73 4a 73 4a 00 00 00 00 |0|0|
    --04 | andi r2,0f,..:620f | 73 4a 03 4a 00 00 00 00 |0|0|
    --05 | andi r3,f0,..:63f0 | 73 4a 03 40 00 00 00 00 |0|0|
    --06 | or_r r4,r2,r3:ec4c | 73 4a 03 40 43 00 00 00 |0|0|
    --07 | xorr r5,r4,r4:f590 | 73 4a 03 40 43 00 00 00 |0|1|
    --str(dmem) = 00 00 00 00 00 00 00 00
    
    
    
    use work.mipro_pack.all;
    
    entity test_mipro is end entity;
    
    architecture a of test_mipro is
      signal T, I: bit;
      signal dmem: t_dmem(0 to 7);
      signal ps: t_proc_state;
      signal dmem_wr: boolean;
      constant imem: t_imem(0 to 7) := (
          0=>cmd(ld_i, r1, x"4a"),
          1=>cmd(ld_i, r0, x"73"),
          2=>cmd(move, r2, r0),
          3=>cmd(move, r3, r1),
          4=>cmd(andi, r2, x"0F"),
          5=>cmd(andi, r3, x"F0"),
          6=>cmd(or_r, r4, r2, r3),
    	  7=>cmd(xorr, r5, r4, r4),
          others=> nop
          );
      constant tP: delay_length := 10 ns;
      constant trace_length: natural :=10;
    
    begin
     DUT: entity work.mipro port map(T, I, imem, dmem, ps, dmem_wr);
    
     I <= '1', '0' after tP;
     
     process
     begin
     
      report(lf&"=====Program=========================");
      for idx in imem'range loop
        report(hex(to_bitvec(idx, 16)) & ": " & str_ir(imem(idx)));
      end loop;
    
      report(lf & c_proc_state);
      wait for tP;
      
      while uint(ps.PC)<imem'high and now<=(trace_length * tP) loop
       T <= '1' after 5 ns, '0' after 10 ns; wait for 10 ns;
       report(str(ps));
       if dmem_wr then  report("str(dmem) = " & str(dmem)); end if;
      end loop; 
      report("str(dmem) = " & str(dmem));
      wait;
     end process;
    
    end architecture;
    
    
  • Testrahmen für Additions- und Subtraktionsbefehle:
  • -- Foliensatz RA-F1, Abschnitt ?.?
    
    -- Testbeispiel mit Additionen und Subtraktionen:
    --  r0:r1 = 733A
    --  r2:r3 = 13E7
    --  r4:r5 = r0:r1 + r2:r3    (Ergebnis: 8721) 
    --  r4:r5 = 8623 - r4:r5     (Ergebnis: FF02)
    
    -- letzte Aenderung: 15.07.2016
    -- Autor: G. Kemnitz
    
    --PC | Befehl assem.: hex | r0 r1 r2 r3 r4 r5 r6 r7 |c|z|
    --00 | ld_i r1,3a,..:293a | 00 3a 00 00 00 00 00 00 |0|0|
    --01 | ld_i r0,73,..:2873 | 73 3a 00 00 00 00 00 00 |0|0|
    --02 | ld_i r3,e7,..:2be7 | 73 3a 00 e7 00 00 00 00 |0|0|
    --03 | ld_i r2,13,..:2a13 | 73 3a 13 e7 00 00 00 00 |0|0|
    --04 | addr r5,r1,r3:c52c | 73 3a 13 e7 00 21 00 00 |1|0|
    --05 | adcr r4,r0,r2:cc08 | 73 3a 13 e7 87 21 00 00 |0|0|
    --06 | subi r5,23,..:5523 | 73 3a 13 e7 87 02 00 00 |0|0|
    --07 | sbci r4,86,..:5c86 | 73 3a 13 e7 ff 02 00 00 |1|0|
    --str(dmem) = 00 00 00 00 00 00 00 00
    
    
    use work.mipro_pack.all;
    
    entity test_mipro is end entity;
    
    architecture a of test_mipro is
      signal T, I: bit;
      signal dmem: t_dmem(0 to 7);
      signal ps: t_proc_state;
      signal dmem_wr: boolean;
      constant imem: t_imem(0 to 7) := (
          0=>cmd(ld_i, r1, x"3a"),
          1=>cmd(ld_i, r0, x"73"),
          2=>cmd(ld_i, r3, x"E7"),
          3=>cmd(ld_i, r2, x"13"),
          4=>cmd(addr, r5, r1,r3),
          5=>cmd(adcr, r4, r0, r2),
    	  6=>cmd(subi, r5, x"23"),
          7=>cmd(sbci, r4, x"86"),
          others=> nop
          );
      constant tP: delay_length := 10 ns;
      constant trace_length: natural :=10;
    
    begin
     DUT: entity work.mipro port map(T, I, imem, dmem, ps, dmem_wr);
    
     I <= '1', '0' after tP;
     
     process
     begin
     
      report(lf&"=====Program=========================");
      for idx in imem'range loop
        report(hex(to_bitvec(idx, 16)) & ": " & str_ir(imem(idx)));
      end loop;
    
      report(lf & c_proc_state);
      wait for tP;
      
      while uint(ps.PC)<imem'high and now<=(trace_length * tP) loop
       T <= '1' after 5 ns, '0' after 10 ns; wait for 10 ns;
       report(str(ps));
       if dmem_wr then  report("str(dmem) = " & str(dmem)); end if;
      end loop; 
      report("str(dmem) = " & str(dmem));
      wait;
     end process;
    
    end architecture;
    
    
    
  • Testrahmen für Lade- und Speicherbefehle:
  • -- Foliensatz RA-F1, Abschnitt ?.?
    
    -- Testbeispiel mit Additionen und Subtraktionen:
    --  r0:r1 = 733A
    --  r2:r3 = 13E7
    --  r4:r5 = r0:r1 + r2:r3    (Ergebnis: 8721) 
    --  r4:r5 = 8623 - r4:r5     (Ergebnis: FF02)
    
    -- letzte Aenderung: 15.07.2016
    -- Autor: G. Kemnitz
    
    --PC | Befehl assem.: hex | r0 r1 r2 r3 r4 r5 r6 r7 |c|z|
    --00 | ld_i r1,3a,..:293a | 00 3a 00 00 00 00 00 00 |0|0|
    --01 | ld_i r0,73,..:2873 | 73 3a 00 00 00 00 00 00 |0|0|
    --02 | ld_i r3,e7,..:2be7 | 73 3a 00 e7 00 00 00 00 |0|0|
    --03 | ld_i r2,13,..:2a13 | 73 3a 13 e7 00 00 00 00 |0|0|
    --04 | addr r5,r1,r3:c52c | 73 3a 13 e7 00 21 00 00 |1|0|
    --05 | adcr r4,r0,r2:cc08 | 73 3a 13 e7 87 21 00 00 |0|0|
    --06 | subi r5,23,..:5523 | 73 3a 13 e7 87 02 00 00 |0|0|
    --07 | sbci r4,86,..:5c86 | 73 3a 13 e7 ff 02 00 00 |1|0|
    --str(dmem) = 00 00 00 00 00 00 00 00
    
    
    use work.mipro_pack.all;
    
    entity test_mipro is end entity;
    
    architecture a of test_mipro is
      signal T, I: bit;
      signal dmem: t_dmem(0 to 7);
      signal ps: t_proc_state;
      signal dmem_wr: boolean;
      constant imem: t_imem(0 to 7) := (
          0=>cmd(ld_i, r1, x"3a"),
          1=>cmd(ld_i, r0, x"73"),
          2=>cmd(ld_i, r3, x"E7"),
          3=>cmd(ld_i, r2, x"13"),
          4=>cmd(addr, r5, r1,r3),
          5=>cmd(adcr, r4, r0, r2),
    	  6=>cmd(subi, r5, x"23"),
          7=>cmd(sbci, r4, x"86"),
          others=> nop
          );
      constant tP: delay_length := 10 ns;
      constant trace_length: natural :=10;
    
    begin
     DUT: entity work.mipro port map(T, I, imem, dmem, ps, dmem_wr);
    
     I <= '1', '0' after tP;
     
     process
     begin
     
      report(lf&"=====Program=========================");
      for idx in imem'range loop
        report(hex(to_bitvec(idx, 16)) & ": " & str_ir(imem(idx)));
      end loop;
    
      report(lf & c_proc_state);
      wait for tP;
      
      while uint(ps.PC)<imem'high and now<=(trace_length * tP) loop
       T <= '1' after 5 ns, '0' after 10 ns; wait for 10 ns;
       report(str(ps));
       if dmem_wr then  report("str(dmem) = " & str(dmem)); end if;
      end loop; 
      report("str(dmem) = " & str(dmem));
      wait;
     end process;
    
    end architecture;
    
    
    
  • Testrahmen mit einem Programm mit Fallunterscheidungen:
  • -- Foliensatz RA-F1, Abschnitt ?.?
    
    -- Testbeispiel mit Fallunterscheidung:
    -- wenn r0 < 0x37 dann r1 = 1; sonst r1 = 4;
    -- zuerst mit r0=0x7 und dann mit r0=0x48
    
    -- letzte Aenderung: 21.03.2018
    -- Autor: G. Kemnitz
    
    -- =====Test1=========================
    -- 0000: ld_i r0,07,..
    -- 0001: comp r0,37,..
    -- 0002: jump 05,leq..
    -- 0003: ld_i r1,01,..
    -- 0004: jump 06,alw..
    -- 0005: ld_i r1,04,..
    -- 0006: ld_i r0,48,..
    
    -- PC|Befehl assem.: hex|r0 r1 r2 r3 r4 r5 r6 r7|c|z|
    -- 00|ld_i r0,07,..:2807|07 00 00 00 00 00 00 00|0|0|
    -- 01|comp r0,37,..:3037|07 00 00 00 00 00 00 00|0|0|
    -- 02|jump 05,leq..:0b05|07 00 00 00 00 00 00 00|0|0|
    -- 05|ld_i r1,04,..:2904|07 04 00 00 00 00 00 00|0|0|
    -- 06|ld_i r0,48,..:2848|48 04 00 00 00 00 00 00|0|0|
    
    -- =====Test 2=========================
    -- 0000: ld_i r0,48,..
    -- 0001: comp r0,37,..
    -- 0002: jump 05,leq..
    -- 0003: ld_i r1,01,..
    -- 0004: jump 06,alw..
    -- 0005: ld_i r1,04,..
    -- 0006: ld_i r0,48,..
    
    -- PC|Befehl assem.: hex|r0 r1 r2 r3 r4 r5 r6 r7|c|z|
    -- 00|ld_i r0,48,..:2848|48 00 00 00 00 00 00 00|0|0|
    -- 01|comp r0,37,..:3037|48 00 00 00 00 00 00 00|1|0|
    -- 02|jump 05,leq..:0b05|48 00 00 00 00 00 00 00|1|0|
    -- 03|ld_i r1,01,..:2901|48 01 00 00 00 00 00 00|1|0|
    -- 04|jump 06,alw..:0906|48 01 00 00 00 00 00 00|1|0|
    -- 06|ld_i r0,48,..:2848|48 01 00 00 00 00 00 00|1|0|
    
    
    
    use work.mipro_pack.all;
    
    entity test_mipro is end entity;
    
    architecture a of test_mipro is
      signal T, I: bit;
      signal dmem: t_dmem(0 to 7);
      signal ps: t_proc_state;
      signal dmem_wr: boolean;
      constant imem: t_imem(0 to 7) := (
        0=>cmd(ld_i, r0, x"48"),
        1=>cmd(comp, r0,x"37"),
        2=>jmp(x"05", leq),
        3=>cmd(ld_i, r1, x"01"),
        4=>jmp(x"06", alw),
        5=>cmd(ld_i, r1, x"04"),
        6=>cmd(ld_i, r0, x"48"),
        others=> nop
        );
      constant tP: delay_length := 10 ns;
      constant trace_length: natural :=18;
    
    begin
     DUT: entity work.mipro port map(T, I, imem, dmem, ps, dmem_wr);
    
     I <= '1', '0' after tP;
     
     process
     begin
     
      report(lf&"=====Program=========================");
      for idx in imem'range loop
        report(hex(to_bitvec(idx, 16)) & ": " & str_ir(imem(idx)));
      end loop;
    
      report(lf & c_proc_state);
      wait for tP;
      
      while uint(ps.PC)<imem'high and now<=(trace_length * tP) loop
       T <= '1' after 5 ns, '0' after 10 ns; wait for 10 ns;
       report(str(ps));
       if dmem_wr then  report("str(dmem) = " & str(dmem)); end if;
      end loop; 
      report("str(dmem) = " & str(dmem));
      wait;
     end process;
    
    end architecture;
    
    
    
  • Testrahmen mit einem Programm mit einer Schleife:
  • -- Foliensatz RA-F1, Abschnitt ?.?
    
    -- Testbeispiel mit Schleife:
    --    r0 = 1; r1 = 34;
    -- M: dmem(r0) = r1;
    --    r1 = r1 - r0;
    --    r0 = r0 +1;
    --    wenn r0 <= 3 springe zu M (2x fuer r0=2 und 3)
    
    -- letzte Aenderung: 21.03.2018
    -- Autor: G. Kemnitz
    
    -- =====Program=========================
    -- 0000: ld_i r0,01,..
    -- 0001: ld_i r1,34,..
    -- 0002: st_r r1,r0,..
    -- 0003: subr r1,r1,r0
    -- 0004: addi r0,01,..
    -- 0005: comp r0,03,..
    -- 0006: jump 02,leq..
    -- 0007: noop ..,..,..
    
    -- PC|Befehl assem.: hex|r0 r1 r2 r3 r4 r5 r6 r7|c|z|
    -- 00|ld_i r0,01,..:2801|01 00 00 00 00 00 00 00|0|0|
    -- 01|ld_i r1,34,..:2934|01 34 00 00 00 00 00 00|0|0|
    -- 02|st_r r1,r0,..:9100|01 34 00 00 00 00 00 00|0|0|
    -- str(dmem) = 00 34 00 00 00 00 00 00
    -- 03|subr r1,r1,r0:d120|01 33 00 00 00 00 00 00|0|0|
    -- 04|addi r0,01,..:4001|02 33 00 00 00 00 00 00|0|0|
    -- 05|comp r0,03,..:3003|02 33 00 00 00 00 00 00|0|0|
    -- 06|jump 02,leq..:0b02|02 33 00 00 00 00 00 00|0|0|
    -- 02|st_r r1,r0,..:9100|02 33 00 00 00 00 00 00|0|0|
    -- str(dmem) = 00 34 33 00 00 00 00 00
    -- 03|subr r1,r1,r0:d120|02 31 00 00 00 00 00 00|0|0|
    -- 04|addi r0,01,..:4001|03 31 00 00 00 00 00 00|0|0|
    -- 05|comp r0,03,..:3003|03 31 00 00 00 00 00 00|0|1|
    -- 06|jump 02,leq..:0b02|03 31 00 00 00 00 00 00|0|1|
    -- 02|st_r r1,r0,..:9100|03 31 00 00 00 00 00 00|0|1|
    -- str(dmem) = 00 34 33 31 00 00 00 00
    -- 03|subr r1,r1,r0:d120|03 2e 00 00 00 00 00 00|0|0|
    -- 04|addi r0,01,..:4001|04 2e 00 00 00 00 00 00|0|0|
    -- 05|comp r0,03,..:3003|04 2e 00 00 00 00 00 00|1|0|
    -- 06|jump 02,leq..:0b02|04 2e 00 00 00 00 00 00|1|0|
    -- 07|noop ..,..,..:0000|04 2e 00 00 00 00 00 00|1|0|
    -- str(dmem) = 00 34 33 31 00 00 00 00
    
    
    use work.mipro_pack.all;
    
    entity test_mipro is end entity;
    
    architecture a of test_mipro is
      signal T, I: bit;
      signal dmem: t_dmem(0 to 7);
      signal ps: t_proc_state;
      signal dmem_wr: boolean;
      constant imem: t_imem(0 to 7) := (
        0=>cmd(ld_i, r0, x"01"),
        1=>cmd(ld_i, r1, x"34"),
        2=>cmd(st_r, r1, r0),
        3=>cmd(subr, r1, r1, r0),
        4=>cmd(addi, r0, x"01"),
        5=>cmd(comp, r0,x"03"),
        6=>jmp(x"02", leq),
        others=> nop
        );
      constant tP: delay_length := 10 ns;
      constant trace_length: natural :=18;
    
    begin
     DUT: entity work.mipro port map(T, I, imem, dmem, ps, dmem_wr);
    
     I <= '1', '0' after tP;
     
     process
     begin
     
      report(lf&"=====Program=========================");
      for idx in imem'range loop
        report(hex(to_bitvec(idx, 16)) & ": " & str_ir(imem(idx)));
      end loop;
    
      report(lf & c_proc_state);
      wait for tP;
      
      while uint(ps.PC)<imem'high and now<=(trace_length * tP) loop
       T <= '1' after 5 ns, '0' after 10 ns; wait for 10 ns;
       report(str(ps));
       if dmem_wr then  report("str(dmem) = " & str(dmem)); end if;
      end loop; 
      report("str(dmem) = " & str(dmem));
      wait;
     end process;
    
    end architecture;
    
    
    

RISC-Prozessor

  • Package mit den ausgabenspezifischen Datentypen und Funktionen:
  • -- Foliensatz EDS-F6, Abschnitt 2: Entwurf eines Prozessors
    -- Programm risc_pack.vhd
    -- Typdefinitionen, Konstanten, Hilfsfunktionen
    -- letzte Aenderung: 21.03.2018
    -- Autor: G. Kemnitz
    
    
    package risc_pack is
    
     -- Instruction set                          || format / built function
     type t_cmd is (noop,                        -- nop
                   jump,                         -- jump(imm8, cond:=non)
                   call, load, stor, ld_i, comp, -- cmd(<cmd> rd, imm8)
                   cmpc, addi, adci, subi, sbci,
                   andi, or_i, xori,
                   retu,                         -- ret(rd)
                   move, ld_r, st_r, sh_l, sh_r, -- cmd(<cmd> rd ra)
                   rotl, rotr, notr, 
                   addr, adcr, subr, sbcr,       -- cmd(<cmd> rd ra rb)
                   andr, or_r, xorr);
     
    -- register definition
     type t_reg is (r0, r1, r2, r3, r4, r5, r6, r7);
    -- jump conditions
     type t_cond is (nev, -- junp never  
                     alw, -- jump allways
                     gth, -- jump greater than        (cy=1)
                     leq, -- jump if less or equal    (cy=0)
                     equ, -- jump if equal            (z =1)
                     neq, -- jump if not equal        (z =0) 
                     geq, -- jump if greater or equal (cy=1 or  z=1) 
                     lth);-- jump if less than        (cy=0 and z=0) 
    
     type t_imem is array (natural range<>) of bit_vector(15 downto 0);
     type t_dmem is array (natural range<>) of bit_vector(7 downto 0);
    
     type t_proc_state is record
      PC  : bit_vector( 7 downto 0); -- Program Counter
      IReg: bit_vector(15 downto 0); -- Instruction Register
      Cmd:  bit_vector( 4 downto 0); -- Op.-Code Register
      O1:  bit_vector( 7 downto 0); -- Operand 1
      O2:  bit_vector( 7 downto 0); -- Operand 2
      cy:   bit;                     -- cary flag
      z:    bit;                     -- zero flag
      RR:  bit_vector( 7 downto 0); -- Result
      RA:  bit_vector( 2 downto 0); -- Result Adress EX
      RB:  bit_vector( 2 downto 0); -- Result Adress RW
      W:   bit_vector( 1 downto 0); -- Result Write Operation
      RSet: t_dmem(0 to 7);          -- Register Set
     end record;
    
     constant c_proc_state: string :=
     "PC| Instruction |Cmd |O1|O2|OR|c|z|RA|RB|W|r0 r1 r2 r3 r4 r5 r6 r7";
    
    -- ========= string conversion ===============================================
    -- data => hex. strings, e.g. 6F
     function hex(dat: bit_vector) return string;
    
     -- sector of data memeory => to string of hex. numbers
    -- e.g. A3 56 12 9A 43 19 7B CA
     function str(w: t_dmem) return string; 
    
     -- register adress, notation r<nr>
     function str_reg(w:bit_vector(2 downto 0)) return string;
    
     -- result write operation: non, ldm, stm or rwr
     function str_RWO(w: bit_vector(1 downto 0)) return string; 
    
     -- instruction in assemly language, e.g. addc r1 r4 r5
     function str_ir(w: bit_vector(15 downto 0)) return string;
    
    -- processor state (length 72 character), e.g.
    --PC| Instruction |Cmd |O1|O2|OR|c|z|RA|RB|W|r0 r1 r2 r3 r4 r5 r6 r7
    --1A|addc r1 r4 r5|load|3E|5B|04|0|1|r3|r6|S|A3 56 12 9A 43 19 7B CA 
     function str(ps: t_proc_state) return string;
    
    -- ==========function to built binary machine instructions====================
    -- no operation instruction is a constant
     constant nop:bit_vector(15 downto 0) := x"0000";
    -- jump instructions has target adress and condition as operands
     function jmp(tgadr: bit_vector(7 downto 0); cond: t_cond:=alw) return bit_vector;
    -- instructions with one register adress und an 8 bit imidiate value
     function cmd(w: t_cmd; rd:t_reg; imm: bit_vector(7 downto 0)) return bit_vector;
    -- instructions with one to three registers adresses
     function cmd(w: t_cmd; rd:t_reg; ra, rb: t_reg:=r0) return bit_vector;
    
    -- =========convertion from t_reg to bit_vector===============================
     function reg(w: t_reg) return bit_vector;
    
    -- =========convertion from bit_vector to unsigned integer====================
     function uint(w: bit_vector) return natural;
    
    -- ========= convertion from unsigned integer to bit_vector===================
     function to_bitvec(w: natural; b: positive) return bit_vector;
    
    -- =========addion of two bit vector with cary ===============================
     function add(a, b: bit_vector(7 downto 0); cy: bit) return bit_vector;
    
    -- ========= increment of a bit vector =======================================
     function inc(a: bit_vector) return bit_vector;
    
    -- ========= test, if bit vector is zero =====================================
      function is_zero(bv: bit_vector(7 downto 0)) return bit;
    
    -- ========= test jump condition =============================================
     function test_jmp_cond(cond: bit_vector(2 downto 0); cy, z: bit) return boolean;
    
    
    
    end package;
    -- ===========================================================================
    
    
    package body risc_pack is
    
    -- ===========================================================================
    -- ========= string conversion ===============================================
    -- data => hex. strings, e.g. 6f
     function hex(dat: bit_vector) return string is
      constant c: string := "0123456789abcdef";
      constant w: bit_vector(dat'length-1 downto 0) := dat;
      variable val, i, j: natural := 0;
      variable k: positive := 1;
      variable s: string(1 to (w'length-1)/4+1) := (others=>'x');
     begin
      while i < w'length loop
       if w(i)='1' then 
        val := val + k;
       end if;
       if k=8 then
        s(s'high-j):=c(val+1);
        j:=j+1; k:=1; val:= 0;
       else
        k:=2*k;
       end if;
       i:=i+1;
      end loop;
      if s'high > j then s(s'high-j):=c(val+1); end if;
      return s;
     end function;
    -- ===========================================================================
    -- sector of data memeory => to string of hex. numbers
    -- e.g. A3 56 12 9A 43 19 7B CA
     function str(w: t_dmem) return string is
      variable s: string(1 to 3*w'length-1) :=(others=>' ');
     begin
      for i in w'low to w'high loop
       s(3*(i-w'low)+1 to 3*(i-w'low)+2) := hex(w(i));
      end loop;
      return s;
     end function;
    -- ===========================================================================
    -- register adress, notation r<nr>, e.g. r4
     function str_reg(w:bit_vector(2 downto 0)) return string is
     begin
      return 'r' & hex(w);
     end function;
    -- ===========================================================================
    -- result write operation: non, ldm, stm or rwr
     function str_RWO(w: bit_vector(1 downto 0)) return string is
     begin
      case w is
       when "00"   => return "-";
       when "01"   => return "S";
       when "10"   => return "L";
       when "11"   => return "R";
      end case;
     end function;
    -- ===========================================================================
    -- instruction => assemly language string, e.g. addc r1 r4 r5
     function str_ir(w: bit_vector(15 downto 0)) return string is
      variable s: string(1 to 13) := "xxxx ..,..,..";
      variable inr: natural;
     begin
       inr := uint(w(15 downto 11));
       --report("inr=" & integer'image(inr));
       s(1 to 4) := t_cmd'image(t_cmd'val(inr));
       if inr >=  t_cmd'pos(addr) then           -- addr 
        s( 6 to  7) := str_reg(w(10 downto 8));  -- addr rd
        s( 9 to 10) := str_reg(w( 7 downto 5));  -- addr rd rs 
        s(12 to 13) := str_reg(w( 4 downto 2));  -- addr rd rs rs 
       elsif inr >=  t_cmd'pos(move) then        -- move
        s( 6 to  7) := str_reg(w(10 downto 8));  -- move rd
        s( 9 to 10) := str_reg(w( 7 downto 5));  -- move rd rs 
       elsif inr >=  t_cmd'pos(retu) then        -- retu
        s( 6 to  7) := str_reg(w(10 downto 8));  -- retu rd
       elsif inr >=  t_cmd'pos(call) then        -- call
        s( 6 to  7) := str_reg(w(10 downto 8));  -- call rd
        s( 9 to 10) := hex(w(7 downto 0));       -- call rd imm8 
       elsif inr  =  t_cmd'pos(jump) then        -- jump
        s( 6 to  7) := hex(w(7 downto 0));       -- jump a3
        s( 9 to 11) := t_cond'image(t_cond'val(uint(w(10 downto 8)))); 
       end if; 
      return s;
     end function;
    
     function str(w: bit) return character is
     begin
      if w='0' then return '0';
      else          return '1';
      end if;
     end function;
    -- ===========================================================================
    -- processor state (length 72 character), e.g.
    --PC| Instruction |Cmd |O1|O2|OR|c|z|RA|RB|W|r0 r1 r2 r3 r4 r5 r6 r7
    --1A|addc r1 r4 r5|load|3E|5B|04|0|1|r3|r6|S|A3 56 12 9A 43 19 7B CA 
     function str(ps: t_proc_state) return string is
     begin
      return hex(ps.PC)     & "|"  & str_ir(ps.IReg) & "|"  
           & t_cmd'image(t_cmd'val(uint(ps.Cmd)))     & "|"
           & hex(ps.O1)    & "|" & hex(ps.O2)     & "|" & hex(ps.RR)     & "|" 
           & str(ps.cy)     & "|"  & str(ps.z)       & "|" & str_reg(ps.RA) & "|"
           & str_reg(ps.RB) & "|"  & str_RWO(ps.W) & "|"  & str(ps.RSet);
     end function;
    -- ===========================================================================
    -- ==========function to built binary machine instructions====================
    -- jump instructions has target adress and condition as operands
     function jmp(tgadr: bit_vector(7 downto 0); cond: t_cond:=alw) return bit_vector is
     begin
      --report("jump");
      return to_bitvec(t_cmd'pos(jump), 5) & 
             to_bitvec(t_cond'pos(cond), 3) & tgadr;
     end function;
    -- ===========================================================================
    -- instructions with one register adress und an 8 bit imidiate value
     function cmd(w: t_cmd; rd:t_reg; imm: bit_vector(7 downto 0)) return bit_vector is
      variable n: natural := t_cmd'pos(w);
     begin
      assert n >= t_cmd'pos(call) and  n <= t_cmd'pos(xori)
      report t_cmd'image(w) & " not format cmd rd imm8"
      severity failure;
      --report(t_cmd'image(w));
      return to_bitvec(t_cmd'pos(w), 5)  &
             to_bitvec(t_reg'pos(rd), 3) & imm;
     end function;
    -- ===========================================================================
    -- instructions with one to three registers adresses
     function cmd(w: t_cmd; rd:t_reg; ra, rb: t_reg:=r0) return bit_vector is
      variable n: natural := t_cmd'pos(w);
     begin
      assert  n >= t_cmd'pos(retu)
      report t_cmd'image(w) & " not format cmd rd [rs [rs]]"
      severity failure;
      --report(t_cmd'image(w));
      return to_bitvec(t_cmd'pos(w  ), 5) &  
             to_bitvec(t_reg'pos(rd ), 3) &
             to_bitvec(t_reg'pos(ra), 3) &
             to_bitvec(t_reg'pos(rb), 3) & "00";
     end function;
    -- ===========================================================================
    -- =========convertion from t_reg to bit_vector===============================
     function reg(w: t_reg) return bit_vector is
     begin 
      return to_bitvec(t_reg'pos(w), 3);
     end function;
    
    -- ========= convertion from bit_vector to unsigned integer===================
     function uint(w: bit_vector) return natural is
      variable n: natural;
      variable bv: bit_vector(w'length-1 downto 0) := w;
     begin
      for idx in 0 to bv'high loop
       if bv(idx)='1' then
        n := n + (2**idx);
       end if;
      end loop;
      return n;
     end function;
    
    -- ========= convertion from unsigned integer to bit_vector===================
     function to_bitvec(w: natural; b:positive) return bit_vector is
      variable bv: bit_vector(b-1 downto 0);
      variable s: string(b-1 downto 0):=(others=>'0');
      variable val: natural := w;
     begin
      --report("w=" & integer'image(w) & " 2**b=" & integer'image(2**b));
      assert w < (2**b)
      report "w=" & integer'image(w) & " too large for bv(" & integer'image(b-1) & " downto 0)"
      severity failure;
      for idx in 0 to b-1 loop
       if (val rem 2) = 1 then
        bv(idx) := '1';
        s(idx)  :=  '1';
       end if;
       val := val/2;
       --report("val=" & integer'image(val) & " bv=" & s);
      end loop;
      return bv;
     end function;
      
    -- =========addion of two bit vector with cary ===============================
     function add(a, b: bit_vector(7 downto 0); cy: bit) return bit_vector is
      variable c: bit := cy;
      variable s: bit_vector(7 downto 0);
     begin
      for idx in  0 to 7 loop
       s(idx) := a(idx) xor b(idx) xor c;
       c := (a(idx) and b(idx)) or (c and (a(idx) or b(idx)));
       --report("idx=" & integer'image(idx) & 
       --                                     " a(idx)=" & bit'image(a(idx)) & 
       --                                     " b(idx)=" & bit'image(b(idx)) & 
       --                                     " c_out="  & bit'image(c) & 
       --                                     " s(idx)=" & bit'image(s(idx)));
      end loop;
      return c & s;
     end function;
    
    -- ========= increment of a bit vector =======================================
     function inc(a: bit_vector) return bit_vector is
      variable s: bit_vector(a'length-1 downto 0);
      variable c: bit:='1';
     begin
      assert a'right = 0
      report "a is not bit_vector(n downto 0)"
      severity failure;
      for idx in  0 to s'high loop
       s(idx) := a(idx) xor c;
       c := a(idx) and c;
      end loop;
      return s;
     end function;
    
    -- ========= test, if bit vector is zero =====================================
      function is_zero(bv: bit_vector(7 downto 0)) return bit is
       variable z: bit :='1';
      begin
       for idx in 0 to bv'high loop
        if bv(idx) = '1' then z := '0';
        end if;
       end loop;
       return z;
      end function;
    
    -- ========= test jump condition =============================================
     function test_jmp_cond(cond: bit_vector(2 downto 0); cy, z: bit) return boolean is
     begin
      return (cond(0) xor ((cond(1) and cy) or (cond(2) and z)))='1';
     end function;
    
    end package body;
    
    
  • Beschreibung des Prozessors:
  • -- Register transfer function of the RISC-Processor design (EDS F6)
    -- Author: gkemnitz
    -- Last change: 21.03.2018
    -- Autor: G. Kemnitz
    
    use work.risc_pack.all;
    
    entity risc is
     generic)dm_init: t_dmem);
     port (
      T, I: bit;
      imem: in t_imem;
      dmem: inout t_dmem;
      ps: buffer t_proc_state;
      dmem_wr: out boolean);   -- Signalisiert Speicherschreibzugriffe
    end entity;
     
    architecture a of risc is
    begin
    
     process(T, I)
      variable res: bit_vector(8 downto 0);
      variable cmd: t_cmd;
     begin
      if I='1' then
       ps.PC <= x"00";
       dmem  <= dem_init;
      elsif T'event and T='1' then
    
      -- instruction fetch (IF)
      ps.PC   <= inc(ps.PC);   
      ps.IReg <= imem(uint(ps.PC)); 
    
      -- Operand Fetch (OF)
      ps.Cmd  <= ps.IReg(15 downto 11);
      ps.RA  <= ps.IReg(10 downto  8);
      cmd := t_cmd'val(uint(ps.IReg(15 downto 11)));
      case cmd is
        when noop => 
         ps.O1 <= x"00";                                -- unused
         ps.O2 <= x"00";                                -- unused
        when jump =>  
         ps.O1 <= ps.IReg(7 downto  0);                 -- jump_target imm8
         ps.O2 <= "00000" & ps.IReg(10 downto  8);      -- branch condition 
        when call =>                                
         ps.O1 <= ps.IReg(7 downto  0);                 -- jump_target imm8
         ps.O2 <= ps.PC;                                -- return_adress
        when load|stor|ld_i =>
         ps.O1 <= ps.IReg( 7 downto  0);                -- imm8
         ps.O2 <= x"00";                                -- unused
        when retu => 
         ps.O1 <= ps.RSet(uint(ps.IReg(10 downto  8))); -- jump_target rd
         ps.O2 <= x"00";                                -- unused
        when move|ld_r|st_r|sh_l|sh_r|rotl|rotr|notr =>
         ps.O1 <= ps.RSet(uint(ps.IReg( 7 downto  5))); -- ra
         ps.O2 <= x"00";                                -- unused
        when addr|adcr|subr|sbcr|andr|or_r|xorr =>
         ps.O1 <= ps.RSet(uint(ps.IReg( 7 downto  5))); -- ra
         ps.O2 <= ps.RSet(uint(ps.IReg( 4 downto  2))); -- rb
        when others =>
         ps.O1 <= ps.IReg( 7 downto  0);                -- imm8
         ps.O2 <= ps.RSet(uint(ps.IReg(10 downto  8))); -- rd
      end case;
    
      -- Execute (EX)
       ps.RB <= ps.RA;
       cmd := t_cmd'val(uint(ps.Cmd));
       case cmd is  
         -- branch instructions
         when jump  => 
          if test_jmp_cond(ps.O2(2 downto 0), ps.cy, ps.z) then
           ps.PC <= ps.O1;
          end if;
         when call =>
          ps.PC  <= ps.O1;
          ps.RR <= ps.O2;
         when retu =>
          ps.PC  <= ps.O1;
         -- load and store instruction
         when ld_i|load|ld_r|stor|st_r|move =>
          ps.RR <= ps.O1;
         -- arithmetic and compare instructions
         when addr|addi =>
          res := add(ps.O1, ps.O2, '0');
          ps.RR <= res(7 downto 0);
          ps.cy  <= res(8);
          ps.z <= is_zero(res(7 downto 0));
         when adcr|adci =>
           res := add(ps.O1, ps.O2, ps.cy);
           ps.RR <= res(7 downto 0);
           ps.cy  <= res(8);
           ps.z   <= is_zero(res(7 downto 0));
          
         when subr|subi|comp =>
          res := add(ps.O1, not ps.O2, '1');
          ps.RR <= res(7 downto 0);
          ps.cy  <= not res(8);
          ps.z   <= is_zero(res(7 downto 0));
         when sbcr|sbci|cmpc =>
          res := add(ps.O1, not ps.O2, not ps.cy);
          ps.RR <= res(7 downto 0);
          ps.cy  <= not res(8);
          ps.z   <= is_zero(res(7 downto 0));
    
         -- shift instructions
         when sh_l =>
          res :=  ps.O1 & '0';
          ps.cy  <= res(8);
          ps.RR <= res(7 downto 0);
          ps.Z   <= is_zero(res(7 downto 0));
         when rotl =>
          res :=  ps.O1 & ps.cy;
          ps.cy  <= res(8);
          ps.RR <= res(7 downto 0);
          ps.Z <= is_zero(res(7 downto 0));
         when sh_r =>
          res := '0' & ps.O1;
          ps.cy  <= res(0);
          ps.RR <= res(8 downto 1);
          ps.Z   <= is_zero(res(8 downto 1));
         when rotr =>
          res := ps.cy & ps.O1;
          ps.cy  <= res(0);
          ps.RR <= res(8 downto 1);
          ps.Z   <= is_zero(res(8 downto 1));
    
         -- logical instructions
         when notr =>
          ps.RR <= not ps.O1;
          ps.Z   <= is_zero(not ps.O1);
         when andr|andi =>
          ps.RR <= ps.O1 and ps.O2;
          ps.Z   <= is_zero(ps.O2 and ps.O2);
         when or_r|or_i =>
          ps.RR <= ps.O1 or ps.O2;
          ps.Z   <= is_zero(ps.O2 or ps.O2);
         when xorr|xori =>
          ps.RR <= ps.O1 xor ps.O2;
          ps.Z   <= is_zero(ps.O2 xor ps.O2);
         when others =>
          null;
       end case;
     
       case cmd is        -- result write operation
        when noop|jump|comp|cmpc|retu =>
         ps.W <= "00";  -- no result write
        when load|ld_r =>
         ps.W <= "10";  -- load rd from dmem
        when stor|st_r =>
         ps.W <= "01";  -- store rd to dmem
        when others =>
          ps.W <= "11"; -- store result in rd
       end case;
     
       -- result write (RW)
       dmem_wr <= false;
       case ps.W is
        when "11" =>                   -- RW write result
         ps.RSet(uint(ps.RB)) <= ps.RR;
        when "10" =>                   -- RW load from memory
         ps.RSet(uint(ps.RB)) <= dmem(uint(ps.RR));
        when "01" =>                   -- RW store to memory
         dmem(uint(ps.RR)) <= ps.RSet(uint(ps.RB));
         dmem_wr <= true;
        when "00" => null;             -- RW do nothing
       end case;
       
      end if;
     end process;
     
    end architecture;
    
    
    
  • Testrahmen für Logikbefehlen:
  • -- Foliensatz RA-F1, Abschnitt ?.?
    
    
    -- Testbeispiel mit Logikoperationen 
    -- r4 = (r1 & 0xF0) | (r2 & 0x0F)
    -- r5 = r3 ^ r3 (r5=0 und Z=1)
    
    
    -- letzte Aenderung: 21.03.2018
    -- Autor: G. Kemnitz
    
    --PC| Instruction |Cmd |O1|O2|OR|c|z|RA|RB|W|r0 r1 r2 r3 r4 r5 r6 r7
    --01|ld_i r1,4a,..|noop|00|00|00|0|0|r0|r0|-|00 00 00 00 00 00 00 00
    --02|ld_i r0,73,..|ld_i|4a|00|00|0|0|r1|r0|-|00 00 00 00 00 00 00 00
    --03|noop ..,..,..|ld_i|73|00|4a|0|0|r0|r1|R|00 00 00 00 00 00 00 00
    --04|move r3,r1,..|noop|00|00|73|0|0|r0|r0|R|00 4a 00 00 00 00 00 00
    --05|move r2,r0,..|move|4a|00|73|0|0|r3|r0|-|73 4a 00 00 00 00 00 00
    --06|noop ..,..,..|move|73|00|4a|0|0|r2|r3|R|73 4a 00 00 00 00 00 00
    --07|andi r3,f0,..|noop|00|00|73|0|0|r0|r2|R|73 4a 00 4a 00 00 00 00
    --08|andi r2,0f,..|andi|f0|4a|73|0|0|r3|r0|-|73 4a 73 4a 00 00 00 00
    --09|noop ..,..,..|andi|0f|73|40|0|0|r2|r3|R|73 4a 73 4a 00 00 00 00
    --0a|noop ..,..,..|noop|00|00|03|0|0|r0|r2|R|73 4a 73 40 00 00 00 00
    --0b|or_r r4,r2,r3|noop|00|00|03|0|0|r0|r0|-|73 4a 03 40 00 00 00 00
    --0c|xorr r5,r3,r3|or_r|03|40|03|0|0|r4|r0|-|73 4a 03 40 00 00 00 00
    --0d|noop ..,..,..|xorr|40|40|43|0|0|r5|r4|R|73 4a 03 40 00 00 00 00
    --0e|noop ..,..,..|noop|00|00|00|0|1|r0|r5|R|73 4a 03 40 43 00 00 00
    
    
    use work.risc_pack.all;
    
    entity test_risc is end entity;
    
    architecture a of test_risc is
      signal T, I: bit;
      signal dmem: t_dmem(0 to 7);
      signal ps: t_proc_state;
      signal dmem_wr: boolean;
      constant imem: t_imem(0 to 14) := (
          0=>cmd(ld_i, r1, x"4a"),
          1=>cmd(ld_i, r0, x"73"),
          3=>cmd(move, r3, r1),
          4=>cmd(move, r2, r0),
          6=>cmd(andi, r3, x"F0"),
          7=>cmd(andi, r2, x"0F"),
         10=>cmd(or_r, r4, r2, r3),
    	 11=>cmd(xorr, r5, r3, r3),
         others=> nop
         );
      constant tP: delay_length := 10 ns;
      constant trace_length: natural := 14;
    
    begin
     DUT: entity work.risc port map(T, I, imem, dmem, ps, dmem_wr);
    
     I <= '1', '0' after tP;
     
     process
    
     begin
      report(lf&"=====Program=========================");
      for idx in imem'range loop
        report(hex(to_bitvec(idx, 16)) & ": " & str_ir(imem(idx)));
      end loop;
    
      report(lf & c_proc_state);
      wait for tP;
      
      while uint(ps.PC)<=imem'high and now<=(trace_length * tP) loop
       T <= '1' after tP/2, '0' after tP; wait for tP;
       report(str(ps));
       if dmem_wr then  report("str(dmem) = " & str(dmem)); end if;
      end loop; 
      wait;
     end process;
    
    end architecture;
    
  • Testrahmen mit Verschiebebefehlen:
  • -- Foliensatz RA-F1, Abschnitt ?.?
    -- Datei: test_risc_shift.vhd
    
    -- Testbeispiel mit Schiebe- und Rotationsbefehlen
    --  Linksverschiebung von r0:r1 um drei Bitstellen
    
    -- letzte Aenderung: 21.03.2018
    -- Autor: G. Kemnitz
    
    --PC| Instruction |Cmd |O1|O2|OR|c|z|RA|RB|W|r0 r1 r2 r3 r4 r5 r6 r7
    --01|ld_i r1,73,..|noop|00|00|00|0|0|r0|r0|-|00 00 00 00 00 00 00 00
    --02|ld_i r0,3a,..|ld_i|73|00|00|0|0|r1|r0|-|00 00 00 00 00 00 00 00
    --03|noop ..,..,..|ld_i|3a|00|73|0|0|r0|r1|R|00 00 00 00 00 00 00 00
    --04|sh_l r3,r1,..|noop|00|00|3a|0|0|r0|r0|R|00 73 00 00 00 00 00 00
    --05|rotl r2,r0,..|sh_l|73|00|3a|0|0|r3|r0|-|3a 73 00 00 00 00 00 00
    --06|noop ..,..,..|rotl|3a|00|e6|0|0|r2|r3|R|3a 73 00 00 00 00 00 00
    --07|sh_l r5,r3,..|noop|00|00|74|0|0|r0|r2|R|3a 73 00 e6 00 00 00 00
    --08|rotl r4,r2,..|sh_l|e6|00|74|0|0|r5|r0|-|3a 73 74 e6 00 00 00 00
    --09|noop ..,..,..|rotl|74|00|cc|1|0|r4|r5|R|3a 73 74 e6 00 00 00 00
    --0a|sh_l r7,r5,..|noop|00|00|e9|0|0|r0|r4|R|3a 73 74 e6 00 cc 00 00
    --0b|rotl r6,r4,..|sh_l|cc|00|e9|0|0|r7|r0|-|3a 73 74 e6 e9 cc 00 00
    --0c|noop ..,..,..|rotl|e9|00|98|1|0|r6|r7|R|3a 73 74 e6 e9 cc 00 00
    --0d|noop ..,..,..|noop|00|00|d3|1|0|r0|r6|R|3a 73 74 e6 e9 cc 00 98
    --0e|noop ..,..,..|noop|00|00|d3|1|0|r0|r0|-|3a 73 74 e6 e9 cc d3 98
    
    use work.risc_pack.all;
    
    entity test_risc is end entity;
    
    architecture a of test_risc is
      signal T, I: bit;
      signal dmem: t_dmem(0 to 7);
      signal ps: t_proc_state;
      signal dmem_wr: boolean;
      constant imem: t_imem(0 to 13) := (
          0=>cmd(ld_i, r1, x"73"),
          1=>cmd(ld_i, r0, x"3a"),
          3=>cmd(sh_l, r3, r1),
          4=>cmd(rotl, r2, r0),
          6=>cmd(sh_l, r5, r3),
          7=>cmd(rotl, r4, r2),
          9=>cmd(sh_l, r7, r5),
         10=>cmd(rotl, r6, r4),
         others=> nop
         );
      constant tP: delay_length := 10 ns;
      constant trace_length: natural := 14;
    
    begin
     DUT: entity work.risc port map(T, I, imem, dmem, ps, dmem_wr);
    
     I <= '1', '0' after tP;
     
     process
    
     begin
      report(lf&"=====Program=========================");
      for idx in imem'range loop
        report(hex(to_bitvec(idx, 16)) & ": " & str_ir(imem(idx)));
      end loop;
    
      report(lf & c_proc_state);
      wait for tP;
      
      while uint(ps.PC)<=imem'high and now<=(trace_length * tP) loop
       T <= '1' after tP/2, '0' after tP; wait for tP;
       report(str(ps));
       if dmem_wr then  report("str(dmem) = " & str(dmem)); end if;
      end loop; 
      wait;
     end process;
    
    end architecture;
    
  • Testrahmen für Additions- und Subtraktionsbefehle:
  • -- Foliensatz RA-F1, Abschnitt ?.?
    
    -- Testbeispiel mit Additionen und Subtraktionen:
    --  r0:r1 = 733A
    --  r2:r3 = 13E7
    --  r4:r5 = r0:r1 + r2:r3    (Ergebnis: 8721) 
    --  r4:r5 = 8623 - r4:r5     (Ergebnis: FF02)
    
    -- letzte Aenderung: 21.03.2018
    -- Autor: G. Kemnitz
    
    --PC| Instruction |Cmd |O1|O2|OR|c|z|RA|RB|W|r0 r1 r2 r3 r4 r5 r6 r7
    --01|ld_i r1,3a,..|noop|00|00|00|0|0|r0|r0|-|00 00 00 00 00 00 00 00
    --02|ld_i r0,73,..|ld_i|3a|00|00|0|0|r1|r0|-|00 00 00 00 00 00 00 00
    --03|ld_i r3,e7,..|ld_i|73|00|3a|0|0|r0|r1|R|00 00 00 00 00 00 00 00
    --04|ld_i r2,13,..|ld_i|e7|00|73|0|0|r3|r0|R|00 3a 00 00 00 00 00 00
    --05|noop ..,..,..|ld_i|13|00|e7|0|0|r2|r3|R|73 3a 00 00 00 00 00 00
    --06|addr r5,r1,r3|noop|00|00|13|0|0|r0|r2|R|73 3a 00 e7 00 00 00 00
    --07|adcr r4,r0,r2|addr|3a|e7|13|0|0|r5|r0|-|73 3a 13 e7 00 00 00 00
    --08|noop ..,..,..|adcr|73|13|21|1|0|r4|r5|R|73 3a 13 e7 00 00 00 00
    --09|subi r5,23,..|noop|00|00|87|0|0|r0|r4|R|73 3a 13 e7 00 21 00 00
    --0a|sbci r4,86,..|subi|23|21|87|0|0|r5|r0|-|73 3a 13 e7 87 21 00 00
    --0b|noop ..,..,..|sbci|86|87|02|0|0|r4|r5|R|73 3a 13 e7 87 21 00 00
    --0c|noop ..,..,..|noop|00|00|ff|1|0|r0|r4|R|73 3a 13 e7 87 02 00 00
    --0d|noop ..,..,..|noop|00|00|ff|1|0|r0|r0|-|73 3a 13 e7 ff 02 00 00
    
    
    use work.risc_pack.all;
    
    entity test_risc is end entity;
    
    architecture a of test_risc is
      signal T, I: bit;
      signal dmem: t_dmem(0 to 7);
      signal ps: t_proc_state;
      signal dmem_wr: boolean;
      constant imem: t_imem(0 to 12) := (
          0=>cmd(ld_i, r1, x"3a"),
          1=>cmd(ld_i, r0, x"73"),
          2=>cmd(ld_i, r3, x"E7"),
          3=>cmd(ld_i, r2, x"13"),
          5=>cmd(addr, r5, r1,r3),
          6=>cmd(adcr, r4, r0, r2),
    	  8=>cmd(subi, r5, x"23"),
          9=>cmd(sbci, r4, x"86"),
          others=> nop
          );
      constant tP: delay_length := 10 ns;
      constant trace_length: natural := 14;
    
    begin
     DUT: entity work.risc port map(T, I, imem, dmem, ps, dmem_wr);
    
     I <= '1', '0' after tP;
     
     process
    
     begin
      report(lf&"=====Program=========================");
      for idx in imem'range loop
        report(hex(to_bitvec(idx, 16)) & ": " & str_ir(imem(idx)));
      end loop;
    
      report(lf & c_proc_state);
      wait for tP;
      
      while uint(ps.PC)<=imem'high and now<=(trace_length * tP) loop
       T <= '1' after tP/2, '0' after tP; wait for tP;
       report(str(ps));
       if dmem_wr then  report("str(dmem) = " & str(dmem)); end if;
      end loop; 
      wait;
     end process;
    
    end architecture;
    
  • Testrahmen für Lade- und Speicherbefehle:
  • -- Foliensatz RA-F1, Abschnitt ?.?
    
    -- Testbeispiel mit Additionen und Subtraktionen:
    --  r0:r1 = 733A
    --  r2:r3 = 13E7
    --  r4:r5 = r0:r1 + r2:r3    (Ergebnis: 8721) 
    --  r4:r5 = 8623 - r4:r5     (Ergebnis: FF02)
    
    -- letzte Aenderung: 21.03.2018
    -- Autor: G. Kemnitz
    
    --PC| Instruction |Cmd |O1|O2|OR|c|z|RA|RB|W|r0 r1 r2 r3 r4 r5 r6 r7
    --01|ld_i r1,3a,..|noop|00|00|00|0|0|r0|r0|-|00 00 00 00 00 00 00 00
    --02|ld_i r0,73,..|ld_i|3a|00|00|0|0|r1|r0|-|00 00 00 00 00 00 00 00
    --03|ld_i r3,e7,..|ld_i|73|00|3a|0|0|r0|r1|R|00 00 00 00 00 00 00 00
    --04|ld_i r2,13,..|ld_i|e7|00|73|0|0|r3|r0|R|00 3a 00 00 00 00 00 00
    --05|noop ..,..,..|ld_i|13|00|e7|0|0|r2|r3|R|73 3a 00 00 00 00 00 00
    --06|addr r5,r1,r3|noop|00|00|13|0|0|r0|r2|R|73 3a 00 e7 00 00 00 00
    --07|adcr r4,r0,r2|addr|3a|e7|13|0|0|r5|r0|-|73 3a 13 e7 00 00 00 00
    --08|noop ..,..,..|adcr|73|13|21|1|0|r4|r5|R|73 3a 13 e7 00 00 00 00
    --09|subi r5,23,..|noop|00|00|87|0|0|r0|r4|R|73 3a 13 e7 00 21 00 00
    --0a|sbci r4,86,..|subi|23|21|87|0|0|r5|r0|-|73 3a 13 e7 87 21 00 00
    --0b|noop ..,..,..|sbci|86|87|02|0|0|r4|r5|R|73 3a 13 e7 87 21 00 00
    --0c|noop ..,..,..|noop|00|00|ff|1|0|r0|r4|R|73 3a 13 e7 87 02 00 00
    --0d|noop ..,..,..|noop|00|00|ff|1|0|r0|r0|-|73 3a 13 e7 ff 02 00 00
    
    
    use work.risc_pack.all;
    
    entity test_risc is end entity;
    
    architecture a of test_risc is
      signal T, I: bit;
      signal dmem: t_dmem(0 to 7);
      signal ps: t_proc_state;
      signal dmem_wr: boolean;
      constant imem: t_imem(0 to 12) := (
          0=>cmd(ld_i, r1, x"3a"),
          1=>cmd(ld_i, r0, x"73"),
          2=>cmd(ld_i, r3, x"E7"),
          3=>cmd(ld_i, r2, x"13"),
          5=>cmd(addr, r5, r1,r3),
          6=>cmd(adcr, r4, r0, r2),
    	  8=>cmd(subi, r5, x"23"),
          9=>cmd(sbci, r4, x"86"),
          others=> nop
          );
      constant tP: delay_length := 10 ns;
      constant trace_length: natural := 14;
    
    begin
     DUT: entity work.risc port map(T, I, imem, dmem, ps, dmem_wr);
    
     I <= '1', '0' after tP;
     
     process
    
     begin
      report(lf&"=====Program=========================");
      for idx in imem'range loop
        report(hex(to_bitvec(idx, 16)) & ": " & str_ir(imem(idx)));
      end loop;
    
      report(lf & c_proc_state);
      wait for tP;
      
      while uint(ps.PC)<=imem'high and now<=(trace_length * tP) loop
       T <= '1' after tP/2, '0' after tP; wait for tP;
       report(str(ps));
       if dmem_wr then  report("str(dmem) = " & str(dmem)); end if;
      end loop; 
      wait;
     end process;
    
    end architecture;
    
  • Testrahmen mit einem Programm mit einer Schleife:
  • -- Foliensatz RA-F1, Abschnitt ?.?
    
    -- Testbeispiel mit Schleife
    --    r0 = 1; r1 = 34;
    -- M: dmem(r0) = r1;
    --    r1 = r1 - r0;
    --    r0 = r0 +1;
    --    wenn r0 <= 3 springe zu M (2x fuer r0=2 und 3)
    
    -- letzte Aenderung: 21.03.2018
    -- Autor: G. Kemnitz
    
    --PC| Instruction |Cmd |O1|O2|OR|c|z|RA|RB|W|r0 r1 r2 r3 r4 r5 r6 r7
    --01|ld_i r0,01,..|noop|00|00|00|0|0|r0|r0|-|00 00 00 00 00 00 00 00
    --02|ld_i r1,34,..|ld_i|01|00|00|0|0|r0|r0|-|00 00 00 00 00 00 00 00
    --03|noop ..,..,..|ld_i|34|00|01|0|0|r1|r0|R|00 00 00 00 00 00 00 00
    --04|comp r0,03,..|noop|00|00|34|0|0|r0|r1|R|01 00 00 00 00 00 00 00
    --05|st_r r1,r0,..|comp|03|01|34|0|0|r0|r0|-|01 34 00 00 00 00 00 00
    --06|jump 02,lth..|st_r|01|00|02|0|0|r1|r0|-|01 34 00 00 00 00 00 00
    --07|addi r0,01,..|jump|02|07|01|0|0|r7|r1|S|01 34 00 00 00 00 00 00
    --02|subr r1,r1,r0|addi|01|01|01|0|0|r0|r7|-|01 34 00 00 00 00 00 00
    --str(dmem) = 00 34 00 00 00 00 00 00
    --03|noop ..,..,..|subr|34|01|02|0|0|r1|r0|R|01 34 00 00 00 00 00 00
    --04|comp r0,03,..|noop|00|00|33|0|0|r0|r1|R|02 34 00 00 00 00 00 00
    --05|st_r r1,r0,..|comp|03|02|33|0|0|r0|r0|-|02 33 00 00 00 00 00 00
    --06|jump 02,lth..|st_r|02|00|01|0|0|r1|r0|-|02 33 00 00 00 00 00 00
    --07|addi r0,01,..|jump|02|07|02|0|0|r7|r1|S|02 33 00 00 00 00 00 00
    --02|subr r1,r1,r0|addi|01|02|02|0|0|r0|r7|-|02 33 00 00 00 00 00 00
    --str(dmem) = 00 34 33 00 00 00 00 00
    --03|noop ..,..,..|subr|33|02|03|0|0|r1|r0|R|02 33 00 00 00 00 00 00
    --04|comp r0,03,..|noop|00|00|31|0|0|r0|r1|R|03 33 00 00 00 00 00 00
    --05|st_r r1,r0,..|comp|03|03|31|0|0|r0|r0|-|03 31 00 00 00 00 00 00
    --06|jump 02,lth..|st_r|03|00|00|0|1|r1|r0|-|03 31 00 00 00 00 00 00
    --07|addi r0,01,..|jump|02|07|03|0|1|r7|r1|S|03 31 00 00 00 00 00 00
    --08|subr r1,r1,r0|addi|01|03|03|0|1|r0|r7|-|03 31 00 00 00 00 00 00
    --str(dmem) = 00 34 33 31 00 00 00 00
    --09|noop ..,..,..|subr|31|03|04|0|0|r1|r0|R|03 31 00 00 00 00 00 00
    --0a|noop ..,..,..|noop|00|00|2e|0|0|r0|r1|R|04 31 00 00 00 00 00 00
    --0b|noop ..,..,..|noop|00|00|2e|0|0|r0|r0|-|04 2e 00 00 00 00 00 00
    
    
    use work.risc_pack.all;
    entity test_risc is end entity;
    
    architecture a of test_risc is
      signal T, I: bit;
      signal dmem: t_dmem(0 to 7);
      signal ps: t_proc_state;
      signal dmem_wr: boolean;
      constant imem: t_imem(0 to 10) := (
          0=>cmd(ld_i, r0, x"01"),
          1=>cmd(ld_i, r1, x"34"),
          3=>cmd(comp, r0,x"03"),
          4=>cmd(st_r, r1, r0),
          5=>jmp(x"02", lth),
          6=>cmd(addi, r0, x"01"),
          7=>cmd(subr, r1, r1, r0),
          others=> nop
          );
      constant tP: delay_length := 10 ns;
      constant trace_length: natural := 23;
    
    begin
     DUT: entity work.risc port map(T, I, imem, dmem, ps, dmem_wr);
    
     I <= '1', '0' after tP;
     
     process
    
     begin
      report(lf&"=====Program=========================");
      for idx in imem'range loop
        report(hex(to_bitvec(idx, 16)) & ": " & str_ir(imem(idx)));
      end loop;
    
      report(lf & c_proc_state);
      wait for tP;
      
      while uint(ps.PC)<=imem'high and now<=(trace_length * tP) loop
       T <= '1' after tP/2, '0' after tP; wait for tP;
       report(str(ps));
       if dmem_wr then  report("str(dmem) = " & str(dmem)); end if;
      end loop; 
      wait;
     end process;
    
    end architecture;
    


Autor: gkemnitz, Letzte Änderung: 26.11.2020 16:26:45


 TU Clausthal 2020  Impressum