URL
https://opencores.org/ocsvn/simpcon/simpcon/trunk
Subversion Repositories simpcon
Compare Revisions
- This comparison shows the changes necessary to convert path
/
- from Rev 20 to Rev 21
- ↔ Reverse comparison
Rev 20 → Rev 21
/trunk/vhdl/sc_sys.vhd
0,0 → 1,258
-- |
-- sc_sys.vhd |
-- |
-- counter, interrrupt handling and watchdog bit |
-- |
-- Author: Martin Schoeberl martin@good-ear.com |
-- |
-- address map: |
-- |
-- 0 read clk counter, write irq ena |
-- 1 read 1 MHz counter, write timer val (us) + irq ack |
-- 2 write generates sw-int (for yield()) |
-- 3 write wd port |
-- 4 write generates SW exception, read exception reason |
-- |
-- todo: |
-- |
-- |
-- 2003-07-05 new IO standard |
-- 2003-08-15 us counter, irq added |
-- 2005-11-30 change interface to SimpCon |
-- 2006-01-11 added exception |
-- 2007-03-17 changed interrupts to records |
-- 2007-06-01 changed name from sc_cnt to sc_sys |
-- |
|
library ieee; |
use ieee.std_logic_1164.all; |
use ieee.numeric_std.all; |
|
use work.jop_types.all; |
|
entity sc_sys is |
|
generic (addr_bits : integer; |
clk_freq : integer; |
cpu_id : integer); |
port ( |
clk : in std_logic; |
reset : in std_logic; |
|
-- SimpCon interface |
|
address : in std_logic_vector(addr_bits-1 downto 0); |
wr_data : in std_logic_vector(31 downto 0); |
rd, wr : in std_logic; |
rd_data : out std_logic_vector(31 downto 0); |
rdy_cnt : out unsigned(1 downto 0); |
|
-- |
-- Interrupts from IO devices |
-- |
irq_in : out irq_in_type; |
exc_req : in exception_type; |
|
sync_out : in sync_out_type; |
sync_in : out sync_in_type; |
|
wd : out std_logic |
|
); |
end sc_sys ; |
|
architecture rtl of sc_sys is |
|
signal clock_cnt : std_logic_vector(31 downto 0); |
signal pre_scale : std_logic_vector(7 downto 0); |
signal us_cnt : std_logic_vector(31 downto 0); |
|
constant div_val : integer := clk_freq/1000000-1; |
|
signal timer_int : std_logic; |
signal yield_int : std_logic; |
signal int_ack : std_logic; |
|
signal timer : std_logic; |
signal yield : std_logic; |
|
signal irq_cnt : std_logic_vector(31 downto 0); |
signal timer_equ : std_logic; |
signal timer_dly : std_logic; |
|
signal exc_type : std_logic_vector(7 downto 0); |
|
signal cpu_identity : std_logic_vector(31 downto 0); |
|
|
begin |
|
cpu_identity <= std_logic_vector(to_unsigned(cpu_id,32)); |
rdy_cnt <= "00"; -- no wait states |
|
-- |
-- read cnt values |
-- |
process(clk, reset) |
begin |
|
if (reset='1') then |
rd_data <= (others => '0'); |
elsif rising_edge(clk) then |
|
if rd='1' then |
case address(2 downto 0) is |
when "000" => |
rd_data <= clock_cnt; |
when "001" => |
rd_data <= us_cnt; |
when "100" => |
rd_data(7 downto 0) <= exc_type; |
rd_data(31 downto 8) <= (others => '0'); |
when "110" => |
rd_data <= cpu_identity; |
-- when "111" => |
when others => |
rd_data(0) <= sync_out.s_out; |
rd_data(31 downto 1) <= (others => '0'); |
end case; |
end if; |
end if; |
|
end process; |
|
-- |
-- compare timer value and us counter |
-- and generate single shot |
-- |
process(us_cnt, irq_cnt) begin |
timer_equ <= '0'; |
if us_cnt = irq_cnt then |
timer_equ <= '1'; |
end if; |
end process; |
|
process(clk, reset, timer_equ) begin |
if (reset='1') then |
timer_dly <= '0'; |
elsif rising_edge(clk) then |
timer_dly <= timer_equ; |
end if; |
end process; |
|
timer_int <= timer_equ and not timer_dly; |
|
-- |
-- int processing from timer and yield request |
-- |
process(clk, reset, timer_int, yield_int) begin |
|
if (reset='1') then |
timer <= '0'; |
yield <= '0'; |
elsif rising_edge(clk) then |
if int_ack='1' then |
timer <= '0'; |
yield <= '0'; |
else |
if timer_int='1' then |
timer <= '1'; |
end if; |
if yield_int='1' then |
yield <= '1'; |
end if; |
end if; |
end if; |
|
end process; |
|
irq_in.irq <= timer or yield; |
|
|
-- |
-- counters |
-- pre_scale is 8 bit => fmax = 255 MHz |
-- |
process(clk, reset) begin |
|
if (reset='1') then |
|
clock_cnt <= (others => '0'); |
us_cnt <= (others => '0'); |
pre_scale <= std_logic_vector(to_unsigned(div_val, pre_scale'length)); |
|
elsif rising_edge(clk) then |
|
clock_cnt <= std_logic_vector(unsigned(clock_cnt) + 1); |
pre_scale <= std_logic_vector(unsigned(pre_scale) - 1); |
if pre_scale = "00000000" then |
pre_scale <= std_logic_vector(to_unsigned(div_val, pre_scale'length)); |
us_cnt <= std_logic_vector(unsigned(us_cnt) + 1); |
end if; |
|
end if; |
end process; |
|
-- |
-- io write processing and exception processing |
-- |
process(clk, reset) |
|
begin |
if (reset='1') then |
|
irq_in.irq_ena <= '0'; |
irq_cnt <= (others => '0'); |
int_ack <= '0'; |
wd <= '0'; |
sync_in.s_in <= '0'; |
|
exc_type <= (others => '0'); |
irq_in.exc_int <= '0'; |
|
elsif rising_edge(clk) then |
|
int_ack <= '0'; |
yield_int <= '0'; |
|
irq_in.exc_int <= '0'; |
|
if exc_req.spov='1' then |
exc_type(2 downto 0) <= EXC_SPOV; |
irq_in.exc_int <= '1'; |
end if; |
if exc_req.np='1' then |
exc_type(2 downto 0) <= EXC_NP; |
irq_in.exc_int <= '1'; |
end if; |
if exc_req.ab='1' then |
exc_type(2 downto 0) <= EXC_AB; |
irq_in.exc_int <= '1'; |
end if; |
|
if wr='1' then |
case address(2 downto 0) is |
when "000" => |
irq_in.irq_ena <= wr_data(0); |
when "001" => |
irq_cnt <= wr_data; |
int_ack <= '1'; |
when "010" => |
yield_int <= '1'; |
when "011" => |
wd <= wr_data(0); |
when "100" => |
exc_type <= wr_data(7 downto 0); |
irq_in.exc_int <= '1'; |
when "110" => |
-- nothing, processor id is read only |
when others => |
-- when "111" => |
sync_in.s_in <= wr_data(0); |
end case; |
end if; |
|
end if; |
end process; |
|
end rtl; |
/trunk/vhdl/sc_sram32_flash.vhd
210,7 → 210,7
-- |
-- next state logic |
-- |
process(state, sc_mem_out.rd, sc_mem_out.wr, trans_ram, wait_state) |
process(state, sc_mem_out, trans_ram, wait_state) |
|
begin |
|
/trunk/vhdl/sc_arbiter_pack.vhd
0,0 → 1,12
library ieee; |
use ieee.std_logic_1164.all; |
use ieee.numeric_std.all; |
|
use work.sc_pack.all; |
|
package sc_arbiter_pack is |
|
type arb_out_type is array (integer range <>) of sc_mem_out_type; |
type arb_in_type is array (integer range <>) of sc_in_type; |
|
end sc_arbiter_pack; |
/trunk/vhdl/sc_arbiter_2m.vhd
0,0 → 1,390
|
|
-- 150407: first working version with records |
-- 170407: produce number of registers depending on the cpu_cnt |
-- 110507: * arbiter that can be used with prefered number of masters |
-- * full functional arbiter with two masters |
-- * short modelsim test with 3 masters carried out |
-- 290607: used for JTRES07 submission |
|
|
library ieee; |
use ieee.std_logic_1164.all; |
use ieee.numeric_std.all; |
|
use work.sc_pack.all; |
use work.sc_arbiter_pack.all; |
|
entity arbiter is |
generic( |
addr_bits : integer; |
cpu_cnt : integer); -- number of masters for the arbiter |
port ( |
clk, reset : in std_logic; |
arb_out : in arb_out_type(0 to cpu_cnt-1); |
arb_in : out arb_in_type(0 to cpu_cnt-1); |
mem_out : out sc_mem_out_type; |
mem_in : in sc_in_type |
); |
end arbiter; |
|
|
architecture rtl of arbiter is |
|
-- signals for the input register of each master |
|
type reg_type is record |
rd : std_logic; |
wr : std_logic; |
wr_data : std_logic_vector(31 downto 0); |
address : std_logic_vector(addr_bits-1 downto 0); |
end record; |
|
type reg_array_type is array (0 to cpu_cnt-1) of reg_type; |
signal reg_in : reg_array_type; |
|
-- one fsm for each CPU |
|
type state_type is (idle, read, write, waitingR, sendR, |
waitingW, sendW); |
type state_array is array (0 to cpu_cnt-1) of state_type; |
signal state : state_array; |
signal next_state : state_array; |
|
-- one fsm for each serve |
|
type serve_type is (idl, serv); |
type serve_array is array (0 to cpu_cnt-1) of serve_type; |
signal this_state : serve_array; |
signal follow_state : serve_array; |
|
-- arbiter |
|
type set_type is array (0 to cpu_cnt-1) of std_logic; |
signal set : set_type; |
|
|
begin |
|
|
-- Generates the input register and saves incoming data for each master |
gen_register: for i in 0 to cpu_cnt-1 generate |
process(clk, reset) |
begin |
if reset = '1' then |
reg_in(i).rd <= '0'; |
reg_in(i).wr <= '0'; |
reg_in(i).wr_data <= (others => '0'); |
reg_in(i).address <= (others => '0'); |
elsif rising_edge(clk) then |
if arb_out(i).rd = '1' or arb_out(i).wr = '1' then |
reg_in(i).rd <= arb_out(i).rd; |
reg_in(i).wr <= arb_out(i).wr; |
reg_in(i).address <= arb_out(i).address; |
reg_in(i).wr_data <= arb_out(i).wr_data; |
end if; |
end if; |
end process; |
end generate; |
|
-- Generates next state of the FSM for each master |
gen_next_state: for i in 0 to cpu_cnt-1 generate |
process(reset, state, arb_out, mem_in, this_state, reg_in) |
begin |
|
next_state(i) <= state(i); |
|
case state(i) is |
when idle => |
|
if this_state(i) = serv then -- checks if this CPU is on turn |
if mem_in.rdy_cnt = 1 and arb_out(i).rd = '1' then |
next_state(i) <= read; |
elsif (mem_in.rdy_cnt = 0) and (arb_out(i).rd = '1' |
or arb_out(i).wr = '1') then |
for k in 0 to cpu_cnt-1 loop |
if arb_out(k).rd = '1' or arb_out(k).wr = '1' then |
if i<=k then |
if arb_out(i).rd = '1' then |
next_state(i) <= read; |
exit; |
elsif arb_out(i).wr = '1' then |
next_state(i) <= write; |
exit; |
end if; |
else |
if arb_out(i).rd = '1' then |
next_state(i) <= waitingR; |
exit; |
elsif arb_out(i).wr = '1' then |
next_state(i) <= waitingW; |
exit; |
end if; |
end if; |
elsif reg_in(k).rd = '1' or reg_in(k).wr = '1' then |
if arb_out(i).rd = '1' then |
next_state(i) <= waitingR; |
exit; |
elsif arb_out(i).wr = '1' then |
next_state(i) <= waitingW; |
exit; |
end if; |
else |
if arb_out(i).rd = '1' then |
next_state(i) <= read; |
elsif arb_out(i).wr = '1' then |
next_state(i) <= write; |
end if; |
end if; |
end loop; |
end if; |
else |
for j in 0 to cpu_cnt-1 loop |
if this_state(j) = serv then |
if mem_in.rdy_cnt = 1 and arb_out(j).rd = '1' and |
arb_out(i).rd = '1' then |
next_state(i) <= waitingR; |
exit; |
elsif mem_in.rdy_cnt = 1 and arb_out(j).rd = '1' and |
arb_out(i).wr = '1' then |
next_state(i) <= waitingW; |
exit; |
end if; |
else |
if mem_in.rdy_cnt = 0 then |
if arb_out(j).rd = '1' or arb_out(j).wr = '1' then |
if i<=j then |
if arb_out(i).rd = '1' then |
next_state(i) <= read; |
exit; -- new |
elsif arb_out(i).wr = '1' then |
next_state(i) <= write; |
exit; -- new |
end if; |
else |
if arb_out(i).rd = '1' then |
next_state(i) <= waitingR; |
exit; |
elsif arb_out(i).wr = '1' then |
next_state(i) <= waitingW; |
exit; |
end if; |
end if; |
-- new |
elsif (state(j) = waitingR) or (state(j) = waitingW) then |
if arb_out(i).rd = '1' then |
next_state(i) <= waitingR; |
elsif arb_out(i).wr = '1' then |
next_state(i) <= waitingW; |
exit; |
end if; |
-- new |
elsif arb_out(i).rd = '1' then |
next_state(i) <= read; |
elsif arb_out(i).wr = '1' then |
next_state(i) <= write; |
end if; |
else |
if arb_out(i).rd = '1' then |
next_state(i) <= waitingR; |
exit; |
elsif arb_out(i).wr = '1' then |
next_state(i) <= waitingW; |
exit; |
end if; |
end if; |
end if; |
end loop; |
end if; |
|
when read => |
next_state(i) <= idle; |
|
when write => |
next_state(i) <= idle; |
|
when waitingR => |
if mem_in.rdy_cnt = 0 then |
-- checks which CPU in waitingR has highest priority |
for j in 0 to cpu_cnt-1 loop |
--if arb_out(j).rd = '1' or arb_out(j).wr = '1' then |
-- next_state(i) <= waitingR; |
-- exit; |
--els |
if (state(j) = waitingR) or (state(j) = waitingW) then |
if j<i then |
next_state(i) <= waitingR; |
exit; |
elsif j=i then |
next_state(i) <= sendR; |
exit; |
else |
next_state(i) <= sendR; |
exit; |
end if; |
else |
next_state(i) <= sendR; |
end if; |
end loop; |
else |
next_state(i) <= waitingR; |
end if; |
|
when sendR => |
next_state(i) <= idle; |
|
when waitingW => |
if mem_in.rdy_cnt = 0 then |
for j in 0 to cpu_cnt-1 loop |
--if arb_out(j).rd = '1' or arb_out(j).wr = '1' then |
-- next_state(i) <= waitingW; |
-- exit; |
--els |
if (state(j) = waitingR) or (state(j) = waitingW) then |
if j<i then |
next_state(i) <= waitingW; |
exit; |
elsif j=i then |
next_state(i) <= sendW; |
exit; |
else |
next_state(i) <= sendW; |
exit; |
end if; |
else |
next_state(i) <= sendW; |
end if; |
end loop; |
else |
next_state(i) <= waitingW; |
end if; |
|
when sendW => |
next_state(i) <= idle; |
|
end case; |
end process; |
end generate; |
|
|
-- Generates the FSM state for each master |
gen_state: for i in 0 to cpu_cnt-1 generate |
process (clk, reset) |
begin |
if (reset = '1') then |
state(i) <= idle; |
elsif (rising_edge(clk)) then |
state(i) <= next_state(i); |
end if; |
end process; |
end generate; |
|
|
-- The arbiter output |
process (arb_out, reg_in, next_state) |
begin |
|
mem_out.rd <= '0'; |
mem_out.wr <= '0'; |
mem_out.address <= (others => '0'); |
mem_out.wr_data <= (others => '0'); |
|
for i in 0 to cpu_cnt-1 loop |
set(i) <= '0'; |
|
case next_state(i) is |
when idle => |
|
when read => |
set(i) <= '1'; |
mem_out.rd <= arb_out(i).rd; |
mem_out.address <= arb_out(i).address; |
|
when write => |
set(i) <= '1'; |
mem_out.wr <= arb_out(i).wr; |
mem_out.address <= arb_out(i).address; |
mem_out.wr_data <= arb_out(i).wr_data; |
|
when waitingR => |
|
when sendR => |
set(i) <= '1'; |
mem_out.rd <= reg_in(i).rd; |
mem_out.address <= reg_in(i).address; |
|
when waitingW => |
|
when sendW => |
set(i) <= '1'; |
mem_out.wr <= reg_in(i).wr; |
mem_out.address <= reg_in(i).address; |
mem_out.wr_data <= reg_in(i).wr_data; |
|
end case; |
end loop; |
end process; |
|
-- generation of follow_state |
gen_serve: for i in 0 to cpu_cnt-1 generate |
process(mem_in, set, this_state) |
begin |
case this_state(i) is |
when idl => |
follow_state(i) <= idl; |
if set(i) = '1' then |
follow_state(i) <= serv; |
end if; |
when serv => |
follow_state(i) <= serv; |
if mem_in.rdy_cnt = 0 and set(i) = '0' then |
follow_state(i) <= idl; |
end if; |
end case; |
end process; |
end generate; |
|
gen_serve2: for i in 0 to cpu_cnt-1 generate |
process (clk, reset) |
begin |
if (reset = '1') then |
this_state(i) <= idl; |
elsif (rising_edge(clk)) then |
this_state(i) <= follow_state(i); |
end if; |
end process; |
end generate; |
|
gen_rdy_cnt: for i in 0 to cpu_cnt-1 generate |
process (mem_in, state, this_state) |
begin |
arb_in(i).rdy_cnt <= mem_in.rdy_cnt; |
arb_in(i).rd_data <= mem_in.rd_data; |
|
case state(i) is |
when idle => |
case this_state(i) is |
when idl => |
arb_in(i).rdy_cnt <= "00"; |
when serv => |
end case; |
|
when read => |
|
when write => |
|
when waitingR => |
arb_in(i).rdy_cnt <= "11"; |
|
when sendR => |
|
when waitingW => |
arb_in(i).rdy_cnt <= "11"; |
|
when sendW => |
|
end case; |
end process; |
end generate; |
|
end rtl; |
/trunk/vhdl/sc_arbiter.vhd
0,0 → 1,424
|
|
-- 150407: first working version with records |
-- 170407: produce number of registers depending on the cpu_cnt |
-- 110507: * arbiter that can be used with prefered number of masters |
-- * full functional arbiter with two masters |
-- * short modelsim test with 3 masters carried out |
-- 190607: Problem found: Both CPU1 and CPU2 start to read cache line!!! |
-- 030707: Several bugs are fixed now. CMP with 3 running masters functions! |
|
|
library ieee; |
use ieee.std_logic_1164.all; |
use ieee.numeric_std.all; |
|
use work.sc_pack.all; |
use work.sc_arbiter_pack.all; |
|
entity arbiter is |
generic( |
addr_bits : integer; |
cpu_cnt : integer); -- number of masters for the arbiter |
port ( |
clk, reset : in std_logic; |
arb_out : in arb_out_type(0 to cpu_cnt-1); |
arb_in : out arb_in_type(0 to cpu_cnt-1); |
mem_out : out sc_mem_out_type; |
mem_in : in sc_in_type |
); |
end arbiter; |
|
|
architecture rtl of arbiter is |
|
-- signals for the input register of each master |
|
type reg_type is record |
rd : std_logic; |
wr : std_logic; |
wr_data : std_logic_vector(31 downto 0); |
address : std_logic_vector(addr_bits-1 downto 0); |
end record; |
|
type reg_array_type is array (0 to cpu_cnt-1) of reg_type; |
signal reg_in : reg_array_type; |
|
-- one fsm for each CPU |
|
type state_type is (idle, read, write, waitingR, sendR, |
waitingW, sendW); |
type state_array is array (0 to cpu_cnt-1) of state_type; |
signal state : state_array; |
signal next_state : state_array; |
|
-- one fsm for each serve |
|
type serve_type is (idl, serv); |
type serve_array is array (0 to cpu_cnt-1) of serve_type; |
signal this_state : serve_array; |
signal follow_state : serve_array; |
|
-- arbiter |
|
type set_type is array (0 to cpu_cnt-1) of std_logic; |
signal set : set_type; |
signal waiting : set_type; |
signal masterWaiting : std_logic; |
|
|
begin |
|
|
-- Generates the input register and saves incoming data for each master |
gen_register: for i in 0 to cpu_cnt-1 generate |
process(clk, reset) |
begin |
if reset = '1' then |
reg_in(i).rd <= '0'; |
reg_in(i).wr <= '0'; |
reg_in(i).wr_data <= (others => '0'); |
reg_in(i).address <= (others => '0'); |
elsif rising_edge(clk) then |
if arb_out(i).rd = '1' or arb_out(i).wr = '1' then |
reg_in(i).rd <= arb_out(i).rd; |
reg_in(i).wr <= arb_out(i).wr; |
reg_in(i).address <= arb_out(i).address; |
reg_in(i).wr_data <= arb_out(i).wr_data; |
end if; |
end if; |
end process; |
end generate; |
|
-- Register for masterWaiting |
process(clk, reset) |
begin |
if reset = '1' then |
masterWaiting <= '0'; |
elsif rising_edge(clk) then |
for i in 0 to cpu_cnt-1 loop |
if waiting(i) = '1' then |
masterWaiting <= '1'; |
exit; |
else |
masterWaiting <= '0'; |
end if; |
end loop; |
end if; |
end process; |
|
-- Generates next state of the FSM for each master |
gen_next_state: for i in 0 to cpu_cnt-1 generate |
process(reset, state, arb_out, mem_in, this_state, reg_in, masterWaiting) |
begin |
|
next_state(i) <= state(i); |
waiting(i) <= '0'; |
|
case state(i) is |
when idle => |
|
-- checks if this CPU is on turn (pipelined access) |
if this_state(i) = serv then |
-- pipelined access |
if mem_in.rdy_cnt = 1 and arb_out(i).rd = '1' then |
next_state(i) <= read; |
|
elsif (mem_in.rdy_cnt = 0 and (arb_out(i).rd = '1' or arb_out(i).wr = '1')) then |
|
-- check if some master is waiting |
if masterWaiting = '1' then |
if arb_out(i).rd = '1' then |
next_state(i) <= waitingR; |
waiting(i) <= '1'; |
elsif arb_out(i).wr = '1' then |
next_state(i) <= waitingW; |
waiting(i) <= '1'; |
end if; |
|
-- check if parallel access |
else |
for j in 0 to cpu_cnt-1 loop |
if arb_out(j).rd = '1' or arb_out(j).wr = '1' then |
if i<=j then |
if arb_out(i).rd = '1' then |
next_state(i) <= read; |
exit; |
elsif arb_out(i).wr = '1' then |
next_state(i) <= write; |
exit; |
end if; |
else |
if arb_out(i).rd = '1' then |
next_state(i) <= waitingR; |
waiting(i) <= '1'; |
exit; |
elsif arb_out(i).wr = '1' then |
next_state(i) <= waitingW; |
waiting(i) <= '1'; |
exit; |
end if; |
end if; |
end if; |
end loop; |
end if; |
|
-- all other kinds of rdy_cnt |
else |
if arb_out(i).rd = '1' then |
next_state(i) <= waitingR; |
waiting(i) <= '1'; |
elsif arb_out(i).wr = '1' then |
next_state(i) <= waitingW; |
waiting(i) <= '1'; |
end if; |
end if; |
|
-- CPU is not on turn (no pipelined access possible) |
else |
if (mem_in.rdy_cnt = 0 and (arb_out(i).rd = '1' or arb_out(i).wr = '1')) then |
-- check if some master is waiting |
if masterWaiting = '1' then |
if arb_out(i).rd = '1' then |
next_state(i) <= waitingR; |
waiting(i) <= '1'; |
elsif arb_out(i).wr = '1' then |
next_state(i) <= waitingW; |
waiting(i) <= '1'; |
end if; |
|
-- check if parallel access |
else |
for j in 0 to cpu_cnt-1 loop |
if arb_out(j).rd = '1' or arb_out(j).wr = '1' then |
if i<=j then |
if arb_out(i).rd = '1' then |
next_state(i) <= read; |
exit; |
elsif arb_out(i).wr = '1' then |
next_state(i) <= write; |
exit; |
end if; |
else |
if arb_out(i).rd = '1' then |
next_state(i) <= waitingR; |
waiting(i) <= '1'; |
exit; |
elsif arb_out(i).wr = '1' then |
next_state(i) <= waitingW; |
waiting(i) <= '1'; |
exit; |
end if; |
end if; |
-- if no parallel access, master can access |
else |
if arb_out(i).rd = '1' then |
next_state(i) <= read; |
elsif arb_out(i).wr = '1' then |
next_state(i) <= write; |
end if; |
end if; |
end loop; |
end if; |
|
-- rdy_cnt != 0 |
else |
if arb_out(i).rd = '1' then |
next_state(i) <= waitingR; |
waiting(i) <= '1'; |
elsif arb_out(i).wr = '1' then |
next_state(i) <= waitingW; |
waiting(i) <= '1'; |
end if; |
end if; |
end if; |
|
|
when read => |
next_state(i) <= idle; |
|
when write => |
next_state(i) <= idle; |
|
when waitingR => |
if mem_in.rdy_cnt = 0 then |
-- checks which CPU in waitingR has highest priority |
for j in 0 to cpu_cnt-1 loop |
if (state(j) = waitingR) or (state(j) = waitingW) then |
if j<i then |
next_state(i) <= waitingR; |
waiting(i) <= '1'; |
exit; |
elsif j=i then |
next_state(i) <= sendR; |
exit; |
else |
next_state(i) <= sendR; |
exit; |
end if; |
else |
next_state(i) <= sendR; |
end if; |
end loop; |
else |
next_state(i) <= waitingR; |
waiting(i) <= '1'; |
end if; |
|
when sendR => |
next_state(i) <= idle; |
|
when waitingW => |
|
if mem_in.rdy_cnt = 0 then |
for j in 0 to cpu_cnt-1 loop |
if (state(j) = waitingR) or (state(j) = waitingW) then |
if j<i then |
next_state(i) <= waitingW; |
waiting(i) <= '1'; |
exit; |
elsif j=i then |
next_state(i) <= sendW; |
exit; |
else |
next_state(i) <= sendW; |
exit; |
end if; |
else |
next_state(i) <= sendW; |
end if; |
end loop; |
else |
next_state(i) <= waitingW; |
waiting(i) <= '1'; |
end if; |
|
when sendW => |
next_state(i) <= idle; |
|
end case; |
end process; |
end generate; |
|
|
-- Generates the FSM state for each master |
gen_state: for i in 0 to cpu_cnt-1 generate |
process (clk, reset) |
begin |
if (reset = '1') then |
state(i) <= idle; |
elsif (rising_edge(clk)) then |
state(i) <= next_state(i); |
end if; |
end process; |
end generate; |
|
|
-- The arbiter output |
process (arb_out, reg_in, next_state) |
begin |
|
mem_out.rd <= '0'; |
mem_out.wr <= '0'; |
mem_out.address <= (others => '0'); |
mem_out.wr_data <= (others => '0'); |
|
for i in 0 to cpu_cnt-1 loop |
set(i) <= '0'; |
|
case next_state(i) is |
when idle => |
|
when read => |
set(i) <= '1'; |
mem_out.rd <= arb_out(i).rd; |
mem_out.address <= arb_out(i).address; |
|
when write => |
set(i) <= '1'; |
mem_out.wr <= arb_out(i).wr; |
mem_out.address <= arb_out(i).address; |
mem_out.wr_data <= arb_out(i).wr_data; |
|
when waitingR => |
|
when sendR => |
set(i) <= '1'; |
mem_out.rd <= reg_in(i).rd; |
mem_out.address <= reg_in(i).address; |
|
when waitingW => |
|
when sendW => |
set(i) <= '1'; |
mem_out.wr <= reg_in(i).wr; |
mem_out.address <= reg_in(i).address; |
mem_out.wr_data <= reg_in(i).wr_data; |
|
end case; |
end loop; |
end process; |
|
-- generation of follow_state |
gen_serve: for i in 0 to cpu_cnt-1 generate |
process(mem_in, set, this_state) |
begin |
case this_state(i) is |
when idl => |
follow_state(i) <= idl; |
if set(i) = '1' then |
follow_state(i) <= serv; |
end if; |
when serv => |
follow_state(i) <= serv; |
if mem_in.rdy_cnt = 0 and set(i) = '0' then |
follow_state(i) <= idl; |
end if; |
end case; |
end process; |
end generate; |
|
gen_serve2: for i in 0 to cpu_cnt-1 generate |
process (clk, reset) |
begin |
if (reset = '1') then |
this_state(i) <= idl; |
elsif (rising_edge(clk)) then |
this_state(i) <= follow_state(i); |
end if; |
end process; |
end generate; |
|
gen_rdy_cnt: for i in 0 to cpu_cnt-1 generate |
process (mem_in, state, this_state) |
begin |
arb_in(i).rdy_cnt <= mem_in.rdy_cnt; |
arb_in(i).rd_data <= mem_in.rd_data; |
|
case state(i) is |
when idle => |
case this_state(i) is |
when idl => |
arb_in(i).rdy_cnt <= "00"; |
when serv => |
end case; |
|
when read => |
|
when write => |
|
when waitingR => |
arb_in(i).rdy_cnt <= "11"; |
|
when sendR => |
|
when waitingW => |
arb_in(i).rdy_cnt <= "11"; |
|
when sendW => |
|
end case; |
end process; |
end generate; |
|
end rtl; |
/trunk/vhdl/sc_sram16.vhd
18,6 → 18,8
-- 2006-08-01 Adapted from sc_ram32.vhd |
-- 2006-08-16 Rebuilding the already working (lost) version |
-- Use wait_state, din register without MUX |
-- 2007-06-04 changed SimpCon to records |
-- 2007-09-09 Additional input register for high data (correct SimpCon violation) |
-- |
|
Library IEEE; |
25,6 → 27,7
use ieee.numeric_std.all; |
|
use work.jop_types.all; |
use work.sc_pack.all; |
|
entity sc_mem_if is |
generic (ram_ws : integer; addr_bits : integer); |
33,14 → 36,12
|
clk, reset : in std_logic; |
|
-- SimpCon interface |
-- |
-- SimpCon memory interface |
-- |
sc_mem_out : in sc_mem_out_type; |
sc_mem_in : out sc_in_type; |
|
address : in std_logic_vector(addr_bits-1 downto 0); |
wr_data : in std_logic_vector(31 downto 0); |
rd, wr : in std_logic; |
rd_data : out std_logic_vector(31 downto 0); |
rdy_cnt : out unsigned(1 downto 0); |
|
-- memory interface |
|
ram_addr : out std_logic_vector(addr_bits-1 downto 0); |
76,8 → 77,8
signal inc_addr : std_logic; |
signal wr_low : std_logic; |
|
signal ram_dout_low : std_logic_vector(15 downto 0); |
signal ram_din_low : std_logic_vector(15 downto 0); |
signal ram_dout_low : std_logic_vector(15 downto 0); |
signal ram_din_high : std_logic_vector(15 downto 0); |
|
signal ram_din_reg : std_logic_vector(31 downto 0); |
|
85,7 → 86,7
|
ram_dout_en <= dout_ena; |
|
rdy_cnt <= cnt; |
sc_mem_in.rdy_cnt <= cnt; |
|
-- |
-- Register memory address, write data and read data |
100,25 → 101,28
|
elsif rising_edge(clk) then |
|
if rd='1' or wr='1' then |
ram_addr <= address(addr_bits-2 downto 0) & "0"; |
if sc_mem_out.rd='1' or sc_mem_out.wr='1' then |
ram_addr <= sc_mem_out.address(addr_bits-2 downto 0) & "0"; |
end if; |
if inc_addr='1' then |
ram_addr(0) <= '1'; |
end if; |
if wr='1' then |
ram_dout <= wr_data(31 downto 16); |
ram_dout_low <= wr_data(15 downto 0); |
if sc_mem_out.wr='1' then |
ram_dout <= sc_mem_out.wr_data(31 downto 16); |
ram_dout_low <= sc_mem_out.wr_data(15 downto 0); |
end if; |
if wr_low='1' then |
ram_dout <= ram_dout_low; |
end if; |
-- use an addtional input register to adhire the SimpCon spec |
-- to not change rd_data untill the full new word is available |
-- results in input MUX at RAM data input |
if rd_data_ena_h='1' then |
ram_din_reg(15 downto 0) <= ram_din; |
ram_din_high <= ram_din; |
end if; |
if rd_data_ena_l='1' then |
-- move first word to higher half |
ram_din_reg(31 downto 16) <= ram_din_reg(15 downto 0); |
ram_din_reg(31 downto 16) <= ram_din_high; |
-- read second word |
ram_din_reg(15 downto 0) <= ram_din; |
end if; |
126,7 → 130,7
end if; |
end process; |
|
rd_data <= ram_din_reg; |
sc_mem_in.rd_data <= ram_din_reg; |
|
-- |
-- 'delay' nwe 1/2 cycle -> change on falling edge |
146,7 → 150,7
-- |
-- next state logic |
-- |
process(state, rd, wr, wait_state) |
process(state, sc_mem_out.rd, sc_mem_out.wr, wait_state) |
|
begin |
|
155,7 → 159,7
case state is |
|
when idl => |
if rd='1' then |
if sc_mem_out.rd='1' then |
if ram_ws=0 then |
-- then we omit state rd1! |
next_state <= rd2_h; |
162,7 → 166,7
else |
next_state <= rd1_h; |
end if; |
elsif wr='1' then |
elsif sc_mem_out.wr='1' then |
next_state <= wr_h; |
end if; |
|
192,7 → 196,7
next_state <= idl; |
-- This should do to give us a pipeline |
-- level of 2 for read |
if rd='1' then |
if sc_mem_out.rd='1' then |
if ram_ws=0 then |
-- then we omit state rd1! |
next_state <= rd2_h; |
199,7 → 203,7
else |
next_state <= rd1_h; |
end if; |
elsif wr='1' then |
elsif sc_mem_out.wr='1' then |
next_state <= wr_h; |
end if; |
|
342,7 → 346,7
cnt <= "00"; |
end if; |
|
if rd='1' or wr='1' then |
if sc_mem_out.rd='1' or sc_mem_out.wr='1' then |
wait_state <= to_unsigned(ram_ws+1, 4); |
end if; |
|
359,7 → 363,7
-- take care for pipelined cach transfer |
-- there is no idl state and cnt should |
-- go back to "11" |
if rd='0' and wr='0' then |
if sc_mem_out.rd='0' and sc_mem_out.wr='0' then |
-- if wait_state<4 then |
if wait_state(3 downto 2)="00" then |
cnt <= wait_state(1 downto 0)-1; |