diff --git a/cMIPS/bin/build.sh b/cMIPS/bin/build.sh
index d372760297fd6d9cc3f2fa1598419f88ccb08fc8..8b766acb3b22e622219a41dcb6650a876bb28d46 100755
--- a/cMIPS/bin/build.sh
+++ b/cMIPS/bin/build.sh
@@ -66,7 +66,7 @@ simulator=tb_cmips
 
 pkg="packageWires.vhd packageMemory.vhd packageExcp.vhd"
 
-src="aux.vhd altera.vhd macnica.vhd memory.vhd cache.vhd instrcache.vhd ram.vhd rom.vhd units.vhd io.vhd uart.vhd fpu.vhd pipestages.vhd exception.vhd core.vhd tb_cMIPS.vhd"
+src="aux.vhd altera.vhd macnica.vhd memory.vhd cache.vhd instrcache.vhd sdram.vhd ram.vhd rom.vhd units.vhd io.vhd uart.vhd fpu.vhd pipestages.vhd exception.vhd core.vhd tb_cMIPS.vhd"
 
 # build simulator
 #ghdl --clean
diff --git a/cMIPS/vhdl/sdram.vhd b/cMIPS/vhdl/sdram.vhd
index 0e0ec2fa1cc9b24695e74e816fe7367ce1372952..f768f41bfa8ff321153e837ea5c4b9da5cdb933d 100644
--- a/cMIPS/vhdl/sdram.vhd
+++ b/cMIPS/vhdl/sdram.vhd
@@ -33,12 +33,12 @@ use work.p_wires.all;
 use work.p_memory.all;
 
 entity SDRAM_controller is
-  port (rst      : in    std_logic;     -- FPGA reset
-        clk      : in    std_logic;     -- 100MHz clock
+  port (rst      : in    std_logic;     -- FPGA reset (=0)
+        clk2x    : in    std_logic;     -- 100MHz clock
 
-        hcs      : in    std_logic;     -- host side chip select
-        rdy      : in    std_logic;     -- tell CPU to wait 
-        wr       : in    std_logic;     -- host side write enable
+        hcs      : in    std_logic;     -- host side chip select (=0)
+        rdy      : in    std_logic;     -- tell CPU to wait (=0)
+        wr       : in    std_logic;     -- host side write enable (=0)
         bsel     : in    reg4;          -- byte select
         haddr    : in    reg26;         -- host side address
         hDinp    : in    reg32;         -- host side data input
@@ -54,16 +54,60 @@ entity SDRAM_controller is
         ba0      : out   std_logic;     -- ram side bank select 0
         ba1      : out   std_logic;     -- ram side bank select 1
         saddr    : out   reg12;         -- ram side address
-        sdata    :inout  reg16);        -- ram side data
+        sdata    : inout  reg16);       -- ram side data
 
-  type sdram_cmd is (cmd_NOP, cmd_PALL, cmd_ARF, cmd_LMR, cmd_ACT,
-    cmd_RD, cmd_WR, cmd_invalid);
+  constant REFRESH_doit : integer := 704;  -- force a refresh every 704 cycles
+
+  subtype cmd_index is integer range 0 to 13;
   
-end entity SDRAM_controller;
+  constant cDSL  : cmd_index := 0;
+  constant cNOP  : cmd_index := 1;
+  constant cBST  : cmd_index := 2;
+  constant cRD   : cmd_index := 3;
+  constant cRDA  : cmd_index := 4;
+  constant cWR   : cmd_index := 5;
+  constant cWRA  : cmd_index := 6;
+  constant cACT  : cmd_index := 7;
+  constant cPRE  : cmd_index := 8;
+  constant cPALL : cmd_index := 9;
+  constant cREF  : cmd_index := 10;
+  constant cSELF : cmd_index := 11;
+  constant cMRS  : cmd_index := 12;
+  constant cinv  : cmd_index := 13;
+
+  type t_cmd_type is record
+    cmd: cmd_index;
+    cs:  std_logic;
+    ras: std_logic;
+    cas: std_logic;
+    we:  std_logic;
+    a10: std_logic;
+  end record;
 
+  type t_cmd_mem is array (0 to 12) of t_cmd_type;
+
+  
+end entity SDRAM_controller;
 
 architecture simple of SDRAM_controller is
 
+  constant cmd_table : t_cmd_mem := (  -- page 9
+  -- cmd    cs ras cas we  a10
+    (cDSL, '1','1','1','1','1'),        -- DESL device deselect
+    (cNOP, '0','1','1','1','1'),        -- NOP no operation
+    (cBST, '0','1','1','0','1'),        -- BST burst stop
+    (cRD,  '0','1','0','1','0'),        -- RD read
+    (cRDA, '0','1','0','1','1'),        -- RDA read with auto precharge
+    (cWR,  '0','1','0','0','0'),        -- WR write
+    (cWRA, '0','1','0','0','1'),        -- WR write with auto precharge
+    (cACT, '0','0','1','1','1'),        -- ACT bank activate
+    (cPRE, '0','0','1','0','0'),        -- PRE precharge selected bank
+    (cPALL,'0','0','1','0','1'),        -- PALL precharge all banks
+    (cREF, '0','0','0','1','1'),        -- REF CBR auto-refresh
+    (cSELF,'0','0','0','1','1'),        -- SELF self-refresh
+    (cMRS, '0','0','0','0','0')         -- MRS mode register set
+);
+
   component registerN is
     generic (NUM_BITS: integer; INIT_VAL: std_logic_vector);
     port(clk, rst, ld: in  std_logic;
@@ -71,52 +115,318 @@ architecture simple of SDRAM_controller is
          Q:            out std_logic_vector);
   end component registerN;
 
-  signal reset_done, same_row : boolean := FALSE;
+  -- state machine
+  type ctrl_state is
+    (st_noreset,                        -- 0
+     st_in0, st_in1, st_ipre, st_in2,   -- 4
+     st_aref1, st_1n0, st_1n1, st_1n2, st_1n3, st_1n4, st_1n5,  -- 11
+     st_aref2, st_2n0, st_2n1, st_2n2, st_2n3, st_2n4, st_2n5,  -- 18
+     st_aref3, st_3n0, st_3n1, st_3n2, st_3n3, st_3n4, st_3n5,  -- 25
+     st_aref4, st_4n0, st_4n1, st_4n2, st_4n3, st_4n4, st_4n5,  -- 32
+     st_lmr, st_ln0, st_ln1,            -- 35
+     st_pall, st_pn0, st_pn1,           -- 38
+     st_refr, st_rn0, st_rn1, st_rn2, st_rn3, st_rn4, st_rn5,  -- 45
+     st_idle2,                          -- 46
+     st_act, st_an0, st_an1,            -- 49
+     st_rdcol, st_rdn0, st_rd_done,     -- 52
+     st_wrcol,                          -- 53
+     st_idle);                          -- 54
+  
+  signal curr_st, next_st : ctrl_state;
+  signal ctrl_dbg_st : integer;         -- for debugging only
+  
+  signal reset_done, same_row, do_refresh, refresh_done : boolean := FALSE;
+  signal is_accs, is_rd, is_wr : boolean := FALSE;
   signal addr : reg26;
-  signal last_row : reg13;
+  signal row_bits, last_row : reg13;
   signal col_bits : reg10;
   signal rwo_bits : reg13;
+  signal ld_old : std_logic;
+  signal command : t_cmd_type;
+  signal doit : cmd_index;
   
 begin  -- simple
 
- 
+  command  <= cmd_table(doit);
+  scs  <= command.cs;
+  ras  <= command.ras;
+  cas  <= command.cas;
+  we   <= command.we;
+
+  saddr(10) <= addr(10) when command.cmd = cACT else
+               command.a10;
+  
   U_address: registerN  generic map (26, b"00"&x"000000")
-    port map (clk, rst, hcs, haddr, addr);
+    port map (clk2x, rst, hcs, haddr, addr);
 
   row_bits <= addr(23 downto 11);
   col_bits <= addr(10 downto 1);
   ba0 <= addr(24);
   ba1 <= addr(25);
+
   
-  U_last_row: registerN  generic map (13, '0'&x"000")
-    port map (clk, rst, active, haddr(23 downto 11), last_row);
+  ld_old <= hcs and not(BOOL2SL(same_row));
+  U_last_row: registerN  generic map (13, '1'&x"fff")
+    port map (clk2x, rst, ld_old, haddr(23 downto 11), last_row);
+  same_row <= (last_row = row_bits) and (command.cmd /= cPALL);
+
 
   
 
+  -- this state machine contols the SDRAM interface -----------------------
+  U_CTRL_st_reg: process(rst,clk2x)
+  begin
+    if rst = '0' then
+      curr_st <= st_noreset;
+    elsif rising_edge(clk2x) then
+      curr_st <= next_st;
+    end if;
+  end process U_CTRL_st_reg; ----------------------------------------------
+
+  ctrl_dbg_st <= integer(ctrl_state'pos(curr_st)); -- for debugging
+
+    
+  U_CTRL_st_transitions: process(curr_st, reset_done, do_refresh, -------
+                                 same_row, is_accs, is_rd, is_wr)
+  begin
+    case curr_st is
+
+      -- WAIT FOR POWER-ON RESET TO COMPLETE
+      when st_noreset =>                -- 0
+        if reset_done then
+          next_st <= st_in0;
+        else
+          next_st <= st_noreset;
+        end if;
 
+      -- INITIALIZATION SEQUENCE
+      when st_in0 =>                    -- 1 nop
+        next_st <= st_in1;
+      when st_in1 =>                    -- 2 nop
+        next_st <= st_ipre;
+      when st_ipre =>                   -- 3 precharge all banks
+        next_st <= st_in2;
+      when st_in2 =>                    -- 4 nop
+        next_st <= st_aref1;
 
+      when st_aref1 =>                  -- 5 auto refresh 1 + 60ns delay
+        next_st <= st_1n0;
+      when st_1n0 =>                    -- 6 nop
+        next_st <= st_1n1;
+      when st_1n1 =>                    -- 7 nop
+        next_st <= st_1n2;
+      when st_1n2 =>                    -- 8 nop
+        next_st <= st_1n3;
+      when st_1n3 =>                    -- 9 nop
+        next_st <= st_1n4;
+      when st_1n4 =>                    -- 10 nop
+        next_st <= st_1n5;
+      when st_1n5 =>                    -- 11 nop
+        next_st <= st_aref2;
+      
+      when st_aref2 =>                  -- 12 auto refresh 2 + 60ns delay
+        next_st <= st_2n0;
+      when st_2n0 =>                    -- 13 nop
+        next_st <= st_2n1;
+      when st_2n1 =>                    -- 14 nop
+        next_st <= st_2n2;
+      when st_2n2 =>                    -- 15 nop
+        next_st <= st_2n3;
+      when st_2n3 =>                    -- 16 nop
+        next_st <= st_2n4;
+      when st_2n4 =>                    -- 17 nop
+        next_st <= st_2n5;
+      when st_2n5 =>                    -- 18 nop
+        next_st <= st_aref3;
+      
+      when st_aref3 =>                  -- 19 auto refresh 3 + 60ns delay
+        next_st <= st_3n0;
+      when st_3n0 =>                    -- 20 nop
+        next_st <= st_3n1;
+      when st_3n1 =>                    -- 21 nop
+        next_st <= st_3n2;
+      when st_3n2 =>                    -- 22 nop
+        next_st <= st_3n3;
+      when st_3n3 =>                    -- 23 nop
+        next_st <= st_3n4;
+      when st_3n4 =>                    -- 24 nop
+        next_st <= st_3n5;
+      when st_3n5 =>                    -- 25 nop
+        next_st <= st_aref4;
+      
+      when st_aref4 =>                  -- 26 auto refresh 4 + 60ns delay
+        next_st <= st_4n0;
+      when st_4n0 =>                    -- 27 nop
+        next_st <= st_4n1;
+      when st_4n1 =>                    -- 28 nop
+        next_st <= st_4n2;
+      when st_4n2 =>                    -- 29 nop
+        next_st <= st_4n3;
+      when st_4n3 =>                    -- 30 nop
+        next_st <= st_4n4;
+      when st_4n4 =>                    -- 31 nop
+        next_st <= st_4n5;
+      when st_4n5 =>                    -- 32 nop
+        next_st <= st_lmr;
+      
+      when st_lmr =>                    -- 33 load mode register + 2 nops
+        next_st <= st_ln0;
+      when st_ln0 =>                    -- 34 nop
+        next_st <= st_ln1;
+      when st_ln1 =>                    -- 35 nop
+        next_st <= st_idle;
 
+      -- AUTO-REFRESH SEQUENCE 
+      when st_pall =>                   -- 36 precharge all banks + 2 nops
+        next_st <= st_pn0;
+      when st_pn0 =>                    -- 37 nop
+        next_st <= st_pn1;
+      when st_pn1 =>                    -- 38 nop
+        next_st <= st_refr;
+        
+      when st_refr =>                   -- 39 auto refresh + 60ns delay
+        next_st <= st_rn0;
+      when st_rn0 =>                    -- 40 nop
+        next_st <= st_rn1;
+      when st_rn1 =>                    -- 41 nop
+        next_st <= st_rn2;
+      when st_rn2 =>                    -- 42 nop
+        next_st <= st_rn3;
+      when st_rn3 =>                    -- 43 nop
+        next_st <= st_rn4;
+      when st_rn4 =>                    -- 44 nop
+        next_st <= st_rn5;
+      when st_rn5 =>                    -- 45 nop; sameRow was cleared
+        next_st <= st_idle2;
+
+      when st_idle2 =>                  -- 46
+        if is_accs then                 -- is post-refresh access, activate row
+          next_st <= st_act;
+        else
+          next_st <= st_idle2;
+        end if;
+
+      -- ACTIVATE NEW ROW
+      when st_act =>                    -- 47 activate row + 2 nops
+        next_st <= st_an0;
+      when st_an0 =>                    -- 48 nop
+        next_st <= st_an1;
+      when st_an1 =>                    -- 49 nop
+        if is_rd then
+          next_st <= st_rdcol;          -- access is a read, set column
+        else
+          next_st <= st_wrcol;          -- access is a write, set column
+        end if;
+
+      -- READ FROM COLUMN
+      when st_rdcol =>                  -- 50 set column for RD + 2 nops
+        next_st <= st_rdn0;
+      when st_rdn0 =>                   -- 51 nop
+        next_st <= st_rd_done;
+      when st_rd_done =>                -- 52 nop
+        if do_refresh then
+          next_st <= st_pall;           -- go to refresh sequence
+        else
+          next_st <= st_idle;           -- wait for next access to same row
+        end if;
+
+      -- WRITE TO COLUMN
+      when st_wrcol =>                  -- 53 set column for WR
+        if do_refresh then
+          next_st <= st_pall;           -- go to refresh sequence
+        else
+          next_st <= st_idle;           -- wait for next access to same row
+        end if;
+        
+      when st_idle =>                   -- 54
+        if is_accs and not(same_row) then
+          next_st <= st_act;
+        elsif is_rd then
+          next_st <= st_rdcol;
+        elsif is_wr then
+          next_st <= st_rdcol;
+        else
+          next_st <= st_idle;
+        end if;
+      when others =>
+        assert false report "CTRL stateMachine broken"
+          & integer'image(ctrl_state'pos(curr_st)) severity failure;
+    end case;
+  end process U_CTRL_st_transitions;   ------------------------------------
 
 
   
+  U_CTRL_outputs: process(curr_st)  ------------------------------
+  begin
+    case curr_st is
+      when st_rdcol =>
+        doit <= cRD;                    -- read from column
+        
+      when st_wrcol =>
+        doit <= cWR;                    -- write to column
+        
+      when st_ipre | st_pall =>
+        doit <= cPALL;                  -- precharge all banks
 
-  -- purpose: wait for 100us after reset
-  U_rst_100us: process (clk2x,rst)
-    variable cnt : integer := 0;
-  begin  -- process clk2x
+      when st_aref1 | st_aref2 | st_aref3 | st_aref4 =>
+        doit <= cREF;                   -- auto-refresh
+
+      when st_lmr =>
+        doit <= cMRS;                   -- load mode register
+
+      when st_act =>
+        doit <= cACT;                   -- activate row
+
+      when others =>
+        doit <= cNOP;
+    end case;
+  end process U_CTRL_outputs;   -------------------------------------------
+
+
+
+
+  
+
+  -- do a refresh in less than 7,8us (8192 in 64ms @ 100MHz)
+  U_do_refresh: process (rst, clk2x, refresh_done)
+    variable cnt : integer range 0 to 1023:= 0;
+  begin
     if rst = '0' then
+      do_refresh <= FALSE;
       cnt := 0;
-      reset_done <= FALSE;
-    elsif rising_edge(clk) then
-      cnt := cnt + 1;
-      if cnt = 10000 then               -- 100us elapsed
-        reset_done <= TRUE;
-        wait;
+    elsif rising_edge(clk2x) then
+      if cnt > REFRESH_doit then
+        if refresh_done then
+          do_refresh <= FALSE;
+          cnt := 0;
+        else
+          do_refresh <= TRUE;           -- add some hysteresis
+          cnt := cnt + 1;               --   to accomodate slow commands
+        end if;
+      else
+        do_refresh <= FALSE;
+        cnt := cnt + 1;
       end if;
     end if;
-  end process clk2x;
+  end process U_do_refresh;
+  
+
+  -- do wait for 100us after reset
+  U_rst_100us: process
+    variable cnt : integer range 0 to 16383:= 0;
+  begin  -- process clk2x
+    reset_done <= FALSE;
+    wait until rst = '1';
+    cnt := 0;
+    wait until rising_edge(clk2x);
+    cnt := cnt + 1;
+    if cnt = 10000 then               -- 100us elapsed
+      reset_done <= TRUE;
+      wait;
+    end if;
+  end process U_rst_100us;
  
 
 end simple;
-
+-- ---------------------------------------------------------------------
     
diff --git a/cMIPS/vhdl/tb_cMIPS.vhd b/cMIPS/vhdl/tb_cMIPS.vhd
index 982bacb25a4a871e5da62e99f2ff13090fb3649f..6f1919f8c8057eceaae2ff01f0fe66a3f4618f85 100644
--- a/cMIPS/vhdl/tb_cMIPS.vhd
+++ b/cMIPS/vhdl/tb_cMIPS.vhd
@@ -287,6 +287,29 @@ architecture TB of tb_cMIPS is
           dump_ram : in    std_logic);
   end component fpga_RAM;
 
+  component SDRAM_controller is
+    port (rst      : in    std_logic;     -- FPGA reset (=0)
+          clk2x    : in    std_logic;     -- 100MHz clock
+          hcs      : in    std_logic;     -- host side chip select (=0)
+          rdy      : in    std_logic;     -- tell CPU to wait (=0)
+          wr       : in    std_logic;     -- host side write enable (=0)
+          bsel     : in    reg4;          -- byte select
+          haddr    : in    reg26;         -- host side address
+          hDinp    : in    reg32;         -- host side data input
+          hDout    : out   reg32;         -- host side data output
+          cke      : out   std_logic;     -- ram side clock enable
+          scs      : out   std_logic;     -- ram side chip select
+          ras      : out   std_logic;     -- ram side RAS
+          cas      : out   std_logic;     -- ram side CAS
+          we       : out   std_logic;     -- ram side write enable
+          dqm0     : out   std_logic;     -- ram side byte0 output enable
+          dqm1     : out   std_logic;     -- ram side byte0 output enable
+          ba0      : out   std_logic;     -- ram side bank select 0
+          ba1      : out   std_logic;     -- ram side bank select 1
+          saddr    : out   reg12;         -- ram side address
+          sdata    : inout reg16);        -- ram side data
+  end component SDRAM_controller;
+    
   component fake_I_CACHE is
     port (rst      : in    std_logic;
           clk4x    : in    std_logic;
@@ -477,6 +500,27 @@ architecture TB of tb_cMIPS is
   signal LCD_DATA : std_logic_vector(7 downto 0);  -- LCD data bus
   signal LCD_RS, LCD_RW, LCD_EN, LCD_BLON : std_logic;  -- LCD control
   signal uart_txd, uart_rxd, uart_rts, uart_cts, uart_irq : std_logic;
+
+
+ signal        hcs      :     std_logic;     -- host side chip select (=0)
+  signal   sdram_rdy    :     std_logic;     -- host side chip select (=0)
+ signal          haddr    :     reg26;         -- host side address
+ signal          hDinp    :     reg32;         -- host side data input
+ signal          hDout    :    reg32;         -- host side data output
+ signal          sdcke      :   std_logic;     -- ram side clock enable
+ signal          sdscs      :   std_logic;     -- ram side chip select
+ signal          sdras      :   std_logic;     -- ram side RAS
+ signal          sdcas      :   std_logic;     -- ram side CAS
+ signal          sdwe       :   std_logic;     -- ram side write enable
+ signal          sddqm0     :   std_logic;     -- ram side byte0 output enable
+ signal          sddqm1     :   std_logic;     -- ram side byte0 output enable
+ signal          sdba0      :   std_logic;     -- ram side bank select 0
+ signal          sdba1      :   std_logic;     -- ram side bank select 1
+ signal          sdaddr    :    reg12;         -- ram side address
+ signal          sddata    :  reg16;        -- ram side data
+
+
+
   
 begin  -- TB
 
@@ -587,6 +631,10 @@ begin  -- TB
               mem_addr, datram_out, datram_inp, mem_xfer, dump_ram);
 
 
+  U_SDRAM_controller : SDRAM_controller port map 
+    (rst, clk,hcs,sdram_rdy,wr,cpu_xfer,haddr,hDinp,hDout,
+     sdcke,sdscs,sdras,sdcas,sdwe,sddqm0,sddqm1,sdba0,sdba1,sdaddr,sddata); 
+  
   
   U_to_stdout: to_stdout
     port map (rst,clk, io_stdout_sel, wr, cpu_data);