OpenCores
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;

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.