OpenCores
URL https://opencores.org/ocsvn/simpcon/simpcon/trunk

Subversion Repositories simpcon

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /simpcon
    from Rev 28 to Rev 29
    Reverse comparison

Rev 28 → Rev 29

/trunk/vhdl/sc_uart_tal.vhd
1,4 → 1,25
--
--
-- This file is a part of JOP, the Java Optimized Processor
--
-- Copyright (C) 2001-2008, Martin Schoeberl (martin@jopdesign.com)
--
-- This program is free software: you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
-- the Free Software Foundation, either version 3 of the License, or
-- (at your option) any later version.
--
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with this program. If not, see <http://www.gnu.org/licenses/>.
--
 
 
--
-- sc_uart_tal.vhd
--
-- 8-N-1 serial interface
/trunk/vhdl/sc2ahbsl.vhd
1,4 → 1,25
--
--
-- This file is a part of JOP, the Java Optimized Processor
--
-- Copyright (C) 2001-2008, Martin Schoeberl (martin@jopdesign.com)
--
-- This program is free software: you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
-- the Free Software Foundation, either version 3 of the License, or
-- (at your option) any later version.
--
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with this program. If not, see <http://www.gnu.org/licenses/>.
--
 
 
--
-- sc2ahbsl.vhd
--
-- SimpCon to AMBA bridge
55,9 → 76,9
ahbsi.hsel(1 to NAHBSLV-1) <= (others => '0'); -- we use only slave 0
ahbsi.hsel(0) <= scmo.rd or scmo.wr; -- slave select
-- do we need to store the addrsss in a register?
ahbsi.haddr(MEM_ADDR_SIZE-1+2 downto 2) <= scmo.address; -- address bus (byte)
ahbsi.haddr(SC_ADDR_SIZE-1+2 downto 2) <= scmo.address; -- address bus (byte)
ahbsi.haddr(1 downto 0) <= (others => '0');
ahbsi.haddr(31 downto MEM_ADDR_SIZE+2) <= (others => '0');
ahbsi.haddr(31 downto SC_ADDR_SIZE+2) <= (others => '0');
ahbsi.hwrite <= scmo.wr; -- read/write
ahbsi.htrans <= HTRANS_NONSEQ; -- transfer type
ahbsi.hsize <= "010"; -- transfer size 32 bits
/trunk/vhdl/sc_isa.vhd
1,4 → 1,25
--
--
-- This file is a part of JOP, the Java Optimized Processor
--
-- Copyright (C) 2001-2008, Martin Schoeberl (martin@jopdesign.com)
--
-- This program is free software: you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
-- the Free Software Foundation, either version 3 of the License, or
-- (at your option) any later version.
--
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with this program. If not, see <http://www.gnu.org/licenses/>.
--
 
 
--
-- sc_isa.vhd
--
-- ISA bus for ethernet chip
/trunk/vhdl/sc_pack.vhd
1,45 → 1,174
--
-- sc_pack.vhd
--
-- Package for SimpCon defines
--
-- Author: Martin Schoeberl (martin@jopdesign.com)
--
--
-- 2007-03-16 first version
--
--
 
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
 
package sc_pack is
 
constant MEM_ADDR_SIZE : integer := 21;
constant IO_ADDR_SIZE : integer := 7;
constant RDY_CNT_SIZE : integer := 2;
 
type sc_mem_out_type is record
address : std_logic_vector(MEM_ADDR_SIZE-1 downto 0);
wr_data : std_logic_vector(31 downto 0);
rd : std_logic;
wr : std_logic;
end record;
 
type sc_io_out_type is record
address : std_logic_vector(IO_ADDR_SIZE-1 downto 0);
wr_data : std_logic_vector(31 downto 0);
rd : std_logic;
wr : std_logic;
end record;
type sc_in_type is record
rd_data : std_logic_vector(31 downto 0);
rdy_cnt : unsigned(RDY_CNT_SIZE-1 downto 0);
end record;
type sc_io_out_array_type is array (integer range <>) of sc_io_out_type;
type sc_in_array_type is array (integer range <>) of sc_in_type;
end sc_pack;
--
--
-- This file is a part of JOP, the Java Optimized Processor
--
-- Copyright (C) 2001-2008, Martin Schoeberl (martin@jopdesign.com)
--
-- This program is free software: you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
-- the Free Software Foundation, either version 3 of the License, or
-- (at your option) any later version.
--
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with this program. If not, see <http://www.gnu.org/licenses/>.
--
 
 
--
-- sc_pack.vhd
--
-- Package for SimpCon defines
--
-- Author: Martin Schoeberl (martin@jopdesign.com)
--
--
-- 2007-03-16 first version
--
--
 
library std;
use std.textio.all;
 
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
 
package sc_pack is
 
-- two more bits than needed for the main memory
-- one to distinguishe between memory and IO access
-- one more to allow memory mirroring for size auto
-- detection at boot time
constant SC_ADDR_SIZE : integer := 23;
constant RDY_CNT_SIZE : integer := 2;
 
type sc_out_type is record
address : std_logic_vector(SC_ADDR_SIZE-1 downto 0);
wr_data : std_logic_vector(31 downto 0);
rd : std_logic;
wr : std_logic;
atomic : std_logic;
nc : std_logic;
end record;
 
type sc_in_type is record
rd_data : std_logic_vector(31 downto 0);
rdy_cnt : unsigned(RDY_CNT_SIZE-1 downto 0);
end record;
type sc_out_array_type is array (integer range <>) of sc_out_type;
type sc_in_array_type is array (integer range <>) of sc_in_type;
 
constant TIMEOUT : integer := 50;
 
procedure sc_write(
signal clk : in std_logic;
constant addr : in natural;
constant data : in natural;
signal sc_out : out sc_out_type;
signal sc_in : in sc_in_type);
 
procedure sc_read(
signal clk : in std_logic;
constant addr : in natural;
variable data : out natural;
signal sc_out : out sc_out_type;
signal sc_in : in sc_in_type);
 
end sc_pack;
 
package body sc_pack is
 
procedure sc_write(
signal clk : in std_logic;
constant addr : in natural;
constant data : in natural;
signal sc_out : out sc_out_type;
signal sc_in : in sc_in_type) is
 
variable txt : line;
 
begin
 
write(txt, now, right, 8);
write(txt, string'(" wrote "));
write(txt, data);
write(txt, string'(" to addr. "));
write(txt, addr);
 
sc_out.wr_data <= std_logic_vector(to_unsigned(data, sc_out.wr_data'length));
sc_out.address <= std_logic_vector(to_unsigned(addr, sc_out.address'length));
sc_out.wr <= '1';
sc_out.rd <= '0';
 
-- one cycle valid
wait until rising_edge(clk);
sc_out.wr_data <= (others => 'X');
sc_out.address <= (others => 'X');
sc_out.wr <= '0';
 
for i in 1 to TIMEOUT loop
wait until rising_edge(clk);
exit when sc_in.rdy_cnt = "00";
if (i = TIMEOUT) then
write (txt, string'("No acknowledge recevied!"));
end if;
end loop;
 
writeline(output, txt);
 
end;
 
procedure sc_read(
signal clk : in std_logic;
constant addr : in natural;
variable data : out natural;
signal sc_out : out sc_out_type;
signal sc_in : in sc_in_type) is
 
variable txt : line;
variable in_data : natural;
 
begin
 
write(txt, now, right, 8);
write(txt, string'(" read from addr. "));
write(txt, addr);
writeline(output, txt);
 
sc_out.address <= std_logic_vector(to_unsigned(addr, sc_out.address'length));
sc_out.wr_data <= (others => 'X');
sc_out.wr <= '0';
sc_out.rd <= '1';
 
-- one cycle valid
wait until rising_edge(clk);
sc_out.address <= (others => 'X');
sc_out.rd <= '0';
 
-- wait for acknowledge
for i in 1 to TIMEOUT loop
wait until rising_edge(clk);
exit when sc_in.rdy_cnt = "00";
if (i = TIMEOUT) then
write (txt, string'("No acknowledge recevied!"));
end if;
end loop;
 
in_data := to_integer(unsigned(sc_in.rd_data));
data := in_data;
 
write(txt, now, right, 8);
write(txt, string'(" value: "));
write(txt, in_data);
 
writeline(output, txt);
 
end;
 
end sc_pack;
/trunk/vhdl/sc_arbiter_fixedpr_int.vhd
0,0 → 1,480
--
-- This file is part of JOP, the Java Optimized Processor
--
-- Copyright (C) 2007,2008, Christof Pitter
--
-- This program is free software: you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
-- the Free Software Foundation, either version 3 of the License, or
-- (at your option) any later version.
--
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with this program. If not, see <http://www.gnu.org/licenses/>.
--
 
 
 
 
-- 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!
-- 261107: Fixed Priority Interruptive Arbiter
 
 
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_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, pipeBlocked);
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
if mem_in.rdy_cnt = 1 and arb_out(i).rd = '1' then
-- check if higher priority CPU wants to access and blocks pipelined access
next_state(i) <= read;
if arb_out(i).atomic = '1' then
for j in 0 to cpu_cnt-1 loop
if arb_out(j).rd = '1' or arb_out(j).wr = '1' then
if j<i then
next_state(i) <= pipeBlocked;
--wait_cycles <= 1;
exit;
end if;
end if;
end loop;
end if;
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 already pipelined accessing the memory
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 another CPU wants to access in parallel
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;
-- ** cannot ever happen!!!!!!! **
-- 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;
-- pipelined gets blocked
if mem_in.rdy_cnt = 2 and arb_out(i).atomic = '1' then
for j in 0 to cpu_cnt-1 loop
if arb_out(j).rd = '1' or arb_out(j).wr = '1' then
if j<i then
next_state(i) <= pipeBlocked;
--wait_cycles <= 3;
exit;
end if;
end if;
end loop;
end if;
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;
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;
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;
when pipeBlocked =>
if mem_in.rdy_cnt = 0 then -- to be in serv Mode until request done
next_state(i) <= waitingR; --no waitingW possible because we don't use pipelined write!!!!!
else
next_state(i) <= pipeBlocked;
end if;
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');
mem_out.atomic <= '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;
when pipeBlocked =>
set(i) <= '1';
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 =>
when pipeBlocked =>
arb_in(i).rdy_cnt <= "11";
end case;
end process;
end generate;
 
end rtl;
/trunk/vhdl/sc_lego.vhd
1,4 → 1,25
--
--
-- This file is a part of JOP, the Java Optimized Processor
--
-- Copyright (C) 2001-2008, Martin Schoeberl (martin@jopdesign.com)
--
-- This program is free software: you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
-- the Free Software Foundation, either version 3 of the License, or
-- (at your option) any later version.
--
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with this program. If not, see <http://www.gnu.org/licenses/>.
--
 
 
--
-- sc_lego.vhd
--
-- Motor and sensor interface for LEGO MindStorms
/trunk/vhdl/sc_usb.vhd
1,4 → 1,25
--
--
-- This file is a part of JOP, the Java Optimized Processor
--
-- Copyright (C) 2001-2008, Martin Schoeberl (martin@jopdesign.com)
--
-- This program is free software: you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
-- the Free Software Foundation, either version 3 of the License, or
-- (at your option) any later version.
--
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with this program. If not, see <http://www.gnu.org/licenses/>.
--
 
 
--
-- sc_usb.vhd
--
-- Interface to FTDI FT2232C parallel port B
/trunk/vhdl/sc2wb.vhd
1,4 → 1,25
--
--
-- This file is a part of JOP, the Java Optimized Processor
--
-- Copyright (C) 2001-2008, Martin Schoeberl (martin@jopdesign.com)
--
-- This program is free software: you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
-- the Free Software Foundation, either version 3 of the License, or
-- (at your option) any later version.
--
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with this program. If not, see <http://www.gnu.org/licenses/>.
--
 
 
--
-- sc2wb.vhd
--
-- SimpCon/Wishbone bridge
/trunk/vhdl/sc_test_top.vhd
1,4 → 1,25
--
--
-- This file is a part of JOP, the Java Optimized Processor
--
-- Copyright (C) 2001-2008, Martin Schoeberl (martin@jopdesign.com)
--
-- This program is free software: you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
-- the Free Software Foundation, either version 3 of the License, or
-- (at your option) any later version.
--
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with this program. If not, see <http://www.gnu.org/licenses/>.
--
 
 
--
-- scio_test_top.vhd
--
-- The top level to test SimpCon IO devices.
/trunk/vhdl/sc_sigdel.vhd
1,4 → 1,25
--
--
-- This file is a part of JOP, the Java Optimized Processor
--
-- Copyright (C) 2001-2008, Martin Schoeberl (martin@jopdesign.com)
--
-- This program is free software: you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
-- the Free Software Foundation, either version 3 of the License, or
-- (at your option) any later version.
--
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with this program. If not, see <http://www.gnu.org/licenses/>.
--
 
 
--
-- sc_sigdel.vhd
--
-- A simple sigma-delta ADC and PWM DAC for the SimpCon interface
/trunk/vhdl/sc_control_channel.vhd
0,0 → 1,179
--
--
-- This file is a part of JOP, the Java Optimized Processor
--
-- Copyright (C) 2008, Jack Whitham
--
-- This program is free software: you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
-- the Free Software Foundation, either version 3 of the License, or
-- (at your option) any later version.
--
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with this program. If not, see <http://www.gnu.org/licenses/>.
--
 
 
--
-- sc_control_channel.vhd
--
-- 32 bit parallel interface for the control channel;
-- mimics a serial port UART device. Data is sent in a packet
-- form (with a header word and zero or more payload words).
--
 
 
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned."+";
use ieee.numeric_std.all;
 
entity sc_control_channel is
generic (addr_bits : 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);
 
cc_out_data : out std_logic_vector(31 downto 0);
cc_out_wr : out std_logic;
cc_out_rdy : in std_logic;
 
cc_in_data : in std_logic_vector(31 downto 0);
cc_in_wr : in std_logic;
cc_in_rdy : out std_logic
);
end sc_control_channel;
 
architecture rtl of sc_control_channel is
 
signal incoming_message : std_logic_vector(31 downto 0);
signal outgoing_message : std_logic_vector(31 downto 0);
signal send_ack, send_flag : std_logic;
 
type StateType is ( IDLE, RELAY, SEND, AWAIT_REPLY, AWAIT_REPLY_RELAY );
 
signal state : StateType;
 
begin
 
process ( clk , reset ) is
begin
if ( reset = '1' )
then
send_flag <= '0';
 
elsif ( clk = '1' )
and ( clk'event )
then
if ( send_ack = '1' )
then
send_flag <= '0';
end if;
 
if ( rd = '1' )
then
null;
elsif ( wr = '1' )
then
outgoing_message <= wr_data;
send_flag <= '1';
end if;
end if;
end process;
 
rdy_cnt <= "00" when (( state = IDLE ) and ( send_flag = '0' )) else "11";
rd_data <= incoming_message;
 
process ( clk , reset ) is
begin
if ( reset = '1' )
then
state <= IDLE;
cc_in_rdy <= '0';
cc_out_wr <= '0';
send_ack <= '0';
 
elsif ( clk = '1' )
and ( clk'event )
then
cc_in_rdy <= '0';
cc_out_wr <= '0';
send_ack <= '0';
 
case state is
when IDLE =>
if ( send_flag = '1' )
then
-- A message to be sent
cc_out_data <= outgoing_message;
send_ack <= '1';
state <= SEND;
elsif ( cc_in_wr = '1' )
then
-- Relay incoming message since we are not
-- waiting for a message
cc_out_data <= cc_in_data;
state <= RELAY;
else
-- Ready for CC data
cc_in_rdy <= '1';
end if;
 
when RELAY =>
if ( cc_out_rdy = '1' )
then
cc_out_wr <= '1';
state <= IDLE;
end if;
 
when SEND =>
if ( cc_out_rdy = '1' )
then
cc_out_wr <= '1';
state <= AWAIT_REPLY;
end if;
 
when AWAIT_REPLY =>
if ( cc_in_wr = '1' )
then
-- Examine incoming message
if ( cc_in_data ( 30 downto 16 ) = outgoing_message ( 30 downto 16 ) )
then
-- Correct message
incoming_message <= cc_in_data;
state <= IDLE;
else
-- Wrong message (for someone else)
cc_out_data <= cc_in_data;
state <= AWAIT_REPLY_RELAY;
end if;
else
-- Ready for CC data
cc_in_rdy <= '1';
end if;
when AWAIT_REPLY_RELAY =>
if ( cc_out_rdy = '1' )
then
cc_out_wr <= '1';
state <= AWAIT_REPLY;
end if;
end case;
end if;
end process;
 
end rtl;
 
/trunk/vhdl/sc_uart.vhd
1,4 → 1,25
--
--
-- This file is a part of JOP, the Java Optimized Processor
--
-- Copyright (C) 2001-2008, Martin Schoeberl (martin@jopdesign.com)
--
-- This program is free software: you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
-- the Free Software Foundation, either version 3 of the License, or
-- (at your option) any later version.
--
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with this program. If not, see <http://www.gnu.org/licenses/>.
--
 
 
--
-- sc_uart.vhd
--
-- 8-N-1 serial interface
/trunk/vhdl/sc_sys.vhd
1,14 → 1,35
--
--
-- This file is a part of JOP, the Java Optimized Processor
--
-- Copyright (C) 2001-2008, Martin Schoeberl (martin@jopdesign.com)
--
-- This program is free software: you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
-- the Free Software Foundation, either version 3 of the License, or
-- (at your option) any later version.
--
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with this program. If not, see <http://www.gnu.org/licenses/>.
--
 
 
--
-- sc_sys.vhd
--
-- counter, interrrupt handling and watchdog bit
--
-- Author: Martin Schoeberl martin@good-ear.com
-- Author: Martin Schoeberl martin@jopdesign.com
--
-- address map:
--
-- 0 read clk counter, write irq ena
-- 1 read 1 MHz counter, write timer val (us) + irq ack
-- 1 read 1 MHz counter, write timer val (us)
-- 2 write generates sw-int (for yield())
-- 3 write wd port
-- 4 write generates SW exception, read exception reason
22,8 → 43,61
-- 2006-01-11 added exception
-- 2007-03-17 changed interrupts to records
-- 2007-06-01 changed name from sc_cnt to sc_sys
-- 2007-11-22 added global lock and bootup of CMP
-- 2007-12-03 prioritized interrupt processing
-- 2007-12-07 global lock redesign
 
 
--
-- state for a single interrupt
--
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
 
entity intstate is
 
port (
clk : in std_logic;
reset : in std_logic;
 
irq : in std_logic; -- external request
ena : in std_logic; -- local enable
ack : in std_logic; -- is served
clear : in std_logic; -- reset pending interrupt
pending : out std_logic -- the output request
);
end intstate;
 
architecture rtl of intstate is
 
signal flag : std_logic;
 
begin
 
-- TODO: add minimum interarrival time
 
process(clk, reset) begin
 
if reset='1' then
flag <= '0';
elsif rising_edge(clk) then
if ack='1' or clear='1' then
flag <= '0';
elsif irq='1' then
flag <= '1';
end if;
end if;
 
end process;
 
pending <= flag and ena;
 
end rtl;
 
--
-- the sc_sys component
--
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
34,7 → 108,9
 
generic (addr_bits : integer;
clk_freq : integer;
cpu_id : integer);
cpu_id : integer;
cpu_cnt : integer;
num_io_int : integer := 2); -- a default value to play with SW interrupts
port (
clk : in std_logic;
reset : in std_logic;
50,14 → 126,22
--
-- Interrupts from IO devices
--
irq_in : out irq_in_type;
irq_in : out irq_bcf_type;
irq_out : in irq_ack_type;
exc_req : in exception_type;
 
io_int : in std_logic_vector(num_io_int-1 downto 0) := "00";
sync_out : in sync_out_type;
sync_out : in sync_out_type := NO_SYNC;
sync_in : out sync_in_type;
wd : out std_logic
wd : out std_logic;
-- remove the comment for RAM access counting
-- ram_count : in std_logic;
 
inval : out std_logic
 
);
end sc_sys ;
 
70,26 → 154,51
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_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);
signal cpu_identity : std_logic_vector(31 downto 0);
signal lock_reqest : std_logic;
-- remove the comment for RAM access counting
-- signal ram_counter : std_logic_vector(31 downto 0);
 
 
signal cnt_ena : unsigned(31 downto 0);
--
-- signals for interrupt handling
--
signal int_pend : std_logic;
signal int_ena : std_logic;
signal exc_pend : std_logic;
signal irq_gate : std_logic;
signal irq_dly : std_logic;
signal exc_dly : std_logic;
 
--
-- signals for interrupt source state machines
--
constant NUM_INT : integer := num_io_int+1; -- plus timer interrupt
signal hwreq : std_logic_vector(NUM_INT-1 downto 0);
signal swreq : std_logic_vector(NUM_INT-1 downto 0);
signal intreq : std_logic_vector(NUM_INT-1 downto 0);
signal mask : std_logic_vector(NUM_INT-1 downto 0);
signal ack : std_logic_vector(NUM_INT-1 downto 0);
signal pending : std_logic_vector(NUM_INT-1 downto 0);
signal prioint : std_logic_vector(4 downto 0);
signal intnr : std_logic_vector(4 downto 0); -- processing int number
signal clearall : std_logic;
 
begin
 
cpu_identity <= std_logic_vector(to_unsigned(cpu_id,32));
rdy_cnt <= "00"; -- no wait states
 
rdy_cnt <= "11" when (sync_out.halted='1' and lock_reqest='1') else "00";
--
-- read cnt values
--
96,25 → 205,39
process(clk, reset)
begin
 
if (reset='1') then
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" =>
case address(3 downto 0) is
when "0000" =>
rd_data <= clock_cnt;
when "001" =>
when "0001" =>
rd_data <= us_cnt;
when "100" =>
when "0010" =>
rd_data(4 downto 0) <= intnr;
rd_data(31 downto 5) <= (others => '0');
when "0100" =>
rd_data(7 downto 0) <= exc_type;
rd_data(31 downto 8) <= (others => '0');
when "110" =>
when "0101" =>
rd_data(0) <= lock_reqest;
rd_data(31 downto 1) <= (others => '0');
when "0110" =>
rd_data <= cpu_identity;
-- when "111" =>
when others =>
when "0111" =>
rd_data(0) <= sync_out.s_out;
rd_data(31 downto 1) <= (others => '0');
-- remove the comment for RAM access counting
-- when "1010" =>
-- rd_data(31 downto 0) <= ram_counter;
when "1011" =>
rd_data <= std_logic_vector(to_unsigned(cpu_cnt, 32));
when "1111" =>
-- nothing, cache inval is write only
when others =>
-- nothing
end case;
end if;
end if;
125,15 → 248,15
-- compare timer value and us counter
-- and generate single shot
--
process(us_cnt, irq_cnt) begin
process(us_cnt, timer_cnt) begin
timer_equ <= '0';
if us_cnt = irq_cnt then
if us_cnt = timer_cnt then
timer_equ <= '1';
end if;
end process;
 
process(clk, reset, timer_equ) begin
if (reset='1') then
process(clk, reset) begin
if reset='1' then
timer_dly <= '0';
elsif rising_edge(clk) then
timer_dly <= timer_equ;
145,30 → 268,73
--
-- int processing from timer and yield request
--
process(clk, reset, timer_int, yield_int) begin
 
if (reset='1') then
timer <= '0';
yield <= '0';
hwreq(0) <= timer_int;
hwreq(NUM_INT-1 downto 1) <= io_int;
 
process(prioint, irq_out.ack_irq) begin
ack <= (others => '0');
ack(to_integer(unsigned(prioint))) <= irq_out.ack_irq;
end process;
 
gen_int: for i in 0 to NUM_INT-1 generate
intreq(i) <= hwreq(i) or swreq(i);
cis: entity work.intstate
port map(clk, reset,
irq => intreq(i),
ena => mask(i),
ack => ack(i),
clear => clearall,
pending => pending(i)
);
 
end generate;
 
-- find highest priority pending interrupt
process(pending) begin
 
int_pend <= '0';
prioint <= (others => '0');
for i in NUM_INT-1 downto 0 loop
if pending(i)='1' then
int_pend <= '1';
prioint <= std_logic_vector(to_unsigned(i, 5));
exit;
end if;
end loop;
end process;
 
--
-- interrupt processing
--
process(clk, reset) begin
 
if reset='1' then
irq_dly <= '0';
exc_dly <= '0';
intnr <= (others => '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;
 
irq_dly <= irq_gate;
exc_dly <= exc_pend;
-- save processing interrupt number
if irq_out.ack_irq='1' then
intnr <= prioint;
end if;
 
end if;
 
end process;
 
irq_in.irq <= timer or yield;
irq_gate <= int_pend and int_ena;
irq_in.irq <= irq_gate and not irq_dly;
irq_in.exc <= exc_pend and not exc_dly;
irq_in.ena <= int_ena;
 
 
 
--
-- counters
-- pre_scale is 8 bit => fmax = 255 MHz
201,54 → 367,78
begin
if (reset='1') then
 
irq_in.irq_ena <= '0';
irq_cnt <= (others => '0');
int_ack <= '0';
int_ena <= '0';
timer_cnt <= (others => '0');
wd <= '0';
sync_in.s_in <= '0';
sync_in.lock_req <= '0';
lock_reqest <= '0';
 
exc_type <= (others => '0');
irq_in.exc_int <= '0';
exc_pend <= '0';
 
swreq <= (others => '0');
mask <= (others => '0');
clearall <= '0';
 
elsif rising_edge(clk) then
 
int_ack <= '0';
yield_int <= '0';
exc_pend <= '0';
swreq <= (others => '0');
clearall <= '0';
inval <= '0';
 
irq_in.exc_int <= '0';
-- disable interrupts on a taken interrupt or excption
if irq_out.ack_irq='1' or irq_out.ack_exc='1' then
int_ena <= '0';
end if;
 
-- exceptions from core or memory
if exc_req.spov='1' then
exc_type(2 downto 0) <= EXC_SPOV;
irq_in.exc_int <= '1';
exc_pend <= '1';
end if;
if exc_req.np='1' then
exc_type(2 downto 0) <= EXC_NP;
irq_in.exc_int <= '1';
exc_pend <= '1';
end if;
if exc_req.ab='1' then
exc_type(2 downto 0) <= EXC_AB;
irq_in.exc_int <= '1';
exc_pend <= '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" =>
case address(3 downto 0) is
when "0000" =>
int_ena <= wr_data(0);
when "0001" =>
timer_cnt <= wr_data;
when "0010" =>
swreq(to_integer(unsigned(wr_data))) <= '1';
when "0011" =>
wd <= wr_data(0);
when "100" =>
when "0100" =>
exc_type <= wr_data(7 downto 0);
irq_in.exc_int <= '1';
when "110" =>
exc_pend <= '1';
when "0101" =>
sync_in.lock_req <= wr_data(0);
lock_reqest <= wr_data(0);
-- implicit cache invalidation on monitorenter
inval <= wr_data(0);
when "0110" =>
-- nothing, processor id is read only
when "0111" =>
sync_in.s_in <= wr_data(0);
when "1000" =>
mask <= wr_data(NUM_INT-1 downto 0);
when "1001" =>
clearall <= '1';
when "1010" =>
-- nothing, ram_counter is read only
when "1111" =>
-- explicit cache invalidation
inval <= '1';
when others =>
-- when "111" =>
sync_in.s_in <= wr_data(0);
end case;
end if;
255,4 → 445,16
end if;
end process;
 
-- remove the comment for RAM access counting
-- process(clk, reset)
-- begin
-- if reset = '1' then
-- ram_counter <= (others => '0');
-- elsif rising_edge(clk) then
-- if (ram_count='0') then
-- ram_counter <= std_logic_vector(unsigned(ram_counter) + 1);
-- end if;
-- end if;
-- end process;
 
end rtl;
/trunk/vhdl/sc_cnt.vhd
1,4 → 1,25
--
--
-- This file is a part of JOP, the Java Optimized Processor
--
-- Copyright (C) 2001-2008, Martin Schoeberl (martin@jopdesign.com)
--
-- This program is free software: you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
-- the Free Software Foundation, either version 3 of the License, or
-- (at your option) any later version.
--
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with this program. If not, see <http://www.gnu.org/licenses/>.
--
 
 
--
-- sc_cnt.vhd
--
-- counter, interrrupt handling and watchdog bit
/trunk/vhdl/sc_arbiter_pack.vhd
1,3 → 1,23
--
-- This file is part of JOP, the Java Optimized Processor
--
-- Copyright (C) 2007,2008, Christof Pitter
--
-- This program is free software: you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
-- the Free Software Foundation, either version 3 of the License, or
-- (at your option) any later version.
--
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with this program. If not, see <http://www.gnu.org/licenses/>.
--
 
 
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
6,7 → 26,7
 
package sc_arbiter_pack is
type arb_out_type is array (integer range <>) of sc_mem_out_type;
type arb_out_type is array (integer range <>) of sc_out_type;
type arb_in_type is array (integer range <>) of sc_in_type;
 
end sc_arbiter_pack;
/trunk/vhdl/sc_arbiter_fair.vhd
0,0 → 1,442
--
-- This file is part of JOP, the Java Optimized Processor
--
-- Copyright (C) 2007,2008, Christof Pitter
--
-- This program is free software: you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
-- the Free Software Foundation, either version 3 of the License, or
-- (at your option) any later version.
--
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with this program. If not, see <http://www.gnu.org/licenses/>.
--
 
 
 
 
-- 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!
-- 150108: Quasi Round Robin Arbiter -- added sync signal to arbiter
-- 160108: First tests running with new Round Robin Arbiter
-- 250408: Renaming of this_state to mode, follow_state to next_mode, reg_in to reg_out
-- 240708: added data_reg for each CPU in arbiter
-- 070808: removed combinatorial loop (pipelined bug)
-- 210808: - reg_in_rd_data(i) also gets loaded when rdy_cnt = 3 using pipelined access
-- - arb_in(i).rd_data gets mem_in.rd_data when rdy_cnt 3 using pipelined access
 
 
-- Functioning: See description of SIES08 paper
 
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
 
use work.sc_pack.all;
use work.sc_arbiter_pack.all;
use work.jop_types.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_out_type;
mem_in : in sc_in_type
);
end arbiter;
 
 
architecture rtl of arbiter is
 
-- stores the signals in a 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_out_type is array (0 to cpu_cnt-1) of reg_type;
signal reg_out : reg_out_type;
-- register to CPU for rd_data
type reg_in_type is array (0 to cpu_cnt-1) of std_logic_vector(31 downto 0);
signal reg_in_rd_data : reg_in_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, servR, servW);
type serve_array is array (0 to cpu_cnt-1) of serve_type;
signal mode : serve_array;
signal next_mode : serve_array;
-- arbiter
type set_type is array (0 to cpu_cnt-1) of std_logic_vector(1 downto 0);
signal set : set_type;
type pipelined_type is array (0 to cpu_cnt-1) of std_logic;
signal pipelined : pipelined_type;
signal next_pipelined : pipelined_type;
-- counter
signal counter : integer;
type slot_type is array (0 to cpu_cnt-1) of std_logic;
signal slot : slot_type; -- defines which CPU is on turn
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_out(i).rd <= '0';
reg_out(i).wr <= '0';
reg_out(i).wr_data <= (others => '0');
reg_out(i).address <= (others => '0');
elsif rising_edge(clk) then
if arb_out(i).rd = '1' or arb_out(i).wr = '1' then
reg_out(i).rd <= arb_out(i).rd;
reg_out(i).wr <= arb_out(i).wr;
reg_out(i).address <= arb_out(i).address;
reg_out(i).wr_data <= arb_out(i).wr_data;
end if;
end if;
end process;
end generate;
-- Generate Counter
process(clk, reset)
begin
if reset = '1' then
counter <= 0;
elsif rising_edge(clk) then
counter <= counter + 1;
for i in 0 to cpu_cnt-1 loop
if next_mode(i) = servR or next_mode(i) = servW then
if mem_in.rdy_cnt = 1 and arb_out(i).rd = '0' then
if counter = cpu_cnt-1 then
counter <= 0;
else
counter <= counter+1;
end if;
exit;
else
counter <= counter;
exit;
end if;
elsif counter = cpu_cnt-1 then
counter <= 0;
end if;
end loop;
end if;
end process;
-- The slot is assigned depending on the counter
process(counter)
begin
for j in 0 to cpu_cnt-1 loop
if j = counter then
slot(j) <= '1';
else
slot(j) <= '0';
end if;
end loop;
end process;
-- Generates next state of the FSM for each master
gen_next_state: for i in 0 to cpu_cnt-1 generate
process(state, mode, slot, mem_in, arb_out, pipelined)
begin
 
next_state(i) <= state(i);
 
case state(i) is
when idle =>
next_pipelined(i) <= '0';
-- is CPU allowed to access
if (slot(i) = '1') then
-- pipelined read access
if (mode(i) = servR) and (mem_in.rdy_cnt = 1) and (arb_out(i).rd = '1') then
next_state(i) <= read;
next_pipelined(i) <= '1';
elsif (mode(i) = servR) and (mem_in.rdy_cnt = 0) then
if arb_out(i).rd = '1' then
next_state(i) <= read;
elsif arb_out(i).wr = '1' then
next_state(i) <= write;
end if;
elsif (mode(i) = servW) and (mem_in.rdy_cnt = 0) then
if arb_out(i).rd = '1' then
next_state(i) <= read;
elsif arb_out(i).wr = '1' then
next_state(i) <= write;
end if;
elsif (mode(i) = idl) and (mem_in.rdy_cnt = 0) then
if arb_out(i).rd = '1' then
next_state(i) <= read;
elsif arb_out(i).wr = '1' then
next_state(i) <= write;
end if;
-- all other kinds (can that happen at all?)
else
if arb_out(i).rd = '1' then
next_state(i) <= waitingR;
elsif arb_out(i).wr = '1' then
next_state(i) <= waitingW;
end if;
end if;
 
-- CPU is not allowed to access
else
if arb_out(i).rd = '1' then
next_state(i) <= waitingR;
elsif arb_out(i).wr = '1' then
next_state(i) <= waitingW;
end if;
end if;
when read =>
next_state(i) <= idle;
next_pipelined(i) <= '0';
if pipelined(i) = '1' then
next_pipelined(i) <= '1';
end if;
when write =>
next_state(i) <= idle;
next_pipelined(i) <= '0';
when waitingR =>
next_pipelined(i) <= '0';
if ((mem_in.rdy_cnt = 0) and (slot(i) = '1')) then
next_state(i) <= sendR;
else
next_state(i) <= waitingR;
end if;
when sendR =>
next_state(i) <= idle;
next_pipelined(i) <= '0';
when waitingW =>
next_pipelined(i) <= '0';
if ((mem_in.rdy_cnt = 0) and (slot(i) = '1')) then
next_state(i) <= sendW;
else
next_state(i) <= waitingW;
end if;
when sendW =>
next_state(i) <= idle;
next_pipelined(i) <= '0';
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;
pipelined(i) <= '0';
elsif (rising_edge(clk)) then
state(i) <= next_state(i);
pipelined(i) <= next_pipelined(i);
end if;
end process;
end generate;
 
 
-- The arbiter output
process (arb_out, reg_out, next_state)
begin
 
mem_out.rd <= '0';
mem_out.wr <= '0';
mem_out.address <= (others => '0');
mem_out.wr_data <= (others => '0');
mem_out.atomic <= '0';
for i in 0 to cpu_cnt-1 loop
set(i) <= "00";
case next_state(i) is
when idle =>
when read =>
set(i) <= "01";
mem_out.rd <= arb_out(i).rd;
mem_out.address <= arb_out(i).address;
when write =>
set(i) <= "10";
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) <= "01";
mem_out.rd <= reg_out(i).rd;
mem_out.address <= reg_out(i).address;
when waitingW =>
when sendW =>
set(i) <= "10";
mem_out.wr <= reg_out(i).wr;
mem_out.address <= reg_out(i).address;
mem_out.wr_data <= reg_out(i).wr_data;
end case;
end loop;
end process;
 
-- generation of next_mode
gen_serve: for i in 0 to cpu_cnt-1 generate
process(mem_in, set, mode)
begin
case mode(i) is
when idl =>
next_mode(i) <= idl;
if set(i) = "01" then
next_mode(i) <= servR;
elsif set(i) = "10" then
next_mode(i) <= servW;
end if;
when servR =>
next_mode(i) <= servR;
if mem_in.rdy_cnt = 0 and set(i) = "00" then
next_mode(i) <= idl;
end if;
when servW =>
next_mode(i) <= servW;
if mem_in.rdy_cnt = 0 and set(i) = "00" then
next_mode(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
mode(i) <= idl;
elsif (rising_edge(clk)) then
mode(i) <= next_mode(i);
end if;
end process;
end generate;
 
 
 
-- Registers rd_data for each CPU
gen_reg_in: for i in 0 to cpu_cnt-1 generate
process(clk, reset)
begin
if reset = '1' then
reg_in_rd_data(i) <= (others => '0');
elsif rising_edge(clk) then
if mode(i) = servR then
if mem_in.rdy_cnt = 0 then
reg_in_rd_data(i) <= mem_in.rd_data;
-- added mem_in.rdy_cnt = 3.
-- More correct would be: ((mem_in.rdy_cnt = ram_cnt) or (mem_in.rdy_cnt = 3))
elsif ((( mem_in.rdy_cnt = 2 ) or ( mem_in.rdy_cnt = 3 )) and (next_pipelined(i) = '1')) then
reg_in_rd_data(i) <= mem_in.rd_data;
end if;
end if;
end if;
end process;
end generate;
 
 
-- Generates rdy_cnt and rd_data for all CPUs
gen_rdy_cnt: for i in 0 to cpu_cnt-1 generate
process (mem_in, state, mode, reg_in_rd_data, next_pipelined)
begin
arb_in(i).rd_data <= reg_in_rd_data(i);
arb_in(i).rdy_cnt <= mem_in.rdy_cnt;
case state(i) is
when idle =>
if (mode(i) = idl) then
arb_in(i).rdy_cnt <= "00";
elsif (mode(i) = servR) and (mem_in.rdy_cnt = 0) then
arb_in(i).rd_data <= mem_in.rd_data;
end if;
when read =>
if (mode(i) = servR) then
if (mem_in.rdy_cnt = 0) then
arb_in(i).rd_data <= mem_in.rd_data;
-- added mem_in.rdy_cnt = 3
elsif ((( mem_in.rdy_cnt = 2 ) or ( mem_in.rdy_cnt = 3 )) and (next_pipelined(i) = '1')) then
arb_in(i).rd_data <= mem_in.rd_data;
end if;
end if;
when write =>
when waitingR =>
arb_in(i).rdy_cnt <= "11";
if mode(i) = servR then
arb_in(i).rd_data <= mem_in.rd_data;
end if;
when sendR =>
when waitingW =>
arb_in(i).rdy_cnt <= "11";
when sendW =>
end case;
end process;
end generate;
 
end rtl;
/trunk/vhdl/sc_fpu.vhd
1,3 → 1,24
--
--
-- This file is a part of JOP, the Java Optimized Processor
--
-- Copyright (C) 2001-2008, Martin Schoeberl (martin@jopdesign.com)
--
-- This program is free software: you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
-- the Free Software Foundation, either version 3 of the License, or
-- (at your option) any later version.
--
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with this program. If not, see <http://www.gnu.org/licenses/>.
--
 
 
-- This is the SimpCon interface to the FPU
--
 
/trunk/vhdl/sc_spi.vhd
0,0 → 1,290
--
--
-- address map:
--
-- 0 SS Register
-- 1 SCLK Divider
-- 2 Data in
-- 3 Data out
-- 4 Interrupt Config Status
--
 
 
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
 
use work.jop_types.all;
 
entity sc_spi is
 
generic (addr_bits : integer;
clk_freq : 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);
 
-- SPI Con
 
slave_s : out std_logic_vector(7 downto 0);
miso : in std_logic;
mosi : out std_logic;
sclk : out std_logic;
 
);
end sc_spi;
 
architecture rtl of sc_spi is
 
signal spi_out : std_logic_vector(7 downto 0);
signal spi_in : std_logic_vector(7 downto 0);
 
signal read_ack : std_logic;
signal fifo_wr : std_logic;
 
--
--
constant WS : integer := (clk_freq/20000000)+1;
signal cnt : integer range 0 to WS;
 
--
-- FIFO signals
--
signal tf_dout : std_logic_vector(7 downto 0); -- fifo out
signal tf_rd : std_logic;
signal tf_empty : std_logic;
signal tf_full : std_logic;
 
signal rf_din : std_logic_vector(7 downto 0); -- fifo input
signal rf_wr : std_logic;
signal rf_empty : std_logic;
signal rf_full : std_logic;
 
 
--
-- USB interface signals
--
type state_type is (idle, inact, rx1, rx2, tx1, tx2);
signal state : state_type;
 
signal spi_dout : std_logic_vector(7 downto 0);
signal spi_din : std_logic_vector(7 downto 0);
 
--signal nrxf_buf : std_logic_vector(1 downto 0);
--signal ntxe_buf : std_logic_vector(1 downto 0);
--signal rdr, wrr : std_logic_vector(7 downto 0);
--signal data_oe : std_logic;
 
begin
 
rdy_cnt <= "00"; -- no wait states
rd_data(31 downto 8) <= std_logic_vector(to_unsigned(0, 24));
--
-- The registered MUX is all we need for a SimpCon read.
-- The read data is stored in registered rd_data.
--
process(clk, reset)
begin
 
if (reset='1') then
rd_data(7 downto 0) <= (others => '0');
elsif rising_edge(clk) then
 
read_ack <= '0';
if rd='1' then
case address(2 downto 0) is
when "000" =>
rd_data(7 downto 0) <= slave_s;
rd_data(31 downto 8) <= (others => '0');
when "001" =>
rd_data(7 downto 0) <= WS;
rd_data(31 downto 8) <= (others => '0');
when "010" =>
rd_data(7 downto 0) <= spi_din;
rd_data(31 downto 8) <= (others => '0');
when "011" =>
rd_data(7 downto 0) <= spi_dout;
rd_data(31 downto 8) <= (others => '0');
when "100" =>
rd_data(7 downto 0) <= spi_dout;
rd_data(31 downto 8) <= (others => '0');
-- when "111" =>
when others =>
rd_data(0) <= '0';
rd_data(31 downto 1) <= (others => '0');
end case;
end if;
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" =>
spi_din <= wr_data;;
when "011" =>
spi_dout <= wr_data;;
when "100" =>
spi_dout <= wr_data;;
when "110" =>
-- nothing, processor id is read only
when others =>
-- when "111" =>
sync_in.s_in <= wr_data(0);
end case;
end if;
end process;
 
 
-- we don't use the send immediate
nsi <= '1';
 
 
--
-- receive fifo
--
rxfifo: entity work.fifo generic map (
width => 8,
depth => 4,
thres => 2 -- we don't care about the half signal
) port map (
clk => clk,
reset => reset,
din => rf_din,
dout => usb_dout,
rd => read_ack,
wr => rf_wr,
empty => rf_empty,
full => rf_full,
half => open
);
 
--
-- transmit fifo
--
txfifo: entity work.fifo generic map (
width => 8,
depth => 4,
thres => 2 -- we don't care about the half signal
) port map (
clk => clk,
reset => reset,
din => wr_data(7 downto 0),
dout => tf_dout,
rd => tf_rd,
wr => fifo_wr,
empty => tf_empty,
full => tf_full,
half => open
);
 
 
--
-- state machine for the usb bus
--
process(clk, reset)
 
begin
 
if (reset='1') then
state <= idle;
nrxf_buf <= "11";
ntxe_buf <= "11";
cnt <= WS;
 
rdr <= (others => '0');
wrr <= (others => '0');
 
tf_rd <= '0';
rf_wr <= '0';
 
nrd <= '1';
ft_wr <= '0';
 
elsif rising_edge(clk) then
 
-- input register
nrxf_buf(0) <= nrxf;
nrxf_buf(1) <= nrxf_buf(0);
ntxe_buf(0) <= ntxe;
ntxe_buf(1) <= ntxe_buf(0);
 
case state is
 
when idle =>
cnt <= WS;
tf_rd <= '0';
rf_wr <= '0';
nrd <= '1';
ft_wr <= '0';
data_oe <= '0';
if rf_full='0' and nrxf_buf(1)='0' then
nrd <= '0';
state <= rx1;
elsif tf_empty='0' and ntxe_buf(1)='0' then
ft_wr <= '1';
wrr <= tf_dout;
tf_rd <= '1';
state <= tx1;
end if;
 
when inact =>
tf_rd <= '0';
rf_wr <= '0';
nrd <= '1';
ft_wr <= '0';
data_oe <= '0';
cnt <= cnt-1;
if cnt=0 then
state <= idle;
end if;
 
 
when rx1 =>
cnt <= cnt-1;
if cnt=0 then
state <= rx2;
rdr <= data;
end if;
 
when rx2 =>
nrd <= '1';
rf_wr <= '1';
cnt <= WS;
state <= inact;
when tx1 =>
tf_rd <= '0';
data_oe <= '1';
cnt <= cnt-1;
if cnt=0 then
state <= tx2;
ft_wr <= '0';
end if;
 
when tx2 =>
data_oe <= '0';
cnt <= WS;
state <= inact;
 
end case;
end if;
 
end process;
 
data <= wrr when data_oe='1' else (others => 'Z');
rf_din <= data;
 
end rtl;
/trunk/vhdl/sc_arbiter_tdma.vhd
0,0 → 1,504
--
-- This file is part of JOP, the Java Optimized Processor
--
-- Copyright (C) 2007,2008, Christof Pitter
--
-- This program is free software: you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
-- the Free Software Foundation, either version 3 of the License, or
-- (at your option) any later version.
--
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with this program. If not, see <http://www.gnu.org/licenses/>.
--
 
 
 
 
-- 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!
-- 150108: Quasi Round Robin Arbiter -- added sync signal to arbiter
-- 160108: First tests running with new Round Robin Arbiter
-- 190208: Development of TDMA Arbiter
-- 130308: * Renaming of this_state to mode, follow_state to next_mode
-- * counter dependencies moved from FSM to slot generation
-- * changed set to 2 bits
-- * changed serv to servR and servW
-- * added signal pipelined
-- * added rd_data register for each CPU
-- 140308: Working version
-- 070808: removed combinatorial loop (pipelined bug)
-- 210808: - reg_in_rd_data(i) also gets loaded when rdy_cnt = 3 using pipelined access
-- - arb_in(i).rd_data gets mem_in.rd_data when rdy_cnt 3 using pipelined access
 
-- TODO: - Add atomic for Wolfgang
-- - full pipelined version
-- - add period and time slots from software using RAM
 
 
 
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
 
use work.sc_pack.all;
use work.sc_arbiter_pack.all;
use work.jop_types.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_out_type;
mem_in : in sc_in_type
);
end arbiter;
 
 
architecture rtl of arbiter is
 
-- stores the signals in a 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_out_type is array (0 to cpu_cnt-1) of reg_type;
signal reg_out : reg_out_type;
-- register to CPU for rd_data
type reg_in_type is array (0 to cpu_cnt-1) of std_logic_vector(31 downto 0);
signal reg_in_rd_data : reg_in_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, servR, servW);
type serve_array is array (0 to cpu_cnt-1) of serve_type;
signal mode : serve_array;
signal next_mode : serve_array;
-- arbiter
type set_type is array (0 to cpu_cnt-1) of std_logic_vector(1 downto 0);
signal set : set_type;
type pipelined_type is array (0 to cpu_cnt-1) of std_logic;
signal pipelined : pipelined_type;
signal next_pipelined : pipelined_type;
-- counter
signal counter : integer;
signal period : integer;
signal slot_length : integer;
type time_type is array (0 to cpu_cnt-1) of integer;
signal cpu_time : time_type; -- how much clock cycles each CPU
type slot_type is array (0 to cpu_cnt-1) of std_logic;
signal slot : slot_type; -- defines which CPU is on turn
-- read and write gaps
 
signal read_gap : integer;
signal write_gap : integer;
begin
 
-- Constants for read_gap, write_gap, slot_length:
-- DE2 board: 6 cycle memory write, 4 cycle memory read
-- write_gap <= 5; read_gap <= 3;
-- minimal slot_length <= 6;
-- cyc12 board: 3 cycle memory write, 2 cycle memory read
-- write_gap <= 2; read_gap <= 1;
-- minimal slot_length <= 3;
 
write_gap <= 2;
read_gap <= 1;
slot_length <=7;
period <= cpu_cnt*slot_length;
 
-- generate slot information
slots: for i in 0 to cpu_cnt-1 generate
cpu_time(i) <= (i+1)*slot_length;
end generate;
 
-- TODO: should really be configrable with: number of CPUs, slot length,
-- and memory access time. Should use assert to check that the slot length
-- is longer than the memory access time.
 
 
-- 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_out(i).rd <= '0';
reg_out(i).wr <= '0';
reg_out(i).wr_data <= (others => '0');
reg_out(i).address <= (others => '0');
elsif rising_edge(clk) then
if arb_out(i).rd = '1' or arb_out(i).wr = '1' then
reg_out(i).rd <= arb_out(i).rd;
reg_out(i).wr <= arb_out(i).wr;
reg_out(i).address <= arb_out(i).address;
reg_out(i).wr_data <= arb_out(i).wr_data;
end if;
end if;
end process;
end generate;
-- Generate Counter
process(clk, reset)
begin
if reset = '1' then
counter <= 0;
elsif rising_edge(clk) then
counter <= counter + 1;
if counter = period-1 then
counter <= 0;
end if;
end if;
end process;
-- A time slot is assigned to each CPU
process(counter, cpu_time, read_gap, write_gap, arb_out)
begin
for j in 0 to cpu_cnt-1 loop
slot(j) <= '0';
end loop;
if (counter > -1) and (counter < cpu_time(0)-write_gap) then
slot(0) <= '1';
elsif (counter > -1) and (counter < cpu_time(0)-read_gap) and (arb_out(0).rd = '1') then -- rd is 2 cycles longer allowed
slot(0) <= '1';
elsif (counter > cpu_time(0)-1) and (counter < cpu_time(1)-write_gap) then
slot(1) <= '1';
elsif (counter > cpu_time(0)-1) and (counter < cpu_time(1)-read_gap) and (arb_out(1).rd = '1') then -- rd is 2 cycles longer allowed
slot(1) <= '1';
elsif (counter > cpu_time(1)-1) and (counter < cpu_time(2)-write_gap) then
slot(2) <= '1';
elsif (counter > cpu_time(1)-1) and (counter < cpu_time(2)-read_gap) and (arb_out(2).rd = '1') then -- rd is 2 cycles longer allowed
slot(2) <= '1';
--
-- elsif (counter > cpu_time(2)-1) and (counter < cpu_time(3)-write_gap) then
-- slot(3) <= '1';
-- elsif (counter > cpu_time(2)-1) and (counter < cpu_time(3)-read_gap) and (arb_out(3).rd = '1') then -- rd is 2 cycles longer allowed
-- slot(3) <= '1';
--
-- elsif (counter > cpu_time(3)-1) and (counter < cpu_time(4)-write_gap) then
-- slot(4) <= '1';
-- elsif (counter > cpu_time(3)-1) and (counter < cpu_time(4)-read_gap) and (arb_out(4).rd = '1') then -- rd is 2 cycles longer allowed
-- slot(4) <= '1';
--
-- elsif (counter > cpu_time(4)-1) and (counter < cpu_time(5)-write_gap) then
-- slot(5) <= '1';
-- elsif (counter > cpu_time(4)-1) and (counter < cpu_time(5)-read_gap) and (arb_out(5).rd = '1') then -- rd is 2 cycles longer allowed
-- slot(5) <= '1';
--
-- elsif (counter > cpu_time(5)-1) and (counter < cpu_time(6)-write_gap) then
-- slot(6) <= '1';
-- elsif (counter > cpu_time(5)-1) and (counter < cpu_time(6)-read_gap) and (arb_out(6).rd = '1') then -- rd is 2 cycles longer allowed
-- slot(6) <= '1';
--
-- elsif (counter > cpu_time(6)-1) and (counter < cpu_time(7)-write_gap) then
-- slot(7) <= '1';
-- elsif (counter > cpu_time(6)-1) and (counter < cpu_time(7)-read_gap) and (arb_out(7).rd = '1') then -- rd is 2 cycles longer allowed
-- slot(7) <= '1';
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(state, mode, slot, counter, mem_in, arb_out, pipelined)
begin
 
next_state(i) <= state(i);
 
case state(i) is
when idle =>
next_pipelined(i) <= '0';
-- is CPU allowed to access
if (slot(i) = '1') then
-- pipelined read access
if (mode(i) = servR) and (mem_in.rdy_cnt = 1) and (arb_out(i).rd = '1') then
next_state(i) <= read;
next_pipelined(i) <= '1';
elsif (mode(i) = servR) and (mem_in.rdy_cnt = 0) then
if arb_out(i).rd = '1' then
next_state(i) <= read;
elsif arb_out(i).wr = '1' then
next_state(i) <= write;
end if;
elsif (mode(i) = servW) and (mem_in.rdy_cnt = 0) then
if arb_out(i).rd = '1' then
next_state(i) <= read;
elsif arb_out(i).wr = '1' then
next_state(i) <= write;
end if;
elsif (mode(i) = idl) and (mem_in.rdy_cnt = 0) then
if arb_out(i).rd = '1' then
next_state(i) <= read;
elsif arb_out(i).wr = '1' then
next_state(i) <= write;
end if;
-- all other kinds (can that happen at all?)
else
if arb_out(i).rd = '1' then
next_state(i) <= waitingR;
elsif arb_out(i).wr = '1' then
next_state(i) <= waitingW;
end if;
end if;
 
-- CPU is not allowed to access
else
if arb_out(i).rd = '1' then
next_state(i) <= waitingR;
elsif arb_out(i).wr = '1' then
next_state(i) <= waitingW;
end if;
end if;
when read =>
next_state(i) <= idle;
next_pipelined(i) <= '0';
if pipelined(i) = '1' then
next_pipelined(i) <= '1';
end if;
when write =>
next_state(i) <= idle;
next_pipelined(i) <= '0';
when waitingR =>
next_pipelined(i) <= '0';
if ((mem_in.rdy_cnt = 0) and (slot(i) = '1')) then
next_state(i) <= sendR;
else
next_state(i) <= waitingR;
end if;
when sendR =>
next_state(i) <= idle;
next_pipelined(i) <= '0';
when waitingW =>
next_pipelined(i) <= '0';
if ((mem_in.rdy_cnt = 0) and (slot(i) = '1')) then
next_state(i) <= sendW;
else
next_state(i) <= waitingW;
end if;
when sendW =>
next_state(i) <= idle;
next_pipelined(i) <= '0';
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;
pipelined(i) <= '0';
elsif (rising_edge(clk)) then
state(i) <= next_state(i);
pipelined(i) <= next_pipelined(i);
end if;
end process;
end generate;
 
 
-- The arbiter output
process (arb_out, reg_out, next_state)
begin
 
mem_out.rd <= '0';
mem_out.wr <= '0';
mem_out.address <= (others => '0');
mem_out.wr_data <= (others => '0');
mem_out.atomic <= '0';
for i in 0 to cpu_cnt-1 loop
set(i) <= "00";
case next_state(i) is
when idle =>
when read =>
set(i) <= "01";
mem_out.rd <= arb_out(i).rd;
mem_out.address <= arb_out(i).address;
when write =>
set(i) <= "10";
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) <= "01";
mem_out.rd <= reg_out(i).rd;
mem_out.address <= reg_out(i).address;
when waitingW =>
when sendW =>
set(i) <= "10";
mem_out.wr <= reg_out(i).wr;
mem_out.address <= reg_out(i).address;
mem_out.wr_data <= reg_out(i).wr_data;
end case;
end loop;
end process;
 
-- generation of next_mode
gen_serve: for i in 0 to cpu_cnt-1 generate
process(mem_in, set, mode)
begin
case mode(i) is
when idl =>
next_mode(i) <= idl;
if set(i) = "01" then
next_mode(i) <= servR;
elsif set(i) = "10" then
next_mode(i) <= servW;
end if;
when servR =>
next_mode(i) <= servR;
if mem_in.rdy_cnt = 0 and set(i) = "00" then
next_mode(i) <= idl;
end if;
when servW =>
next_mode(i) <= servW;
if mem_in.rdy_cnt = 0 and set(i) = "00" then
next_mode(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
mode(i) <= idl;
elsif (rising_edge(clk)) then
mode(i) <= next_mode(i);
end if;
end process;
end generate;
 
 
 
-- Registers rd_data for each CPU
gen_reg_in: for i in 0 to cpu_cnt-1 generate
process(clk, reset)
begin
if reset = '1' then
reg_in_rd_data(i) <= (others => '0');
elsif rising_edge(clk) then
if mode(i) = servR then
if mem_in.rdy_cnt = 0 then
reg_in_rd_data(i) <= mem_in.rd_data;
-- added mem_in.rdy_cnt = 3.
-- More correct would be: ((mem_in.rdy_cnt = ram_cnt) or (mem_in.rdy_cnt = 3))
elsif ((( mem_in.rdy_cnt = 2 ) or ( mem_in.rdy_cnt = 3 )) and next_pipelined(i) = '1') then
reg_in_rd_data(i) <= mem_in.rd_data;
end if;
end if;
end if;
end process;
end generate;
 
 
-- Generates rdy_cnt and rd_data for all CPUs
gen_rdy_cnt: for i in 0 to cpu_cnt-1 generate
process (mem_in, state, mode, next_pipelined, reg_in_rd_data)
begin
arb_in(i).rd_data <= reg_in_rd_data(i);
arb_in(i).rdy_cnt <= mem_in.rdy_cnt;
case state(i) is
when idle =>
if (mode(i) = idl) then
arb_in(i).rdy_cnt <= "00";
elsif (mode(i) = servR) and (mem_in.rdy_cnt = 0) then
arb_in(i).rd_data <= mem_in.rd_data;
end if;
when read =>
if (mode(i) = servR) then
if (mem_in.rdy_cnt = 0) then
arb_in(i).rd_data <= mem_in.rd_data;
-- added mem_in.rdy_cnt = 3.
-- More correct would be: ((mem_in.rdy_cnt = ram_cnt) or (mem_in.rdy_cnt = 3))
elsif ((( mem_in.rdy_cnt = 2 ) or ( mem_in.rdy_cnt = 3 )) and next_pipelined(i) = '1') then
arb_in(i).rd_data <= mem_in.rd_data;
end if;
end if;
when write =>
when waitingR =>
arb_in(i).rdy_cnt <= "11";
if mode(i) = servR then
arb_in(i).rd_data <= mem_in.rd_data;
end if;
when sendR =>
when waitingW =>
arb_in(i).rdy_cnt <= "11";
when sendW =>
end case;
end process;
end generate;
 
end rtl;
/trunk/vhdl/sc_mac.vhd
1,4 → 1,25
--
--
-- This file is a part of JOP, the Java Optimized Processor
--
-- Copyright (C) 2001-2008, Martin Schoeberl (martin@jopdesign.com)
--
-- This program is free software: you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
-- the Free Software Foundation, either version 3 of the License, or
-- (at your option) any later version.
--
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with this program. If not, see <http://www.gnu.org/licenses/>.
--
 
 
--
-- sc_mac.vhd
--
-- A simple MAC unit with a SimpCon interface
/trunk/vhdl/sc2avalon.vhd
1,4 → 1,25
--
--
-- This file is a part of JOP, the Java Optimized Processor
--
-- Copyright (C) 2001-2008, Martin Schoeberl (martin@jopdesign.com)
--
-- This program is free software: you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
-- the Free Software Foundation, either version 3 of the License, or
-- (at your option) any later version.
--
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with this program. If not, see <http://www.gnu.org/licenses/>.
--
 
 
--
-- sc2avalon.vhd
--
-- SimpCon to Avalon bridge
/trunk/vhdl/sc_test_slave.vhd
1,4 → 1,25
--
--
-- This file is a part of JOP, the Java Optimized Processor
--
-- Copyright (C) 2001-2008, Martin Schoeberl (martin@jopdesign.com)
--
-- This program is free software: you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
-- the Free Software Foundation, either version 3 of the License, or
-- (at your option) any later version.
--
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with this program. If not, see <http://www.gnu.org/licenses/>.
--
 
 
--
-- sc_test_slave.vhd
--
-- A simple test slave for the SimpCon interface
/trunk/vhdl/sc_arbiter_fixedpr.vhd
0,0 → 1,446
--
-- This file is part of JOP, the Java Optimized Processor
--
-- Copyright (C) 2007,2008, Christof Pitter
--
-- This program is free software: you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
-- the Free Software Foundation, either version 3 of the License, or
-- (at your option) any later version.
--
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with this program. If not, see <http://www.gnu.org/licenses/>.
--
 
 
 
 
-- 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!
-- 210208: Does not use atomic
 
 
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_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');
mem_out.atomic <= '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;

powered by: WebSVN 2.1.0

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