Skip to content
Snippets Groups Projects
Commit 2c424a99 authored by Roberto Hexsel's avatar Roberto Hexsel
Browse files

SDRAM controller's state machine written

parent eea4da3a
No related branches found
No related tags found
No related merge requests found
Pipeline #
......@@ -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
......
......@@ -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
......@@ -56,14 +56,58 @@ entity SDRAM_controller is
saddr : out reg12; -- ram side address
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;
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;
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;
-- purpose: wait for 100us after reset
U_rst_100us: process (clk2x,rst)
variable cnt : integer := 0;
begin -- process clk2x
-- 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
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;
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 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;
elsif rising_edge(clk) then
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 if;
end process clk2x;
end process U_rst_100us;
end simple;
-- ---------------------------------------------------------------------
......@@ -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;
......@@ -478,6 +501,27 @@ architecture TB of tb_cMIPS is
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);
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment