URL
https://opencores.org/ocsvn/the_wizardry_project/the_wizardry_project/trunk
Subversion Repositories the_wizardry_project
Compare Revisions
- This comparison shows the changes necessary to convert path
/the_wizardry_project/trunk/Wizardry/VHDL/Wizardry Top Level/Address Generation/JOP
- from Rev 11 to Rev 22
- ↔ Reverse comparison
Rev 11 → Rev 22
/sc_uart.vhd
0,0 → 1,383
-- |
-- |
-- 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 |
-- |
-- wr, rd should be one cycle long => trde, rdrf goes 0 one cycle later |
-- |
-- Author: Martin Schoeberl martin@jopdesign.com |
-- |
-- |
-- resources on ACEX1K30-3 |
-- |
-- 100 LCs, max 90 MHz |
-- |
-- resetting rts with fifo_full-1 works with C program on pc |
-- but not with javax.comm: sends some more bytes after deassert |
-- of rts (16 byte blocks regardless of rts). |
-- Try to stop with half full fifo. |
-- |
-- todo: |
-- |
-- |
-- 2000-12-02 first working version |
-- 2002-01-06 changed tdr and rdr to fifos. |
-- 2002-05-15 changed clkdiv calculation |
-- 2002-11-01 don't wait if read fifo is full, just drop the byte |
-- 2002-11-03 use threshold in fifo to reset rts |
-- don't send if cts is '0' |
-- 2002-11-08 rx fifo to 20 characters and stop after 4 |
-- 2003-07-05 new IO standard, change cts/rts to neg logic |
-- 2003-09-19 sync ncts in! |
-- 2004-03-23 two stop bits |
-- 2005-11-30 change interface to SimpCon |
-- 2006-08-07 rxd input register with clk to avoid Quartus tsu violation |
-- 2006-08-13 use 3 FFs for the rxd input at clk |
-- |
|
|
library ieee; |
use ieee.std_logic_1164.all; |
use ieee.numeric_std.all; |
|
entity sc_uart is |
|
generic (addr_bits : integer; |
clk_freq : integer; |
baud_rate : integer; |
txf_depth : integer; txf_thres : integer; |
rxf_depth : integer; rxf_thres : 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); |
|
txd : out std_logic; |
rxd : in std_logic; |
ncts : in std_logic; |
nrts : out std_logic |
); |
end sc_uart; |
|
architecture rtl of sc_uart is |
|
component fifo is |
|
generic (width : integer; depth : integer; thres : integer); |
port ( |
clk : in std_logic; |
reset : in std_logic; |
|
din : in std_logic_vector(width-1 downto 0); |
dout : out std_logic_vector(width-1 downto 0); |
|
rd : in std_logic; |
wr : in std_logic; |
|
empty : out std_logic; |
full : out std_logic; |
half : out std_logic |
); |
end component; |
|
-- |
-- signals for uart connection |
-- |
signal ua_dout : std_logic_vector(7 downto 0); |
signal ua_wr, tdre : std_logic; |
signal ua_rd, rdrf : std_logic; |
|
type uart_tx_state_type is (s0, s1); |
signal uart_tx_state : uart_tx_state_type; |
|
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 tf_half : std_logic; |
|
signal ncts_buf : std_logic_vector(2 downto 0); -- sync in |
|
signal tsr : std_logic_vector(9 downto 0); -- tx shift register |
|
signal tx_clk : std_logic; |
|
|
type uart_rx_state_type is (s0, s1, s2); |
signal uart_rx_state : uart_rx_state_type; |
|
signal rf_wr : std_logic; |
signal rf_empty : std_logic; |
signal rf_full : std_logic; |
signal rf_half : std_logic; |
|
signal rxd_reg : std_logic_vector(2 downto 0); |
signal rx_buf : std_logic_vector(2 downto 0); -- sync in, filter |
signal rx_d : std_logic; -- rx serial data |
|
signal rsr : std_logic_vector(9 downto 0); -- rx shift register |
|
signal rx_clk : std_logic; |
signal rx_clk_ena : std_logic; |
|
constant clk16_cnt : integer := (clk_freq/baud_rate+8)/16-1; |
|
|
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 |
|
ua_rd <= '0'; |
if rd='1' then |
-- that's our very simple address decoder |
if address(0)='0' then |
rd_data(7 downto 0) <= "000000" & rdrf & tdre; |
else |
rd_data(7 downto 0) <= ua_dout; |
ua_rd <= rd; |
end if; |
end if; |
end if; |
|
end process; |
|
-- write is on address offest 1 |
ua_wr <= wr and address(0); |
|
-- |
-- serial clock |
-- |
process(clk, reset) |
|
variable clk16 : integer range 0 to clk16_cnt; |
variable clktx : unsigned(3 downto 0); |
variable clkrx : unsigned(3 downto 0); |
|
begin |
if (reset='1') then |
clk16 := 0; |
clktx := "0000"; |
clkrx := "0000"; |
tx_clk <= '0'; |
rx_clk <= '0'; |
rx_buf <= "111"; |
|
elsif rising_edge(clk) then |
|
rxd_reg(0) <= rxd; -- to avoid setup timing error in Quartus |
rxd_reg(1) <= rxd_reg(0); |
rxd_reg(2) <= rxd_reg(1); |
|
if (clk16=clk16_cnt) then -- 16 x serial clock |
clk16 := 0; |
-- |
-- tx clock |
-- |
clktx := clktx + 1; |
if (clktx="0000") then |
tx_clk <= '1'; |
else |
tx_clk <= '0'; |
end if; |
-- |
-- rx clock |
-- |
if (rx_clk_ena='1') then |
clkrx := clkrx + 1; |
if (clkrx="1000") then |
rx_clk <= '1'; |
else |
rx_clk <= '0'; |
end if; |
else |
clkrx := "0000"; |
end if; |
-- |
-- sync in filter buffer |
-- |
rx_buf(0) <= rxd_reg(2); |
rx_buf(2 downto 1) <= rx_buf(1 downto 0); |
else |
clk16 := clk16 + 1; |
tx_clk <= '0'; |
rx_clk <= '0'; |
end if; |
|
|
end if; |
|
end process; |
|
-- |
-- transmit fifo |
-- |
cmp_tf: fifo generic map (8, txf_depth, txf_thres) |
port map (clk, reset, wr_data(7 downto 0), tf_dout, tf_rd, ua_wr, tf_empty, tf_full, tf_half); |
|
-- |
-- state machine for actual shift out |
-- |
process(clk, reset) |
|
variable i : integer range 0 to 11; |
|
begin |
|
if (reset='1') then |
uart_tx_state <= s0; |
tsr <= "1111111111"; |
tf_rd <= '0'; |
ncts_buf <= "111"; |
|
elsif rising_edge(clk) then |
|
ncts_buf(0) <= ncts; |
ncts_buf(2 downto 1) <= ncts_buf(1 downto 0); |
|
case uart_tx_state is |
|
when s0 => |
i := 0; |
if (tf_empty='0' and ncts_buf(2)='0') then |
uart_tx_state <= s1; |
tsr <= tf_dout & '0' & '1'; |
tf_rd <= '1'; |
end if; |
|
when s1 => |
tf_rd <= '0'; |
if (tx_clk='1') then |
tsr(9) <= '1'; |
tsr(8 downto 0) <= tsr(9 downto 1); |
i := i+1; |
if (i=11) then -- two stop bits |
uart_tx_state <= s0; |
end if; |
end if; |
|
end case; |
end if; |
|
end process; |
|
txd <= tsr(0); |
tdre <= not tf_full; |
|
|
-- |
-- receive fifo |
-- |
cmp_rf: fifo generic map (8, rxf_depth, rxf_thres) |
port map (clk, reset, rsr(8 downto 1), ua_dout, ua_rd, rf_wr, rf_empty, rf_full, rf_half); |
|
rdrf <= not rf_empty; |
nrts <= rf_half; -- glitches even on empty fifo! |
|
-- |
-- filter rxd |
-- |
with rx_buf select |
rx_d <= '0' when "000", |
'0' when "001", |
'0' when "010", |
'1' when "011", |
'0' when "100", |
'1' when "101", |
'1' when "110", |
'1' when "111", |
'X' when others; |
|
-- |
-- state machine for actual shift in |
-- |
process(clk, reset) |
|
variable i : integer range 0 to 10; |
|
begin |
|
if (reset='1') then |
uart_rx_state <= s0; |
rsr <= "0000000000"; |
rf_wr <= '0'; |
rx_clk_ena <= '0'; |
|
elsif rising_edge(clk) then |
|
case uart_rx_state is |
|
|
when s0 => |
i := 0; |
rf_wr <= '0'; |
if (rx_d='0') then |
rx_clk_ena <= '1'; |
uart_rx_state <= s1; |
else |
rx_clk_ena <= '0'; |
end if; |
|
when s1 => |
if (rx_clk='1') then |
rsr(9) <= rx_d; |
rsr(8 downto 0) <= rsr(9 downto 1); |
i := i+1; |
if (i=10) then |
uart_rx_state <= s2; |
end if; |
end if; |
|
when s2 => |
rx_clk_ena <= '0'; |
if rsr(0)='0' and rsr(9)='1' then |
if rf_full='0' then -- if full just drop it |
rf_wr <= '1'; |
end if; |
end if; |
uart_rx_state <= s0; |
|
end case; |
end if; |
|
end process; |
|
end rtl; |
/sc_wizardry.vhd
0,0 → 1,207
-- |
-- |
-- 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 |
-- |
-- wr, rd should be one cycle long => trde, rdrf goes 0 one cycle later |
-- |
-- Author: Martin Schoeberl martin@jopdesign.com |
-- |
-- |
-- resources on ACEX1K30-3 |
-- |
-- 100 LCs, max 90 MHz |
-- |
-- resetting rts with fifo_full-1 works with C program on pc |
-- but not with javax.comm: sends some more bytes after deassert |
-- of rts (16 byte blocks regardless of rts). |
-- Try to stop with half full fifo. |
-- |
-- todo: |
-- |
-- |
-- 2000-12-02 first working version |
-- 2002-01-06 changed tdr and rdr to fifos. |
-- 2002-05-15 changed clkdiv calculation |
-- 2002-11-01 don't wait if read fifo is full, just drop the byte |
-- 2002-11-03 use threshold in fifo to reset rts |
-- don't send if cts is '0' |
-- 2002-11-08 rx fifo to 20 characters and stop after 4 |
-- 2003-07-05 new IO standard, change cts/rts to neg logic |
-- 2003-09-19 sync ncts in! |
-- 2004-03-23 two stop bits |
-- 2005-11-30 change interface to SimpCon |
-- 2006-08-07 rxd input register with clk to avoid Quartus tsu violation |
-- 2006-08-13 use 3 FFs for the rxd input at clk |
-- |
|
|
library ieee; |
use ieee.std_logic_1164.all; |
use ieee.numeric_std.all; |
|
entity sc_wizardry is |
|
generic (addr_bits : integer := 4); |
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); |
|
-- Control Signals from JOP |
-- configuration_trigger : out std_logic_vector(7 downto 0); |
eRCP_trigger_reg : out std_logic; |
|
--Wizardry Interface |
ack_i : in std_logic; |
err_i : in std_logic; |
dat_i : in std_logic_Vector(31 downto 0); |
cyc_o : out std_logic; |
stb_o : out std_logic; |
we_o : out std_logic; |
dat_o : out std_logic_vector(31 downto 0); |
adr_o : out std_logic_vector(21 downto 0); |
lock_o : out std_logic; |
-- id_o : out std_logic_vector(4 downto 0); |
priority_o : out std_logic_vector(7 downto 0) |
); |
end sc_wizardry; |
|
architecture rtl of sc_wizardry is |
|
--type statetype is (reset_state,wait_for_rd_wr,check_address_value,store_address_state,store_data_state, |
-- write_to_ddr,read_from_ddr,send_sc_ack,wait_for_write_ack,wait_for_read_ack, |
-- prepare_sc_data); |
--signal currentstate, nextstate : statetype; |
signal store_address : std_logic; |
signal store_data : std_logic; |
signal store_config_data : std_logic; |
signal adr_o_reg : std_logic_Vector(21 downto 0); |
signal dat_o_reg : std_logic_vector(31 downto 0); |
--signal wr_data_reg : std_logic_vector(31 downto 0); |
signal address_reg : std_logic_vector(3 downto 0); |
--signal rd_data_reg : std_logic_vector(31 downto 0); |
signal set_sc_data : std_logic; |
--signal dat_i_reg : std_logic_vector(31 downto 0); |
|
component sc_wizardry_fsm is |
Port ( clock : in STD_LOGIC; |
reset : in STD_LOGIC; |
rd : in STD_LOGIC; |
wr : in STD_LOGIC; |
ack_i : in STD_LOGIC; |
err_i : in STD_LOGIC; |
address_reg : in STD_LOGIC_VECTOR (3 downto 0); |
adr_o_reg : in std_logic_vector(21 downto 0); |
dat_o_reg : in std_logic_Vector(31 downto 0); |
cyc_o : out STD_LOGIC; |
stb_o : out STD_LOGIC; |
we_o : out STD_LOGIC; |
adr_o : out STD_LOGIC_VECTOR (21 downto 0); |
dat_o : out STD_LOGIC_VECTOR (31 downto 0); |
store_address : out STD_LOGIC; |
store_data : out STD_LOGIC; |
store_config_data : out STD_LOGIC; |
rdy_cnt : out unsigned (1 downto 0); |
set_sc_data : out STD_LOGIC); |
end component; |
|
component sc_wizardry_processes is |
port( clk : in std_logic; |
reset : in std_logic; |
rd : in std_logic; |
wr : in std_logic; |
ack_i : in std_Logic; |
dat_i : in std_logic_Vector(31 downto 0); |
address : in std_logic_Vector(3 downto 0); |
wr_data : in std_Logic_Vector(31 downto 0); |
rd_data : out std_logic_Vector(31 downto 0); |
store_address : in std_Logic; |
store_data : in std_Logic; |
store_config_data : in STD_LOGIC; |
set_sc_data : in std_Logic; |
adr_o_reg : out std_logic_Vector(21 downto 0); |
dat_o_reg : out std_logic_Vector(31 downto 0); |
-- config_trigger_reg : out std_logic_vector(7 downto 0); |
eRCP_trigger_reg : out std_logic; |
address_reg : out std_logic_vector(3 downto 0)); |
end component; |
|
begin |
--id_o <= "00000"; |
priority_o <= "00000001"; |
lock_o <= '0'; |
-- rdy_cnt <= "00"; -- no wait states |
-- rd_data(31 downto 8) <= std_logic_vector(to_unsigned(0, 24)); |
sc_wiz_fsm: sc_wizardry_fsm |
Port map( clock => clk, |
reset => reset, |
rd => rd, |
wr => wr, |
ack_i => ack_i, |
err_i => err_i, |
address_reg => address_reg, |
adr_o_reg => adr_o_reg, |
dat_o_reg => dat_o_reg, |
cyc_o => cyc_o, |
stb_o => stb_o, |
we_o => we_o, |
adr_o => adr_o, |
dat_o => dat_o, |
store_address => store_address, |
store_data => store_data, |
store_config_data => store_config_data, --eRCP_trigger_reg, -- |
rdy_cnt => rdy_cnt, |
set_sc_data => set_sc_data); |
|
sc_wiz_proc: sc_wizardry_processes |
port map( clk => clk, |
reset => reset, |
rd => rd, |
wr => wr, |
ack_i => ack_i, |
dat_i => dat_i, |
address => address, |
wr_data => wr_data, |
rd_data => rd_data, |
store_address => store_address, |
store_data => store_data, |
store_config_data => store_config_data, |
set_sc_data => set_sc_data, |
adr_o_reg => adr_o_reg, |
dat_o_reg => dat_o_reg, |
-- config_trigger_reg => configuration_trigger, |
eRCP_trigger_reg => eRCP_trigger_reg, --open, -- |
address_reg => address_reg); |
|
--eRCP_trigger_reg <= store_config_data; |
|
end rtl; |
/scio_min.vhd
0,0 → 1,284
-- |
-- |
-- 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_min.vhd |
-- |
-- io devices for minimal configuration |
-- only counter, wd and serial line, alle io pins are tri statet |
-- |
-- |
-- io address mapping: |
-- |
-- IO Base is 0xffffff80 for 'fast' constants (bipush) |
-- |
-- 0x00 0-3 system clock counter, us counter, timer int, wd bit |
-- 0x10 0-1 uart (download) |
-- |
-- status word in uarts: |
-- 0 uart transmit data register empty |
-- 1 uart read data register full |
-- |
-- |
-- todo: |
-- |
-- |
-- 2003-07-09 created |
-- 2005-08-27 ignore ncts on uart |
-- 2005-11-30 changed to SimpCon |
-- 2007-03-17 use records |
-- |
-- |
|
|
Library IEEE; |
use IEEE.std_logic_1164.all; |
use ieee.numeric_std.all; |
|
use work.jop_types.all; |
use work.sc_pack.all; |
use work.jop_config.all; |
|
entity scio is |
generic (cpu_id : integer := 0; cpu_cnt : integer := 1); |
port ( |
clk : in std_logic; |
reset : in std_logic; |
|
-- |
-- SimpCon IO interface |
-- |
sc_io_out : in sc_out_type; |
sc_io_in : out sc_in_type; |
|
-- |
-- Interrupts from IO devices |
-- |
irq_in : out irq_bcf_type; |
irq_out : in irq_ack_type; |
exc_req : in exception_type; |
|
-- Control Signals from JOP |
-- configuration_trigger : out std_logic_vector(7 downto 0); |
eRCP_trigger_reg : out std_logic; |
|
-- CMP |
|
sync_out : in sync_out_type := NO_SYNC; |
sync_in : out sync_in_type; |
|
-- serial interface |
|
txd : out std_logic; |
rxd : in std_logic; |
ncts : in std_logic; |
nrts : out std_logic; |
|
-- watch dog |
|
wd : out std_logic; |
|
-- core i/o pins |
l : inout std_logic_vector(20 downto 1); |
r : inout std_logic_vector(20 downto 1); |
t : inout std_logic_vector(6 downto 1); |
b : inout std_logic_vector(10 downto 1); |
|
-- remove the comment for RAM access counting |
-- ram_cnt : in std_logic |
|
-- Wizardry Interface |
ack_i : in std_logic; |
err_i : in std_logic; |
dat_i : in std_logic_vector(31 downto 0); |
cyc_o : out std_logic; |
stb_o : out std_logic; |
we_o : out std_logic; |
dat_o : out std_logic_vector(31 downto 0); |
adr_o : out std_logic_Vector(21 downto 0); |
lock_o : out std_logic; |
-- id_o : out std_logic_Vector(4 downto 0); |
priority_o : out std_logic_Vector(7 downto 0) |
); |
end scio; |
|
|
architecture rtl of scio is |
|
constant SLAVE_CNT : integer := 3; |
-- SLAVE_CNT <= 2**DECODE_BITS |
-- take care of USB address 0x20! |
constant DECODE_BITS : integer := 2; |
-- number of bits that can be used inside the slave |
constant SLAVE_ADDR_BITS : integer := 4; |
|
type slave_bit is array(0 to SLAVE_CNT-1) of std_logic; |
signal sc_rd, sc_wr : slave_bit; |
|
type slave_dout is array(0 to SLAVE_CNT-1) of std_logic_vector(31 downto 0); |
signal sc_dout : slave_dout; |
|
type slave_rdy_cnt is array(0 to SLAVE_CNT-1) of unsigned(1 downto 0); |
signal sc_rdy_cnt : slave_rdy_cnt; |
|
signal sel, sel_reg : integer range 0 to 2**DECODE_BITS-1; |
|
-- remove the comment for RAM access counting |
-- signal ram_count : std_logic; |
|
begin |
|
-- |
-- unused and input pins tri state |
-- |
l <= (others => 'Z'); |
r <= (others => 'Z'); |
t <= (others => 'Z'); |
b <= (others => 'Z'); |
|
assert SLAVE_CNT <= 2**DECODE_BITS report "Wrong constant in scio"; |
|
sel <= to_integer(unsigned(sc_io_out.address(SLAVE_ADDR_BITS+DECODE_BITS-1 downto SLAVE_ADDR_BITS))); |
|
-- What happens when sel_reg > SLAVE_CNT-1?? |
sc_io_in.rd_data <= sc_dout(sel_reg); |
sc_io_in.rdy_cnt <= sc_rdy_cnt(sel_reg); |
|
-- default for unused USB device |
-- sc_dout(2) <= (others => '0'); |
-- sc_rdy_cnt(2) <= (others => '0'); |
|
-- |
-- Connect SLAVE_CNT simple test slaves |
-- |
gsl: for i in 0 to SLAVE_CNT-1 generate |
|
sc_rd(i) <= sc_io_out.rd when i=sel else '0'; |
sc_wr(i) <= sc_io_out.wr when i=sel else '0'; |
|
end generate; |
|
-- |
-- Register read and write mux selector |
-- |
process(clk, reset) |
begin |
if (reset='1') then |
sel_reg <= 0; |
elsif rising_edge(clk) then |
if sc_io_out.rd='1' or sc_io_out.wr='1' then |
sel_reg <= sel; |
end if; |
end if; |
end process; |
|
cmp_sys: entity work.sc_sys generic map ( |
addr_bits => SLAVE_ADDR_BITS, |
clk_freq => clk_freq, |
cpu_id => cpu_id, |
cpu_cnt => cpu_cnt |
) |
port map( |
clk => clk, |
reset => reset, |
|
address => sc_io_out.address(SLAVE_ADDR_BITS-1 downto 0), |
wr_data => sc_io_out.wr_data, |
rd => sc_rd(0), |
wr => sc_wr(0), |
rd_data => sc_dout(0), |
rdy_cnt => sc_rdy_cnt(0), |
|
irq_in => irq_in, |
irq_out => irq_out, |
exc_req => exc_req, |
|
sync_out => sync_out, |
sync_in => sync_in, |
|
wd => wd |
-- remove the comment for RAM access counting |
-- ram_count => ram_count |
); |
|
-- remove the comment for RAM access counting |
-- ram_count <= ram_cnt; |
|
cmp_ua: entity work.sc_uart generic map ( |
addr_bits => SLAVE_ADDR_BITS, |
clk_freq => clk_freq, |
baud_rate => 115200, |
txf_depth => 2, |
txf_thres => 1, |
rxf_depth => 2, |
rxf_thres => 1 |
) |
port map( |
clk => clk, |
reset => reset, |
|
address => sc_io_out.address(SLAVE_ADDR_BITS-1 downto 0), |
wr_data => sc_io_out.wr_data, |
rd => sc_rd(1), |
wr => sc_wr(1), |
rd_data => sc_dout(1), |
rdy_cnt => sc_rdy_cnt(1), |
|
txd => txd, |
rxd => rxd, |
ncts => '0', |
nrts => nrts |
); |
|
cmp_wiz: entity work.sc_wizardry |
generic map(addr_bits => SLAVE_ADDR_BITS) |
port MAP( |
clk => clk, |
reset => reset, |
|
-- SimpCon interface |
|
address => sc_io_out.address(SLAVE_ADDR_BITS-1 downto 0), |
wr_data => sc_io_out.wr_data, |
rd => sc_rd(2), |
wr => sc_wr(2), |
rd_data => sc_dout(2), |
rdy_cnt => sc_rdy_cnt(2), |
|
-- Control Signals from JOP |
-- configuration_trigger => configuration_trigger, |
eRCP_trigger_reg => eRCP_trigger_reg, |
|
--Wizardry Interface |
ack_i => ack_i, |
err_i => err_i, |
dat_i => dat_i, |
cyc_o => cyc_o, |
stb_o => stb_o, |
we_o => we_o, |
dat_o => dat_o, |
adr_o => adr_o, |
lock_o => lock_o, |
-- id_o => id_o, |
priority_o => priority_o |
); |
|
end rtl; |
/jopcpu.vhd
0,0 → 1,289
-- |
-- |
-- 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/>. |
-- |
|
|
-- |
-- jopcpu.vhd |
-- |
-- The JOP CPU |
-- |
-- 2007-03-16 creation |
-- 2007-04-13 Changed memory connection to records |
-- 2008-02-20 memory - I/O muxing after the memory controller (mem_sc) |
-- 2008-03-03 added scratchpad RAM |
-- 2008-03-04 correct MUX selection |
-- |
-- todo: clean up: substitute all signals by records |
|
|
library ieee; |
use ieee.std_logic_1164.all; |
use ieee.numeric_std.all; |
|
use work.jop_types.all; |
use work.sc_pack.all; |
|
|
entity jopcpu is |
|
generic ( |
jpc_width : integer; -- address bits of java bytecode pc = cache size |
block_bits : integer; -- 2*block_bits is number of cache blocks |
spm_width : integer := 0 -- size of scratchpad RAM (in number of address bits) |
); |
|
port ( |
clk : in std_logic; |
reset : in std_logic; |
|
-- |
-- SimpCon memory interface |
-- |
sc_mem_out : out sc_out_type; |
sc_mem_in : in sc_in_type; |
|
-- |
-- SimpCon IO interface |
-- |
sc_io_out : out sc_out_type; |
sc_io_in : in sc_in_type; |
|
-- |
-- Interrupts from sc_sys |
-- |
irq_in : in irq_bcf_type; |
irq_out : out irq_ack_type; |
exc_req : out exception_type |
); |
end jopcpu; |
|
architecture rtl of jopcpu is |
|
-- |
-- Signals |
-- |
|
signal stack_tos : std_logic_vector(31 downto 0); |
signal stack_nos : std_logic_vector(31 downto 0); |
signal rd, wr : std_logic; |
signal ext_addr : std_logic_vector(EXTA_WIDTH-1 downto 0); |
signal stack_din : std_logic_vector(31 downto 0); |
|
-- extension/mem interface |
|
signal mem_in : mem_in_type; |
signal mem_out : mem_out_type; |
|
signal sc_ctrl_mem_out : sc_out_type; |
signal sc_ctrl_mem_in : sc_in_type; |
|
signal sc_scratch_out : sc_out_type; |
signal sc_scratch_in : sc_in_type; |
|
signal next_mux_mem : std_logic_vector(1 downto 0); |
signal dly_mux_mem : std_logic_vector(1 downto 0); |
signal mux_mem : std_logic_vector(1 downto 0); |
signal is_pipelined : std_logic; |
|
signal mem_access : std_logic; |
signal scratch_access : std_logic; |
signal io_access : std_logic; |
|
signal bsy : std_logic; |
|
signal jbc_addr : std_logic_vector(jpc_width-1 downto 0); |
signal jbc_data : std_logic_vector(7 downto 0); |
|
-- SimpCon io interface |
|
signal sp_ov : std_logic; |
|
begin |
|
-- |
-- components of jop |
-- |
|
cmp_core: entity work.core |
generic map(jpc_width) |
port map (clk, reset, |
bsy, |
stack_din, ext_addr, |
rd, wr, |
jbc_addr, jbc_data, |
irq_in, irq_out, sp_ov, |
stack_tos, stack_nos |
); |
|
exc_req.spov <= sp_ov; |
|
cmp_ext: entity work.extension |
port map ( |
clk => clk, |
reset => reset, |
ain => stack_tos, |
bin => stack_nos, |
|
ext_addr => ext_addr, |
rd => rd, |
wr => wr, |
bsy => bsy, |
dout => stack_din, |
|
mem_in => mem_in, |
mem_out => mem_out |
); |
|
cmp_mem: entity work.mem_sc |
generic map ( |
jpc_width => jpc_width, |
block_bits => block_bits |
) |
port map ( |
clk => clk, |
reset => reset, |
ain => stack_tos, |
bin => stack_nos, |
|
np_exc => exc_req.np, |
ab_exc => exc_req.ab, |
|
mem_in => mem_in, |
mem_out => mem_out, |
|
jbc_addr => jbc_addr, |
jbc_data => jbc_data, |
|
sc_mem_out => sc_ctrl_mem_out, |
sc_mem_in => sc_ctrl_mem_in |
); |
|
|
-- |
-- Generate scratchpad memory when size is != 0. |
-- Results in warnings when the size is 0. |
-- |
sc1: if spm_width /= 0 generate |
cmp_scm: entity work.sdpram |
generic map ( |
width => 32, |
addr_width => spm_width |
) |
port map ( |
wrclk => clk, |
data => sc_scratch_out.wr_data, |
wraddress => sc_scratch_out.address(spm_width-1 downto 0), |
wren => sc_scratch_out.wr, |
rdclk => clk, |
rdaddress => sc_scratch_out.address(spm_width-1 downto 0), |
rden => sc_scratch_out.rd, |
dout => sc_scratch_in.rd_data |
); |
end generate; |
|
sc_scratch_in.rdy_cnt <= (others => '0'); |
|
-- |
-- Select for the read mux |
-- |
-- TODO: this mux selection works ONLY for two cycle pipelining! |
-- |
|
process(clk, reset) |
begin |
if (reset='1') then |
dly_mux_mem <= (others => '0'); |
next_mux_mem <= (others => '0'); |
is_pipelined <= '0'; |
elsif rising_edge(clk) then |
|
if sc_ctrl_mem_out.rd='1' or sc_ctrl_mem_out.wr='1' then |
-- highest address bits decides between IO, memory, and on-chip memory |
-- save the mux selection on read or write |
next_mux_mem <= sc_ctrl_mem_out.address(SC_ADDR_SIZE-1 downto SC_ADDR_SIZE-2); |
-- a read or write with rdy_cnt of 1 means pipelining |
if sc_ctrl_mem_in.rdy_cnt(1) = '0' then |
is_pipelined <= '1'; |
end if; |
end if; |
-- delayed mux selection for pipelined access |
if sc_ctrl_mem_in.rdy_cnt(1) = '0' then |
dly_mux_mem <= next_mux_mem; |
end if; |
-- pipelining is over |
if sc_ctrl_mem_in.rdy_cnt = "00" then |
is_pipelined <= '0'; |
end if; |
|
end if; |
end process; |
|
process(next_mux_mem, dly_mux_mem, sc_ctrl_mem_out, sc_ctrl_mem_in, sc_mem_in, sc_io_in, sc_scratch_in, is_pipelined, mux_mem) |
begin |
|
mem_access <= '0'; |
scratch_access <= '0'; |
io_access <= '0'; |
|
-- for one cycle peripherals we need to set the mux from next_mux_mem |
mux_mem <= next_mux_mem; |
-- for pipelining we need to delay the mux selection |
if is_pipelined='1' then |
mux_mem <= dly_mux_mem; |
end if; |
|
-- read MUX |
case mux_mem is |
when "10" => |
sc_ctrl_mem_in <= sc_scratch_in; |
when "11" => |
sc_ctrl_mem_in <= sc_io_in; |
when others => |
sc_ctrl_mem_in <= sc_mem_in; |
end case; |
|
-- select |
case sc_ctrl_mem_out.address(SC_ADDR_SIZE-1 downto SC_ADDR_SIZE-2) is |
when "10" => |
scratch_access <= '1'; |
when "11" => |
io_access <= '1'; |
when others => |
mem_access <= '1'; |
end case; |
|
end process; |
|
sc_mem_out.address <= sc_ctrl_mem_out.address; |
sc_mem_out.wr_data <= sc_ctrl_mem_out.wr_data; |
sc_mem_out.wr <= sc_ctrl_mem_out.wr and mem_access; |
sc_mem_out.rd <= sc_ctrl_mem_out.rd and mem_access; |
|
sc_scratch_out.address <= sc_ctrl_mem_out.address; |
sc_scratch_out.wr_data <= sc_ctrl_mem_out.wr_data; |
sc_scratch_out.wr <= sc_ctrl_mem_out.wr and scratch_access; |
sc_scratch_out.rd <= sc_ctrl_mem_out.rd and scratch_access; |
|
sc_io_out.address <= sc_ctrl_mem_out.address; |
sc_io_out.wr_data <= sc_ctrl_mem_out.wr_data; |
sc_io_out.wr <= sc_ctrl_mem_out.wr and io_access; |
sc_io_out.rd <= sc_ctrl_mem_out.rd and io_access; |
|
end rtl; |
/sc_sys.vhd
0,0 → 1,450
-- |
-- |
-- 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@jopdesign.com |
-- |
-- address map: |
-- |
-- 0 read clk counter, write irq ena |
-- 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 |
-- |
-- 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 |
-- 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; |
|
use work.jop_types.all; |
|
entity sc_sys is |
|
generic (addr_bits : integer; |
clk_freq : 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; |
|
-- 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_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 := NO_SYNC; |
sync_in : out sync_in_type; |
|
wd : out std_logic |
|
-- remove the comment for RAM access counting |
-- ram_count : in 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 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 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 <= "11" when (sync_out.halted='1' and lock_reqest='1') else "00"; |
|
-- |
-- 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(3 downto 0) is |
when "0000" => |
rd_data <= clock_cnt; |
when "0001" => |
rd_data <= us_cnt; |
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 "0101" => |
rd_data(0) <= lock_reqest; |
rd_data(31 downto 1) <= (others => '0'); |
when "0110" => |
rd_data <= cpu_identity; |
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 others => |
-- nothing |
end case; |
end if; |
end if; |
|
end process; |
|
-- |
-- compare timer value and us counter |
-- and generate single shot |
-- |
process(us_cnt, timer_cnt) begin |
timer_equ <= '0'; |
if us_cnt = timer_cnt then |
timer_equ <= '1'; |
end if; |
end process; |
|
process(clk, reset) 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 |
-- |
|
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 |
|
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_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 |
-- |
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 |
|
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'); |
exc_pend <= '0'; |
|
swreq <= (others => '0'); |
mask <= (others => '0'); |
clearall <= '0'; |
|
elsif rising_edge(clk) then |
|
exc_pend <= '0'; |
swreq <= (others => '0'); |
clearall <= '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; |
exc_pend <= '1'; |
end if; |
if exc_req.np='1' then |
exc_type(2 downto 0) <= EXC_NP; |
exc_pend <= '1'; |
end if; |
if exc_req.ab='1' then |
exc_type(2 downto 0) <= EXC_AB; |
exc_pend <= '1'; |
end if; |
|
if wr='1' then |
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 "0100" => |
exc_type <= wr_data(7 downto 0); |
exc_pend <= '1'; |
when "0101" => |
sync_in.lock_req <= wr_data(0); |
lock_reqest <= 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 others => |
end case; |
end if; |
|
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; |
/sc_pack.vhd
0,0 → 1,63
-- |
-- |
-- 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 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; |
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; |
|
end sc_pack; |
/cache.vhd
0,0 → 1,214
-- |
-- |
-- 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/>. |
-- |
|
|
-- |
-- cache.vhd |
-- |
-- Bytecode caching |
-- |
-- jpc_with (set in top-level) configures the size. |
-- Upper limit is 12 bits (4KB) due to the restriction in the |
-- .jop file format (see JOPWriter.java). Changing this breaks |
-- compatibility with other versions of JOP. |
-- |
-- 2005-01-11 first version |
-- 2005-05-03 configurable size (jpc_width) |
-- 2005-05-09 correction for ModelSim |
-- |
|
-- library std; |
-- use std.textio.all; |
|
|
Library IEEE; |
use IEEE.std_logic_1164.all; |
use ieee.numeric_std.all; |
|
use work.jop_types.all; |
|
-- 2**jpc_width is the caches size in bytes |
-- 2**block_bits is the number of blocks |
|
entity cache is |
generic (jpc_width : integer; block_bits : integer; tag_width : integer := 18); |
|
port ( |
|
clk, reset : in std_logic; |
|
bc_len : in std_logic_vector(METHOD_SIZE_BITS-1 downto 0); -- length of method in words |
bc_addr : in std_logic_vector(17 downto 0); -- memory address of bytecode |
|
find : in std_logic; -- start lookup |
|
-- start of method in bc cache |
-- in 32 bit words - we load only at word boundries |
bcstart : out std_logic_vector(jpc_width-3 downto 0); |
|
rdy : out std_logic; -- lookup finished |
in_cache : out std_logic -- method is in cache |
|
); |
end cache; |
|
architecture rtl of cache is |
|
-- |
-- signals for mem interface |
-- |
type state_type is ( |
idle, s1, s2 |
); |
signal state : state_type; |
|
constant blocks : integer := 2**block_bits; |
|
signal block_addr : std_logic_vector(block_bits-1 downto 0); |
-- tag_width can be used to reduce cachable area - saves a lot in the comperators |
signal use_addr : std_logic_vector(tag_width-1 downto 0); |
|
type tag_array is array (0 to blocks-1) of std_logic_vector(tag_width-1 downto 0); |
signal tag : tag_array; |
|
-- pointer to next block to be used on a miss |
signal nxt : unsigned(block_bits-1 downto 0); |
|
-- (length of the method)-1 in blocks, 0 is one block |
signal nr_of_blks : unsigned(block_bits-1 downto 0); |
|
signal clr_val : std_logic_vector(blocks-1 downto 0); |
|
begin |
|
bcstart <= block_addr & std_logic_vector(to_unsigned(0, jpc_width-2-block_bits)); |
use_addr <= bc_addr(tag_width-1 downto 0); |
|
nr_of_blks <= resize(unsigned(bc_len(METHOD_SIZE_BITS-1 downto jpc_width-2-block_bits)), block_bits); |
|
process(clk, reset, find) |
|
begin |
if (reset='1') then |
state <= idle; |
rdy <= '1'; |
in_cache <= '0'; |
block_addr <= (others => '0'); |
nxt <= (others => '0'); |
|
for i in 0 to blocks-1 loop |
tag(i) <= (others => '0'); |
end loop; |
|
elsif rising_edge(clk) then |
|
case state is |
|
when idle => |
state <= idle; |
rdy <= '1'; |
if find = '1' then |
rdy <= '0'; |
state <= s1; |
end if; |
|
-- check for a hit |
when s1 => |
|
in_cache <= '0'; |
state <= s2; |
block_addr <= std_logic_vector(nxt); |
|
-- Does this generate optimal logic? |
-- Only one if will be true. Therefore, there |
-- should be a place for optimization |
|
-- comment this out for no caching |
for i in 0 to blocks-1 loop |
if tag(i) = use_addr then |
block_addr <= std_logic_vector(to_unsigned(i, block_bits)); |
in_cache <= '1'; |
state <= idle; |
end if; |
end loop; |
-- |
-- remove the comment to force a single method |
-- block cache |
-- |
-- block_addr <= (others => '0'); |
-- in_cache <= '0'; |
-- state <= s2; |
|
-- correct tag memory on a miss |
when s2 => |
|
for i in 0 to blocks-1 loop |
-- these two statements are xor - optimization? |
if clr_val(i) = '1' then |
tag(i) <= (others => '0'); |
end if; |
if nxt = to_unsigned(i, block_bits) then |
tag(i) <= use_addr; |
end if; |
end loop; |
|
state <= idle; |
-- optimization to not advance the next pointer |
-- on short methods |
-- if unsigned(bc_len) > 14 then |
nxt <= nxt + nr_of_blks + 1; |
-- end if; |
|
|
end case; |
|
end if; |
end process; |
|
-- |
-- Determine which block entries have to be cleared in the tag registers. |
-- |
-- clr_val could b registered as we can calculate |
-- process(nxt, nr_of_blks) begin |
process(clk) |
|
variable val : integer; |
begin |
|
if rising_edge(clk) then |
|
for i in 0 to blocks-1 loop |
-- write(output, "cache..."); |
-- val := i; |
-- write(output, integer'image(val)); |
-- val := blocks; |
-- write(output, integer'image(val)); |
if i<=nr_of_blks then |
clr_val(to_integer(nxt+i)) <= '1'; |
else |
clr_val(to_integer(nxt+i)) <= '0'; |
end if; |
end loop; |
end if; |
|
end process; |
|
|
end rtl; |
/mem_sc.vhd
0,0 → 1,872
-- |
-- |
-- 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/>. |
-- |
|
|
-- |
-- mem_sc.vhd |
-- |
-- External memory interface with SimpCon. |
-- Translates between JOP/extension memory interface |
-- and SimpCon memory interface. |
-- Does the method cache load. |
-- |
-- |
-- todo: |
-- |
-- 2005-11-22 first version adapted from mem(_wb) |
-- 2006-06-15 removed unnecessary state in BC load |
-- len decrement in bc_rn and exit from bc_wr |
-- 2007-04-13 Changed memory connection to records |
-- 2007-04-14 xaload and xastore in hardware |
-- 2008-02-19 put/getfield in hardware |
-- 2008-04-30 copy step in hardware |
-- 2008-10-10 correct array access for fast (SPM) memory (+iald23 state) |
-- |
|
Library IEEE; |
use IEEE.std_logic_1164.all; |
use ieee.numeric_std.all; |
|
use work.jop_types.all; |
use work.sc_pack.all; |
|
entity mem_sc is |
generic (jpc_width : integer; block_bits : integer); |
|
port ( |
|
-- jop interface |
|
clk, reset : in std_logic; |
|
ain : in std_logic_vector(31 downto 0); -- TOS |
bin : in std_logic_vector(31 downto 0); -- NOS |
|
-- exceptions |
|
np_exc : out std_logic; |
ab_exc : out std_logic; |
|
-- extension connection |
mem_in : in mem_in_type; |
mem_out : out mem_out_type; |
|
-- jbc connections |
|
jbc_addr : in std_logic_vector(jpc_width-1 downto 0); |
jbc_data : out std_logic_vector(7 downto 0); |
|
-- SimpCon interface |
|
sc_mem_out : out sc_out_type; |
sc_mem_in : in sc_in_type |
); |
end mem_sc; |
|
architecture rtl of mem_sc is |
|
component cache is |
generic (jpc_width : integer; block_bits : integer); |
|
port ( |
|
clk, reset : in std_logic; |
|
bc_len : in std_logic_vector(METHOD_SIZE_BITS-1 downto 0); -- length of method in words |
bc_addr : in std_logic_vector(17 downto 0); -- memory address of bytecode |
|
find : in std_logic; -- start lookup |
|
bcstart : out std_logic_vector(jpc_width-3 downto 0); -- start of method in bc cache |
|
rdy : out std_logic; -- lookup finished |
in_cache : out std_logic -- method is in cache |
|
); |
end component; |
|
-- |
-- jbc component (use technology specific vhdl-file cyc_jbc,...) |
-- |
-- ajbc,xjbc are OLD! |
-- check if ajbc.vhd can still be used (multicycle write!) |
-- |
-- dual port ram |
-- wraddr and wrena registered |
-- rdaddr is registered |
-- indata registered |
-- outdata is unregistered |
-- |
|
component jbc is |
generic (jpc_width : integer); |
port ( |
clk : in std_logic; |
data : in std_logic_vector(31 downto 0); |
rd_addr : in std_logic_vector(jpc_width-1 downto 0); |
wr_addr : in std_logic_vector(jpc_width-3 downto 0); |
wr_en : in std_logic; |
q : out std_logic_vector(7 downto 0) |
); |
end component; |
|
|
-- |
-- signals for mem interface |
-- |
type state_type is ( |
idl, rd1, wr1, |
bc_cc, bc_r1, bc_w, bc_rn, bc_wr, bc_wl, |
iald0, iald1, iald2, iald23, iald3, iald4, |
iasrd, ialrb, |
iast0, iaswb, iasrb, iasst, |
gf0, gf1, gf2, gf3, |
pf0, pf3, |
cp0, cp1, cp2, cp3, cp4, cpstop, |
last, |
npexc, abexc, excw |
); |
signal state : state_type; |
signal next_state : state_type; |
|
-- length should be 'real' RAM size and not RAM + Flash + NAND |
-- should also be considered in the cacheable range |
|
-- addr_reg used to 'store' the address for wr, bc load, and array access |
signal addr_reg : unsigned(SC_ADDR_SIZE-1 downto 0); |
signal addr_next : unsigned(SC_ADDR_SIZE-1 downto 0); |
|
-- MUX for SimpCon address and write data |
signal ram_addr : std_logic_vector(SC_ADDR_SIZE-1 downto 0); |
signal ram_wr_data : std_logic_vector(31 downto 0); |
|
-- |
-- signals for access from the state machine |
-- |
signal state_bsy : std_logic; |
signal state_rd : std_logic; |
signal state_wr : std_logic; |
|
-- |
-- signals for object and array access |
-- |
signal index : std_logic_vector(SC_ADDR_SIZE-1 downto 0); -- array or field index |
signal value : std_logic_vector(31 downto 0); -- store value |
|
signal null_pointer : std_logic; |
signal bounds_error : std_logic; |
|
signal was_a_store : std_logic; |
|
-- |
-- values for bytecode read/cache |
-- |
-- len is in words, 10 bits range is 'hardcoded' in JOPWriter.java |
-- start is address in external memory (rest of the word) |
-- |
signal bc_len : unsigned(METHOD_SIZE_BITS-1 downto 0); -- length of method in words |
signal inc_addr_reg : std_logic; |
signal dec_len : std_logic; |
signal bc_wr_addr : unsigned(jpc_width-3 downto 0); -- address for jbc (in words!) |
signal bc_wr_data : std_logic_vector(31 downto 0); -- write data for jbc |
signal bc_wr_ena : std_logic; |
|
-- |
-- signals for cache connection |
-- |
signal cache_rdy : std_logic; |
signal cache_in_cache : std_logic; |
signal cache_bcstart : std_logic_vector(jpc_width-3 downto 0); |
|
-- |
-- signals for copying and address translation |
-- |
signal base_reg : unsigned(SC_ADDR_SIZE-1 downto 0); |
signal pos_reg : unsigned(SC_ADDR_SIZE-1 downto 0); |
signal offset_reg : unsigned(SC_ADDR_SIZE-1 downto 0); |
signal translate_bit : std_logic; |
signal cp_stopbit : std_logic; |
|
begin |
|
process(sc_mem_in, state_bsy, state) |
begin |
mem_out.bsy <= '0'; |
if sc_mem_in.rdy_cnt=3 then |
mem_out.bsy <= '1'; |
else |
if state/=ialrb and state/=last and state_bsy='1' then |
mem_out.bsy <= '1'; |
end if; |
end if; |
end process; |
|
mem_out.bcstart <= std_logic_vector(to_unsigned(0, 32-jpc_width)) & cache_bcstart & "00"; |
|
|
np_exc <= null_pointer; |
ab_exc <= bounds_error; |
|
-- change byte order for jbc memory (high byte first) |
bc_wr_data <= sc_mem_in.rd_data(7 downto 0) & |
sc_mem_in.rd_data(15 downto 8) & |
sc_mem_in.rd_data(23 downto 16) & |
sc_mem_in.rd_data(31 downto 24); |
|
|
cmp_cache: cache generic map (jpc_width, block_bits) port map( |
clk, reset, |
std_logic_vector(bc_len), std_logic_vector(addr_reg(17 downto 0)), |
mem_in.bc_rd, |
cache_bcstart, |
cache_rdy, cache_in_cache |
); |
|
|
cmp_jbc: jbc generic map (jpc_width) |
port map( |
clk => clk, |
data => bc_wr_data, |
wr_en => bc_wr_ena, |
wr_addr => std_logic_vector(bc_wr_addr), |
rd_addr => jbc_addr, |
q => jbc_data |
); |
|
-- |
-- SimpCon connections |
-- |
|
sc_mem_out.address <= ram_addr; |
sc_mem_out.wr_data <= ram_wr_data; |
sc_mem_out.rd <= mem_in.rd or state_rd; |
sc_mem_out.wr <= mem_in.wr or state_wr; |
mem_out.dout <= sc_mem_in.rd_data; |
|
|
-- |
-- Store the write address |
-- TODO: wouldn't it be easier to use A and B |
-- for data and address with a single write |
-- command? |
-- - see jvm.asm... |
-- |
-- and array access stores |
-- |
process(clk, reset) |
begin |
if reset='1' then |
addr_reg <= (others => '0'); |
index <= (others => '0'); |
value <= (others => '0'); |
was_a_store <= '0'; |
bc_len <= (others => '0'); |
|
base_reg <= (others => '0'); |
pos_reg <= (others => '0'); |
offset_reg <= (others => '0'); |
|
elsif rising_edge(clk) then |
if mem_in.bc_rd='1' then |
bc_len <= unsigned(ain(METHOD_SIZE_BITS-1 downto 0)); |
else |
if dec_len='1' then |
bc_len <= bc_len-1; |
end if; |
end if; |
|
-- save array address and index |
if mem_in.iaload='1' or mem_in.getfield='1' then |
index <= ain(SC_ADDR_SIZE-1 downto 0); -- store array index |
end if; |
-- first step of three-operand operations |
if mem_in.iastore='1' or mem_in.putfield='1' then |
value <= ain; |
end if; |
-- get reference and index for putfield and array stores |
if state=pf0 or state=iast0 then |
index <= ain(SC_ADDR_SIZE-1 downto 0); -- store array index |
end if; |
|
-- get source and index for copying |
if mem_in.copy='1' then |
base_reg <= unsigned(bin(SC_ADDR_SIZE-1 downto 0)); |
pos_reg <= unsigned(ain(SC_ADDR_SIZE-1 downto 0)) + unsigned(bin(SC_ADDR_SIZE-1 downto 0)); |
cp_stopbit <= ain(31); |
end if; |
-- get destination for copying |
if state=cp0 then |
offset_reg <= unsigned(bin(SC_ADDR_SIZE-1 downto 0)) - base_reg; |
end if; |
|
-- address and data tweaking for copying |
if state=cp3 then |
pos_reg <= pos_reg+1; |
value <= sc_mem_in.rd_data; |
end if; |
if state=cpstop then |
pos_reg <= base_reg; |
end if; |
|
-- precompute address translation |
if addr_next >= base_reg and addr_next < pos_reg then |
translate_bit <= '1'; |
else |
translate_bit <= '0'; |
end if; |
addr_reg <= addr_next; |
|
-- set flag for state sharing |
if mem_in.iaload='1' or mem_in.getfield='1' then |
was_a_store <= '0'; |
elsif mem_in.iastore='1' or mem_in.putfield='1' then |
was_a_store <= '1'; |
end if; |
end if; |
end process; |
|
|
-- |
-- RAM address MUX (combinational) |
-- |
process(ain, addr_reg, offset_reg, mem_in, base_reg, pos_reg, translate_bit) |
begin |
if mem_in.rd='1' then |
if unsigned(ain(SC_ADDR_SIZE-1 downto 0)) >= base_reg and unsigned(ain(SC_ADDR_SIZE-1 downto 0)) < pos_reg then |
ram_addr <= std_logic_vector(unsigned(ain(SC_ADDR_SIZE-1 downto 0)) + offset_reg); |
else |
ram_addr <= ain(SC_ADDR_SIZE-1 downto 0); |
end if; |
else |
-- default is the registered address for wr, bc load |
if translate_bit='1' then |
ram_addr <= std_logic_vector(addr_reg(SC_ADDR_SIZE-1 downto 0) + offset_reg); |
else |
ram_addr <= std_logic_vector(addr_reg(SC_ADDR_SIZE-1 downto 0)); |
end if; |
end if; |
end process; |
|
-- |
-- prepare RAM address registering |
-- |
process(addr_reg, sc_mem_in, mem_in, ain, bin, state, inc_addr_reg, index, pos_reg, offset_reg) |
begin |
|
-- default values |
addr_next <= addr_reg; |
if inc_addr_reg='1' then |
addr_next <= addr_reg+1; |
end if; |
|
-- computations that depend on mem_in |
if mem_in.addr_wr='1' then |
addr_next <= unsigned(ain(SC_ADDR_SIZE-1 downto 0)); |
end if; |
|
if mem_in.bc_rd='1' then |
addr_next(17 downto 0) <= unsigned(ain(27 downto 10)); |
-- addr_bits is 17 |
if SC_ADDR_SIZE>18 then |
addr_next(SC_ADDR_SIZE-1 downto 18) <= (others => '0'); |
end if; |
end if; |
|
if mem_in.iaload='1' or mem_in.getfield='1' then |
addr_next <= unsigned(bin(SC_ADDR_SIZE-1 downto 0)); |
end if; |
|
-- computations that depend on the state |
if state=pf0 or state=iast0 then |
addr_next <= unsigned(bin(SC_ADDR_SIZE-1 downto 0)); |
end if; |
|
-- get/putfield could be optimized for faster memory (e.g. SPM) |
if state=iald3 or state=iald23 or state=gf2 then |
addr_next <= unsigned(sc_mem_in.rd_data(SC_ADDR_SIZE-1 downto 0))+unsigned(index); |
end if; |
|
if state=cp0 then |
addr_next <= pos_reg; |
end if; |
|
if state=cp3 then |
addr_next <= pos_reg + offset_reg; |
end if; |
|
end process; |
|
|
-- |
-- RAM write data MUX (combinational) |
-- |
process(ain, addr_reg, mem_in, value) |
begin |
if mem_in.wr='1' then |
ram_wr_data <= ain; |
else |
-- default is the registered value |
ram_wr_data <= value; |
end if; |
end process; |
|
|
-- |
-- next state logic |
-- |
process(state, mem_in, sc_mem_in, |
cache_rdy, cache_in_cache, bc_len, value, index, |
addr_reg, cp_stopbit, was_a_store) |
begin |
|
next_state <= state; |
|
case state is |
|
when idl => |
if mem_in.rd='1' then |
next_state <= rd1; |
elsif mem_in.wr='1' then |
next_state <= wr1; |
elsif mem_in.bc_rd='1' then |
next_state <= bc_cc; |
elsif mem_in.iaload='1' then |
next_state <= iald0; |
elsif mem_in.getfield='1' then |
next_state <= gf0; |
elsif mem_in.putfield='1' then |
next_state <= pf0; |
elsif mem_in.copy='1' then |
next_state <= cp0; |
elsif mem_in.iastore='1' then |
next_state <= iast0; |
end if; |
|
-- after a read the idl state is the result cycle |
-- where the data is available |
when rd1 => |
-- either 1 or 0 |
if sc_mem_in.rdy_cnt(1)='0' then |
next_state <= idl; |
end if; |
|
-- We could avoid the idl state after wr1 to |
-- get back to back wr/wr or wr/rd. |
-- However, it is not used in JOP (at the moment). |
when wr1 => |
-- either 1 or 0 |
if sc_mem_in.rdy_cnt(1)='0' then |
next_state <= idl; |
end if; |
|
-- |
-- bytecode read |
-- |
-- cache lookup |
when bc_cc => |
if cache_rdy = '1' then |
if cache_in_cache = '1' then |
next_state <= idl; |
else |
next_state <= bc_r1; |
end if; |
end if; |
|
-- not in cache |
-- start first read |
when bc_r1 => |
next_state <= bc_w; |
-- even for a two cycle memory we have to go to |
-- wait for the first time as rdy_cnt is 0 in |
-- this state. Becomes valid in the next cycle |
|
-- wait |
when bc_w => |
-- this works with pipeline level 1 |
-- if sc_mem_in.rdy_cnt(1)='0' then |
-- we need a pipeline level of 2 in |
-- the memory interface for this to work! |
if sc_mem_in.rdy_cnt/=3 then |
next_state <= bc_rn; |
end if; |
|
-- start read 2 to n |
when bc_rn => |
next_state <= bc_wr; |
|
when bc_wr => |
if bc_len=to_unsigned(0, jpc_width-3) then |
next_state <= bc_wl; |
else |
-- w. pipeline level 2 |
if sc_mem_in.rdy_cnt/=3 then |
next_state <= bc_rn; |
else |
next_state <= bc_w; |
end if; |
end if; |
|
-- wait for the last ack |
when bc_wl => |
if sc_mem_in.rdy_cnt(1)='0' then |
next_state <= idl; |
end if; |
|
-- |
-- array access |
-- |
when iast0 => |
-- just one cycle wait to store the value |
next_state <= iald0; |
|
-- |
-- iald0 to iald3 are shared with iastore |
-- |
when iald0 => |
if addr_reg=0 then |
next_state <= npexc; |
elsif index(SC_ADDR_SIZE-1)='1' then |
next_state <= abexc; |
else |
next_state <= iald1; |
end if; |
|
when iald1 => |
-- w. pipeline level 2 |
-- would waste one cycle in a single cycle memory (similar |
-- to bc load) - SimpCon rd comes from registered state_rd. |
if sc_mem_in.rdy_cnt<=1 then |
next_state <= iald23; |
elsif sc_mem_in.rdy_cnt/=3 then |
next_state <= iald2; |
end if; |
|
-- |
-- a quick hack for faster memory: we need to read |
-- it now! TODO: get better state names |
-- it's a mix of iald2 and iald3 |
-- |
when iald23 => |
next_state <= iald4; |
------ that's now load specific! |
-- we start loading before we know the upper bound exception! |
-- is there an issue with read peripherals???? |
if was_a_store='1' then |
next_state <= iaswb; |
-- w. pipeline level 2 |
elsif sc_mem_in.rdy_cnt/=3 then |
next_state <= iasrd; |
end if; |
|
when iald2 => |
next_state <= iald3; |
|
when iald3 => |
next_state <= iald4; |
------ that's now load specific! |
-- we start loading before we know the upper bound exception! |
-- is there an issue with read peripherals???? |
if was_a_store='1' then |
next_state <= iaswb; |
-- w. pipeline level 2 |
elsif sc_mem_in.rdy_cnt/=3 then |
next_state <= iasrd; |
end if; |
|
when iald4 => |
if sc_mem_in.rdy_cnt/=3 then |
next_state <= iasrd; |
end if; |
|
-- rdy_cnt is less than 3 we can move on |
when iasrd => |
next_state <= ialrb; |
|
when ialrb => |
-- can we optimize this when we increment index at some state? |
if unsigned(index) >= unsigned(sc_mem_in.rd_data(SC_ADDR_SIZE-1 downto 0)) then |
next_state <= abexc; |
-- either 1 or 0 |
elsif sc_mem_in.rdy_cnt(1)='0' then |
next_state <= idl; |
end if; |
|
when iaswb => |
if sc_mem_in.rdy_cnt(1)='0' then |
next_state <= iasrb; |
end if; |
|
when iasrb => |
next_state <= iasst; |
-- can we optimize this when we increment index at some state? |
if unsigned(index) >= unsigned(sc_mem_in.rd_data(SC_ADDR_SIZE-1 downto 0)) then |
next_state <= abexc; |
end if; |
|
when iasst => |
next_state <= last; |
|
when gf0 => |
if addr_reg=0 then |
next_state <= npexc; |
else |
next_state <= gf1; |
end if; |
when gf1 => |
-- either 1 or 0 |
if sc_mem_in.rdy_cnt(1)='0' then |
next_state <= gf2; |
end if; |
when gf2 => |
next_state <= gf3; |
if was_a_store='1' then |
next_state <= pf3; |
end if; |
when gf3 => |
next_state <= last; |
|
when pf0 => |
-- just one cycle wait to store the value |
next_state <= gf0; |
-- states pf1 and pf2 are shared with getfield |
when pf3 => |
next_state <= last; |
|
when cp0 => |
next_state <= cp1; |
if cp_stopbit = '1' then |
next_state <= cpstop; |
end if; |
when cp1 => |
next_state <= cp2; |
when cp2 => |
-- either 1 or 0 |
if sc_mem_in.rdy_cnt(1)='0' then |
next_state <= cp3; |
end if; |
when cp3 => |
next_state <= cp4; |
when cp4 => |
next_state <= last; |
when cpstop => |
next_state <= idl; |
|
when last => |
-- either 1 or 0 |
if sc_mem_in.rdy_cnt(1)='0' then |
next_state <= idl; |
end if; |
|
when npexc => |
next_state <= excw; |
|
when abexc => |
next_state <= excw; |
|
when excw => |
if sc_mem_in.rdy_cnt="00" then |
next_state <= idl; |
end if; |
|
end case; |
end process; |
|
-- |
-- state machine register |
-- output register |
-- |
process(clk, reset) |
|
begin |
if (reset='1') then |
state <= idl; |
bc_wr_ena <= '0'; |
inc_addr_reg <= '0'; |
dec_len <= '0'; |
state_rd <= '0'; |
state_bsy <= '0'; |
null_pointer <= '0'; |
bounds_error <= '0'; |
state_wr <= '0'; |
sc_mem_out.atomic <= '0'; |
|
elsif rising_edge(clk) then |
|
state <= next_state; |
|
bc_wr_ena <= '0'; |
inc_addr_reg <= '0'; |
dec_len <= '0'; |
state_rd <= '0'; |
null_pointer <= '0'; |
bounds_error <= '0'; |
state_wr <= '0'; |
sc_mem_out.atomic <= '0'; |
|
case next_state is |
|
when idl => |
state_bsy <= '0'; |
|
when rd1 => |
|
when wr1 => |
|
when bc_cc => |
state_bsy <= '1'; |
-- cache check |
|
when bc_r1 => |
-- setup data |
bc_wr_addr <= unsigned(cache_bcstart); |
-- first memory read |
inc_addr_reg <= '1'; |
state_rd <= '1'; |
sc_mem_out.atomic <= '1'; |
|
when bc_w => |
-- wait |
sc_mem_out.atomic <= '1'; |
|
when bc_rn => |
-- following memory reads |
inc_addr_reg <= '1'; |
dec_len <= '1'; |
state_rd <= '1'; |
sc_mem_out.atomic <= '1'; |
|
when bc_wr => |
-- BC write |
bc_wr_ena <= '1'; |
sc_mem_out.atomic <= '1'; |
|
if bc_len=to_unsigned(1, jpc_width-3) then |
sc_mem_out.atomic <= '0'; |
end if; |
|
when bc_wl => |
-- wait for last (unnecessary read) |
|
when iast0 => |
state_bsy <= '1'; |
|
when iald0 => |
state_rd <= '1'; |
state_bsy <= '1'; |
inc_addr_reg <= '1'; |
sc_mem_out.atomic <= '1'; |
|
when iald1 => |
sc_mem_out.atomic <= '1'; |
|
when iald2 => |
state_rd <= '1'; |
sc_mem_out.atomic <= '1'; |
|
when iald23 => |
state_rd <= '1'; |
sc_mem_out.atomic <= '1'; |
|
when iald3 => |
sc_mem_out.atomic <= '1'; |
|
when iald4 => |
sc_mem_out.atomic <= '1'; |
|
when iasrd => |
state_rd <= '1'; |
sc_mem_out.atomic <= '1'; |
|
when ialrb => |
sc_mem_out.atomic <= '1'; |
|
when iaswb => |
sc_mem_out.atomic <= '1'; |
|
when iasrb => |
sc_mem_out.atomic <= '1'; |
|
when iasst => |
state_wr <= '1'; |
sc_mem_out.atomic <= '1'; |
|
when gf0 => |
state_rd <= '1'; |
state_bsy <= '1'; |
sc_mem_out.atomic <= '1'; |
|
when gf1 => |
sc_mem_out.atomic <= '1'; |
|
when gf2 => |
sc_mem_out.atomic <= '1'; |
|
when gf3 => |
state_rd <= '1'; |
sc_mem_out.atomic <= '1'; |
|
when pf0 => |
state_bsy <= '1'; |
|
when pf3 => |
state_wr <= '1'; |
sc_mem_out.atomic <= '1'; |
|
when cp0 => |
sc_mem_out.atomic <= '1'; |
state_bsy <= '1'; |
|
when cp1 => |
state_rd <= '1'; |
sc_mem_out.atomic <= '1'; |
|
when cp2 => |
sc_mem_out.atomic <= '1'; |
|
when cp3 => |
sc_mem_out.atomic <= '1'; |
|
when cp4 => |
state_wr <= '1'; |
sc_mem_out.atomic <= '1'; |
|
when cpstop => |
|
when last => |
sc_mem_out.atomic <= '1'; |
|
when npexc => |
null_pointer <= '1'; |
|
when abexc => |
bounds_error <= '1'; |
|
when excw => |
|
end case; |
|
-- increment in state write |
if state=bc_wr then |
bc_wr_addr <= bc_wr_addr+1; -- next jbc address |
end if; |
end if; |
end process; |
|
end rtl; |
/stack.vhd
0,0 → 1,445
-- |
-- |
-- 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/>. |
-- |
|
|
-- |
-- stack.vhd |
-- |
-- Stack/Alu for JOP3 |
-- |
-- resources on ACEX1K30-3 |
-- |
-- |
-- 2001-06-30 first version (adapted from alu.vhd) |
-- 2001-07-18 components add, sub in own file for Xilinx |
-- 2001-10-28 ldjpc, stjpc |
-- 2001-10-31 init cp and vp with 0 |
-- 2001-12-04 cp removed |
-- 2001-12-06 sp is 0 after reset, must be set in sw |
-- 2001-12-07 removed imm. values |
-- 2002-03-24 barrel shifter |
-- 2003-02-12 added mux for 8 and 16 bit unsigned bytecode operand |
-- 2004-10-07 new alu selection with sel_sub, sel_amux and ena_a |
-- 2006-01-12 new ar for local memory addressing, sp and vp MSB fix at '1' |
-- 2007-08-31 change stack addressing without wrapping, generate sp_ov on max_stack-8 |
-- 2007-09-01 use ram_width from jop_config instead of parameter |
-- 2007-11-21 use 33 bit for the comparison (compare bug for diff > 2^31 corrected) |
-- |
|
|
library ieee; |
use ieee.std_logic_1164.all; |
use ieee.numeric_std.all; |
|
use work.jop_config.all; |
|
entity stack is |
|
generic ( |
width : integer := 32; -- one data word |
jpc_width : integer := 10 -- address bits of java byte code pc |
); |
port ( |
clk, reset : in std_logic; |
|
din : in std_logic_vector(width-1 downto 0); |
dir : in std_logic_vector(ram_width-1 downto 0); |
opd : in std_logic_vector(15 downto 0); -- index for vp load opd |
jpc : in std_logic_vector(jpc_width downto 0); -- jpc read |
|
sel_sub : in std_logic; -- 0..add, 1..sub |
sel_amux : in std_logic; -- 0..sum, 1..lmux |
ena_a : in std_logic; -- 1..store new value |
sel_bmux : in std_logic; -- 0..a, 1..mem |
sel_log : in std_logic_vector(1 downto 0); -- pop/st, and, or, xor |
sel_shf : in std_logic_vector(1 downto 0); -- sr, sl, sra, (sr) |
sel_lmux : in std_logic_vector(2 downto 0); -- log, shift, mem, din, reg |
sel_imux : in std_logic_vector(1 downto 0); -- java opds |
sel_rmux : in std_logic_vector(1 downto 0); -- sp, vp, jpc |
sel_smux : in std_logic_vector(1 downto 0); -- sp, a, sp-1, sp+1 |
|
sel_mmux : in std_logic; -- 0..a, 1..b |
sel_rda : in std_logic_vector(2 downto 0); -- |
sel_wra : in std_logic_vector(2 downto 0); -- |
|
wr_ena : in std_logic; |
|
ena_b : in std_logic; |
ena_vp : in std_logic; |
ena_ar : in std_logic; |
|
sp_ov : out std_logic; |
|
zf : out std_logic; |
nf : out std_logic; |
eq : out std_logic; |
lt : out std_logic; |
aout : out std_logic_vector(width-1 downto 0); |
bout : out std_logic_vector(width-1 downto 0) |
); |
end stack; |
|
architecture rtl of stack is |
|
component shift is |
generic (width : integer); |
port ( |
din : in std_logic_vector(width-1 downto 0); |
off : in std_logic_vector(4 downto 0); |
shtyp : in std_logic_vector(1 downto 0); |
dout : out std_logic_vector(width-1 downto 0) |
); |
end component shift; |
|
-- |
-- ram component (use technology specific vhdl-file (aram/xram)) |
-- |
-- registered and delayed wraddress, wren |
-- registered din |
-- registered rdaddress |
-- unregistered dout |
-- |
-- => read during write on same address |
-- |
component ram is |
generic (width : integer; addr_width : integer); |
port ( |
data : in std_logic_vector(width-1 downto 0); |
wraddress : in std_logic_vector(ram_width-1 downto 0); |
rdaddress : in std_logic_vector(ram_width-1 downto 0); |
wren : in std_logic; |
clock : in std_logic; |
reset : in std_logic; |
|
q : out std_logic_vector(width-1 downto 0) |
); |
end component; |
|
signal a, b : std_logic_vector(width-1 downto 0); |
signal ram_dout : std_logic_vector(width-1 downto 0); |
|
signal sp, spp, spm : std_logic_vector(ram_width-1 downto 0); |
signal vp0, vp1, vp2, vp3 |
: std_logic_vector(ram_width-1 downto 0); |
signal ar : std_logic_vector(ram_width-1 downto 0); |
|
signal sum : std_logic_vector(32 downto 0); |
signal sout : std_logic_vector(width-1 downto 0); |
signal log : std_logic_vector(width-1 downto 0); |
signal immval : std_logic_vector(width-1 downto 0); |
signal opddly : std_logic_vector(15 downto 0); |
|
signal amux : std_logic_vector(width-1 downto 0); |
signal lmux : std_logic_vector(width-1 downto 0); |
signal imux : std_logic_vector(width-1 downto 0); |
signal mmux : std_logic_vector(width-1 downto 0); |
|
signal rmux : std_logic_vector(jpc_width downto 0); |
signal smux : std_logic_vector(ram_width-1 downto 0); |
signal vpadd : std_logic_vector(ram_width-1 downto 0); |
signal wraddr : std_logic_vector(ram_width-1 downto 0); |
signal rdaddr : std_logic_vector(ram_width-1 downto 0); |
signal ci : std_logic_vector(width-1 downto 0); |
begin |
|
cmp_shf: shift generic map (width) port map (b, a(4 downto 0), sel_shf, sout); |
|
cmp_ram: ram generic map(width, ram_width) |
port map(mmux, wraddr, rdaddr, wr_ena, clk, reset, ram_dout); |
|
|
-- a version that 'could' be better in Spartan |
--process(a, b, sel_sub) |
--begin |
-- |
-- if sel_sub='0' then |
-- temp <= a; |
-- ci <= X"00000000"; |
-- else |
-- temp <= not a; |
-- ci <= X"00000001"; |
-- end if; |
-- sum <= std_logic_vector(signed(b) + signed(temp)+ signed(ci)); |
-- |
--end process; |
|
|
-- this add/sub, the sum/lmux mux and the enable should fit into |
-- a single LE. |
-- But it doesn't! A synthesizer problem in Quartus. |
-- |
process(a, b, sel_sub) |
begin |
|
-- subtract with 33 bits to get the correct carry |
if sel_sub='1' then |
sum <= std_logic_vector(signed(b(31) & b) - signed(a(31) & a)); |
else |
sum <= std_logic_vector(signed(b(31) & b) + signed(a(31) & a)); |
end if; |
|
end process; |
|
lt <= sum(32); -- default is subtract |
|
-- shift version from Flavius? |
|
-- |
-- mux for stack register, alu |
-- |
process(ram_dout, opddly, immval, sout, din, lmux, rmux, sp, vp0, jpc, sum, log, a, b, |
sel_log, sel_shf, sel_rmux, sel_lmux, sel_imux, sel_mmux, sel_amux) |
|
begin |
|
case sel_log is |
when "00" => |
log <= b; |
when "01" => |
log <= a and b; |
when "10" => |
log <= a or b; |
when "11" => |
log <= a xor b; |
when others => |
null; |
end case; |
|
case sel_rmux is |
when "00" => |
-- rmux <= "00" & sp; |
rmux <= std_logic_vector(to_signed(to_integer(unsigned(sp)), jpc_width+1)); |
when "01" => |
-- rmux <= "00" & vp0; |
rmux <= std_logic_vector(to_signed(to_integer(unsigned(vp0)), jpc_width+1)); |
when others => |
rmux <= jpc; |
end case; |
|
-- |
-- this is worse than the shift component |
-- |
-- case sel_shf is |
-- when "00" => |
-- sout <= std_logic_vector(shift_right(unsigned(b),to_integer(unsigned(a(4 downto 0))))); |
-- when "01" => |
-- sout <= std_logic_vector(shift_left(signed(b),to_integer(unsigned(a(4 downto 0))))); |
-- when "10" => |
-- sout <= std_logic_vector(shift_right(signed(b),to_integer(unsigned(a(4 downto 0))))); |
-- when "11" => |
-- sout <= std_logic_vector(shift_right(unsigned(b),to_integer(unsigned(a(4 downto 0))))); |
-- when others => |
-- null; |
-- end case; |
|
case sel_lmux(2 downto 0) is |
when "000" => |
lmux <= log; |
when "001" => |
lmux <= sout; |
when "010" => |
lmux <= ram_dout; |
when "011" => |
lmux <= immval; |
when "100" => |
lmux <= din; |
when others => |
lmux <= std_logic_vector(to_signed(to_integer(unsigned(rmux)), width)); |
end case; |
|
case sel_imux is |
when "00" => |
imux <= "000000000000000000000000" & opddly(7 downto 0); |
when "01" => |
imux <= std_logic_vector(to_signed(to_integer(signed(opddly(7 downto 0))), width)); |
when "10" => |
imux <= "0000000000000000" & opddly; |
when others => |
imux <= std_logic_vector(to_signed(to_integer(signed(opddly)), width)); |
end case; |
|
if sel_mmux='0' then |
mmux <= a; |
else |
mmux <= b; |
end if; |
|
if sel_amux='0' then |
amux <= sum(31 downto 0); |
else |
amux <= lmux; |
end if; |
|
-- if (a = (a'range => '0')) then -- Xilinx ISE has problems |
if (a=std_logic_vector(to_unsigned(0, width))) then |
zf <= '1'; |
else |
zf <= '0'; |
end if; |
nf <= a(width-1); |
if (a=b) then |
eq <= '1'; |
else |
eq <= '0'; |
end if; |
|
end process; |
|
process(clk, reset) begin |
|
if (reset='1') then |
a <= (others => '0'); |
b <= (others => '0'); |
elsif rising_edge(clk) then |
|
if ena_a='1' then |
a <= amux; |
end if; |
|
if ena_b = '1' then |
if sel_bmux = '0' then |
b <= a; |
else |
b <= ram_dout; |
end if; |
end if; |
|
end if; |
end process; |
|
aout <= a; |
bout <= b; |
|
-- |
-- stack pointer and vp register |
-- |
process(a, sp, spm, spp, sel_smux) |
|
begin |
|
case sel_smux is |
when "00" => |
smux <= sp; |
when "01" => |
smux <= spm; |
when "10" => |
smux <= spp; |
when "11" => |
smux <= a(ram_width-1 downto 0); |
when others => |
null; |
end case; |
|
end process; |
|
|
-- |
-- address mux for ram |
-- |
process(sp, spp, vp0, vp1, vp2, vp3, vpadd, ar, dir, sel_rda, sel_wra) |
|
begin |
|
|
case sel_rda is |
when "000" => |
rdaddr <= vp0; |
when "001" => |
rdaddr <= vp1; |
when "010" => |
rdaddr <= vp2; |
when "011" => |
rdaddr <= vp3; |
when "100" => |
rdaddr <= vpadd; |
when "101" => |
rdaddr <= ar; |
when "110" => |
rdaddr <= sp; |
when others => |
rdaddr <= dir; |
end case; |
|
case sel_wra is |
when "000" => |
wraddr <= vp0; |
when "001" => |
wraddr <= vp1; |
when "010" => |
wraddr <= vp2; |
when "011" => |
wraddr <= vp3; |
when "100" => |
wraddr <= vpadd; |
when "101" => |
wraddr <= ar; |
when "110" => |
wraddr <= spp; |
when others => |
wraddr <= dir; |
end case; |
|
end process; |
|
process(clk, reset) |
|
begin |
if (reset='1') then |
-- a reasonable start value for the stack addressing |
-- will be overwritten by the first microcode instructions |
sp <= std_logic_vector(to_unsigned(128, ram_width)); |
spp <= std_logic_vector(to_unsigned(129, ram_width)); |
spm <= std_logic_vector(to_unsigned(127, ram_width)); |
sp_ov <= '0'; |
vp0 <= std_logic_vector(to_unsigned(0, ram_width)); |
vp1 <= std_logic_vector(to_unsigned(0, ram_width)); |
vp2 <= std_logic_vector(to_unsigned(0, ram_width)); |
vp3 <= std_logic_vector(to_unsigned(0, ram_width)); |
ar <= (others => '0'); |
vpadd <= std_logic_vector(to_unsigned(0, ram_width)); |
immval <= std_logic_vector(to_unsigned(0, width)); |
opddly <= std_logic_vector(to_unsigned(0, 16)); |
elsif rising_edge(clk) then |
spp <= std_logic_vector(unsigned(smux) + 1); |
spm <= std_logic_vector(unsigned(smux) - 1); |
sp <= smux; |
-- Value depends on code in JVMHelp.exception() and how much |
-- usefull information can be printed out |
-- -8 was ok with just a plain print... |
-- -10 (or -12) should be ok for a stack trace? |
if sp=std_logic_vector(to_unsigned(2**ram_width-1-16, ram_width)) then |
sp_ov <= '1'; |
end if; |
if (ena_vp = '1') then |
vp0 <= a(ram_width-1 downto 0); |
vp1 <= std_logic_vector(unsigned(a(ram_width-1 downto 0)) + 1); |
vp2 <= std_logic_vector(unsigned(a(ram_width-1 downto 0)) + 2); |
vp3 <= std_logic_vector(unsigned(a(ram_width-1 downto 0)) + 3); |
end if; |
if ena_ar = '1' then |
ar <= a(ram_width-1 downto 0); |
end if; |
vpadd <= std_logic_vector(unsigned(vp0(ram_width-1 downto 0)) + unsigned(opd(6 downto 0))); |
opddly <= opd; |
immval <= imux; |
end if; |
end process; |
|
end rtl; |
/sc_wizardry_fsm.vhd
0,0 → 1,271
+ store_address <= '0';
+ store_data <= '0';
+ store_config_data <= '0';
+ rdy_cnt <= "11";
+ set_sc_data <= '0';
+
+ when read_from_ddr =>
+ nextstate <= wait_for_read_ack;
+ cyc_o <= '1';
+ stb_o <= '1';
+ we_o <= '0';
+ adr_o <= adr_o_reg;
+ dat_o <= (others => '0');
+ store_address <= '0';
+ store_data <= '0';
+ store_config_data <= '0';
+ rdy_cnt <= "11";
+ set_sc_data <= '0';
+
+ when wait_for_read_ack =>
+ if ack_i = '1' then
+ nextstate <= send_sc_ack;
+ else
+ nextstate <= wait_for_read_ack;
+ end if;
+ cyc_o <= '1';
+ stb_o <= '1';
+ we_o <= '0';
+ adr_o <= adr_o_reg;
+ dat_o <= (others => '0');
+ store_address <= '0';
+ store_data <= '0';
+ store_config_data <= '0';
+ rdy_cnt <= "11";
+ set_sc_data <= '0';
+
+ when send_sc_ack =>
+ nextstate <= wait_for_rd_wr;
+ cyc_o <= '0';
+ stb_o <= '0';
+ we_o <= '0';
+ adr_o <= (others => '0');
+ dat_o <= (others => '0');
+ store_address <= '0';
+ store_data <= '0';
+ store_config_data <= '0';
+ rdy_cnt <= "00";
+ set_sc_data <= '0';
+
+ when prepare_sc_data =>
+ nextstate <= send_sc_ack;
+ cyc_o <= '0';
+ stb_o <= '0';
+ we_o <= '0';
+ adr_o <= (others => '0');
+ dat_o <= (others => '0');
+ store_address <= '0';
+ store_data <= '0';
+ store_config_data <= '0';
+ rdy_cnt <= "11";
+ set_sc_data <= '1';
+
+ when others =>
+ nextstate <= reset_state;
+ cyc_o <= '0';
+ stb_o <= '0';
+ we_o <= '0';
+ adr_o <= (others => '0');
+ dat_o <= (others => '0');
+ store_address <= '0';
+ store_data <= '0';
+ store_config_data <= '0';
+ rdy_cnt <= "11";
+ set_sc_data <= '0';
+ end case;
+end process;
+
+process(clock,reset)
+begin
+ if reset = '1' then
+ currentstate <= reset_state;
+ elsif rising_Edge(clock) then
+ currentstate <= nextstate;
+ end if;
+end process;
+
+end Behavioral;
+
---------------------------------------------------------------------------------- |
-- Company: |
-- Engineer: |
-- |
-- Create Date: 10:02:03 01/30/2009 |
-- Design Name: |
-- Module Name: sc_wizardry_fsm - Behavioral |
-- Project Name: |
-- Target Devices: |
-- Tool versions: |
-- Description: |
-- |
-- Dependencies: |
-- |
-- Revision: |
-- Revision 0.01 - File Created |
-- Additional Comments: |
-- |
---------------------------------------------------------------------------------- |
library IEEE; |
use IEEE.STD_LOGIC_1164.ALL; |
--use IEEE.STD_LOGIC_ARITH.ALL; |
--use IEEE.STD_LOGIC_UNSIGNED.ALL; |
use ieee.numeric_std.all; |
---- Uncomment the following library declaration if instantiating |
---- any Xilinx primitives in this code. |
--library UNISIM; |
--use UNISIM.VComponents.all; |
|
entity sc_wizardry_fsm is |
Port ( clock : in STD_LOGIC; |
reset : in STD_LOGIC; |
rd : in STD_LOGIC; |
wr : in STD_LOGIC; |
ack_i : in STD_LOGIC; |
err_i : in STD_LOGIC; |
address_reg : in STD_LOGIC_VECTOR (3 downto 0); |
adr_o_reg : in std_logic_vector(21 downto 0); |
dat_o_reg : in std_logic_Vector(31 downto 0); |
cyc_o : out STD_LOGIC; |
stb_o : out STD_LOGIC; |
we_o : out STD_LOGIC; |
adr_o : out STD_LOGIC_VECTOR (21 downto 0); |
dat_o : out STD_LOGIC_VECTOR (31 downto 0); |
store_address : out STD_LOGIC; |
store_data : out STD_LOGIC; |
store_config_data : out std_logic; |
rdy_cnt : out unsigned (1 downto 0); |
set_sc_data : out STD_LOGIC); |
end sc_wizardry_fsm; |
|
architecture Behavioral of sc_wizardry_fsm is |
|
type statetype is (reset_state,wait_for_rd_wr,check_address_value,store_address_state,store_data_state, |
write_to_ddr,read_from_ddr,send_sc_ack,wait_for_write_ack,wait_for_read_ack, |
prepare_sc_data,store_config_trigger_data); |
signal currentstate, nextstate : statetype; |
|
begin |
|
process(currentstate,rd,wr,ack_i,address_reg,adr_o_reg,dat_o_reg) |
begin |
case currentstate is |
when reset_state => |
nextstate <= wait_for_rd_wr; |
cyc_o <= '0'; |
stb_o <= '0'; |
we_o <= '0'; |
adr_o <= (others => '0'); |
dat_o <= (others => '0'); |
store_address <= '0'; |
store_data <= '0'; |
store_config_data <= '0'; |
rdy_cnt <= "00"; |
set_sc_data <= '0'; |
|
when wait_for_rd_wr => |
if wr = '1' then |
nextstate <= check_address_value; |
elsif rd = '1' then |
nextstate <= prepare_sc_data; |
else |
nextstate <= wait_for_rd_wr; |
end if; |
cyc_o <= '0'; |
stb_o <= '0'; |
we_o <= '0'; |
adr_o <= (others => '0'); |
dat_o <= (others => '0'); |
store_address <= '0'; |
store_data <= '0'; |
store_config_data <= '0'; |
rdy_cnt <= "00"; |
set_sc_data <= '0'; |
|
when check_address_value => |
if address_reg = "0000" then |
nextstate <= store_address_state; |
elsif address_reg = "0001" then |
nextstate <= store_data_state; |
elsif address_reg = "0010" then |
nextstate <= write_to_ddr; |
elsif address_reg = "0011" then |
nextstate <= read_from_ddr; |
elsif address_reg = "0100" then |
nextstate <= store_config_trigger_data; |
else |
nextstate <= send_sc_ack; --may need to send a sc ack (rdy_cnt); |
end if; |
cyc_o <= '0'; |
stb_o <= '0'; |
we_o <= '0'; |
adr_o <= (others => '0'); |
dat_o <= (others => '0'); |
store_address <= '0'; |
store_data <= '0'; |
store_config_data <= '0'; |
rdy_cnt <= "11"; |
set_sc_data <= '0'; |
|
when store_address_state => |
nextstate <= send_sc_ack; |
cyc_o <= '0'; |
stb_o <= '0'; |
we_o <= '0'; |
adr_o <= (others => '0'); |
dat_o <= (others => '0'); |
store_address <= '1'; |
store_data <= '0'; |
store_config_data <= '0'; |
rdy_cnt <= "11"; |
set_sc_data <= '0'; |
|
when store_data_state => |
nextstate <= send_sc_ack; |
cyc_o <= '0'; |
stb_o <= '0'; |
we_o <= '0'; |
adr_o <= (others => '0'); |
dat_o <= (others => '0'); |
store_address <= '0'; |
store_data <= '1'; |
store_config_data <= '0'; |
rdy_cnt <= "11"; |
set_sc_data <= '0'; |
|
when store_config_trigger_data => |
nextstate <= send_sc_ack; |
cyc_o <= '0'; |
stb_o <= '0'; |
we_o <= '0'; |
adr_o <= (others => '0'); |
dat_o <= (others => '0'); |
store_address <= '0'; |
store_data <= '0'; |
store_config_data <= '1'; |
rdy_cnt <= "11"; |
set_sc_data <= '0'; |
|
when write_to_ddr => |
nextstate <= wait_for_write_ack; |
cyc_o <= '1'; |
stb_o <= '1'; |
we_o <= '1'; |
adr_o <= adr_o_reg; |
dat_o <= dat_o_reg; |
store_address <= '0'; |
store_data <= '0'; |
store_config_data <= '0'; |
rdy_cnt <= "11"; |
set_sc_data <= '0'; |
|
when wait_for_write_ack => |
if ack_i = '1' then |
nextstate <= send_sc_ack; |
else |
nextstate <= wait_for_write_ack; |
end if; |
cyc_o <= '1'; |
stb_o <= '1'; |
we_o <= '1'; |
adr_o <= adr_o_reg; |
/jop_ml401.vhd
0,0 → 1,338
-- |
-- jop_ml401.vhd |
-- |
-- top level for ML401 Virtex-4 |
-- |
-- use iocore.vhd for all io-pins |
-- |
-- 2002-06-27: 2088 LCs, 23.6 MHz |
-- 2002-07-27: 2308 LCs, 23.1 MHz with some changes in jvm and baseio |
-- 2002-08-02: 2463 LCs |
-- 2002-08-08: 2431 LCs simpler sigdel |
-- |
-- 2002-03-28 creation |
-- 2002-06-27 isa bus for CS8900 |
-- 2002-07-27 io for baseio |
-- 2002-08-02 second uart (use first for download and debug) |
-- 2002-11-01 removed second uart |
-- 2002-12-01 split memio |
-- 2002-12-07 disable clkout |
-- 2003-02-21 adapt for new Cyclone board with EP1C6 |
-- 2003-07-08 invertion of cts, rts to uart |
-- 2004-09-11 new extension module |
-- 2004-10-01 version for Xilinx |
-- 2004-10-08 mul operands from a and b, single instruction |
-- 2005-06-09 added the bsy routing through extension |
-- 2005-08-15 sp_ov can be used to show a stoack overflow on the wd pin |
-- 2005-11-24 use mem_sc for the memory interface and xs3_jbc for the |
-- bc cache. Now a real block cache (+40% performance with KFL) |
-- 2007-03-15 adapt for ML401 Virtex-4 FPGA board. (S. Calloway) |
-- 2007-03-21 Use jopcpu and change component interface to records |
-- |
|
|
library ieee; |
use ieee.std_logic_1164.all; |
use ieee.numeric_std.all; |
|
use work.jop_types.all; |
use work.sc_pack.all; |
use work.jop_config.all; |
|
---- Uncomment the following library declaration if instantiating |
---- any Xilinx primitives in this code. |
library UNISIM; |
use UNISIM.VComponents.all; |
|
|
|
entity jop is |
|
generic ( |
ram_cnt : integer := 4; -- clock cycles for external ram |
rom_cnt : integer := 15; -- not used for S3K |
jpc_width : integer := 11; -- address bits of java bytecode pc = cache size |
block_bits : integer := 4; -- 2*block_bits is number of cache blocks |
spm_width : integer := 0 -- size of scratchpad RAM (in number of address bits for 32-bit words) |
); |
|
port ( |
clk : in std_logic; |
|
-- |
---- serial interface |
-- |
ser_txd : out std_logic; |
ser_rxd : in std_logic; |
-- |
-- |
-- watchdog |
-- |
wd : out std_logic; |
|
-- Control Signals from JOP |
-- configuration_trigger : out std_logic_vector(7 downto 0); |
eRCP_trigger_reg : out std_logic; |
|
-- |
---==========================================================-- |
----===========Virtex-4 SRAM Port============================-- |
sram_clk : out std_logic; |
sram_feedback_clk : out std_logic; |
|
sram_addr : out std_logic_vector(22 downto 0); |
|
sram_we_n : out std_logic; |
sram_oe_n : out std_logic; |
|
sram_data : inout std_logic_vector(31 downto 0); |
|
sram_bw0: out std_logic; |
sram_bw1 : out std_logic; |
|
sram_bw2 : out std_Logic; |
sram_bw3 : out std_logic; |
|
sram_adv_ld_n : out std_logic; |
sram_mode : out std_logic; |
sram_cen : out std_logic; |
sram_cen_test : out std_logic; |
sram_zz : out std_logic; |
|
---=========================================================--- |
---=========================================================--- |
|
-- |
-- I/O pins of board TODO: change this and io for xilinx board! |
-- |
-- io_b : inout std_logic_vector(10 downto 1); |
-- io_l : inout std_logic_vector(20 downto 1); |
-- io_r : inout std_logic_vector(20 downto 1); |
-- io_t : inout std_logic_vector(6 downto 1) |
|
-- Wizardry Interface |
ack_i : in std_logic; |
err_i : in std_logic; |
dat_i : in std_logic_vector(31 downto 0); |
cyc_o : out std_logic; |
stb_o : out std_logic; |
we_o : out std_logic; |
dat_o : out std_logic_vector(31 downto 0); |
adr_o : out std_logic_Vector(21 downto 0); |
lock_o : out std_logic; |
-- id_o : out std_logic_Vector(4 downto 0); |
priority_o : out std_logic_Vector(7 downto 0) |
); |
end jop; |
|
architecture rtl of jop is |
--======================================================================= |
--Create alias for simple naming convention for Virtex-4 SRAM============ |
--====================================================================== |
alias virtex_ram_addr : std_logic_vector(22 downto 0) is sram_addr; |
alias ram_nwe : std_logic is sram_we_n; |
alias ram_noe : std_logic is sram_oe_n; |
alias rama_d : std_logic_vector(15 downto 0) is sram_data(15 downto 0); |
alias rama_nlb : std_logic is sram_bw0; |
alias rama_nub : std_logic is sram_bw1; |
alias ramb_d : std_logic_vector(15 downto 0) is sram_data(31 downto 16); |
alias ramb_nlb : std_logic is sram_bw2; |
alias ramb_nub : std_logic is sram_bw3; |
signal rama_ncs : std_logic; |
signal ramb_ncs : std_logic; |
--========================================================================= |
|
|
---------original JOP ram address port used to---------------- |
----generate 23 bit address width for Virtex-4 SRAM----------- |
signal ram_addr : std_logic_vector(17 downto 0); |
-------------------------------------------------------------- |
-------------------------------------------------------------- |
|
|
--signal ser_txd : std_logic; |
--signal ser_rxd : std_logic; |
|
-- |
-- Signals |
-- |
signal clk_int, clk2 : std_logic; |
|
signal int_res : std_logic; |
signal res_cnt : unsigned(2 downto 0) := "000"; -- for the simulation |
|
-- attribute altera_attribute : string; |
-- attribute altera_attribute of res_cnt : signal is "POWER_UP_LEVEL=LOW"; |
|
-- |
-- jopcpu connections |
-- |
signal sc_mem_out : sc_out_type; |
signal sc_mem_in : sc_in_type; |
signal sc_io_out : sc_out_type; |
signal sc_io_in : sc_in_type; |
signal irq_in : irq_bcf_type; |
signal irq_out : irq_ack_type; |
signal exc_req : exception_type; |
|
-- |
-- IO interface |
-- |
signal ser_in : ser_in_type; |
signal ser_out : ser_out_type; |
signal wd_out : std_logic; |
|
-- for generation of internal reset |
|
-- memory interface |
|
signal ram_dout : std_logic_vector(31 downto 0); |
signal ram_din : std_logic_vector(31 downto 0); |
signal ram_dout_en : std_logic; |
signal ram_ncs : std_logic; |
|
-- not available at this board: |
signal ser_ncts : std_logic; |
signal ser_nrts : std_logic; |
signal sram_feedback_clk_r1,sram_feedback_clk_r2 : std_logic; |
signal sram_clk_r1,sram_clk_r2 : std_logic; |
|
begin |
|
--================================================-- |
--============VIRTEX 4 SRAM SIGNALS===============-- |
--process(clk) |
--begin |
--if(rising_edge(clk)) then |
sram_feedback_clk <= clk; --not clk;--not clk2; --clk is 100MHz clk2 is 50 MHz |
sram_clk <= clk; --not clk;--not clk2; --clk is 100MHz clk2 is 50 MHz |
--end if; |
--end process; |
|
|
|
sram_adv_ld_n <= '0'; |
sram_mode <= '0'; |
sram_cen <= '0'; |
virtex_ram_addr <= "00000" & ram_addr; |
sram_zz <= '0'; |
|
--================================================-- |
--================================================-- |
|
|
ser_ncts <= '0'; |
-- |
-- intern reset |
-- |
|
process(clk)--_int)--clk is |
begin |
if rising_edge(clk) then --was clk_int |
if (res_cnt/="111") then |
res_cnt <= res_cnt+1; |
end if; |
|
int_res <= not res_cnt(0) or not res_cnt(1) or not res_cnt(2); |
end if; |
end process; |
process(clk) |
begin |
if rising_edge(clk) then |
clk2 <= not clk2; |
end if; |
end process; |
|
-- |
-- components of jop |
-- |
clk_int <= clk2; |
|
wd <= wd_out; |
|
cpm_cpu: entity work.jopcpu |
generic map( |
jpc_width => jpc_width, |
block_bits => block_bits, |
spm_width => spm_width |
) |
port map(clk, int_res, --was clk_int |
sc_mem_out, sc_mem_in, |
sc_io_out, sc_io_in, |
irq_in, irq_out, exc_req); |
|
cmp_io: entity work.scio |
port map (clk, int_res, --was clk_int |
sc_io_out, sc_io_in, |
irq_in, irq_out, exc_req, |
|
-- Control Signals from JOP |
-- configuration_trigger => configuration_trigger, |
eRCP_trigger_reg => eRCP_trigger_reg, |
|
txd => ser_txd, |
rxd => ser_rxd, |
ncts => ser_ncts, |
nrts => ser_nrts, |
wd => wd_out, |
l => open, |
r => open, |
t => open, |
b => open, |
-- Wizardry Interface |
ack_i => ack_i, |
err_i => err_i, |
dat_i => dat_i, |
cyc_o => cyc_o, |
stb_o => stb_o, |
we_o => we_o, |
dat_o => dat_o, |
adr_o => adr_o, |
lock_o => lock_o, |
-- id_o => id_o, |
priority_o => priority_o |
); |
|
cmp_scm: entity work.sc_mem_if |
generic map ( |
ram_ws => ram_cnt-1, |
addr_bits => 18 |
) |
port map (clk, int_res, --was clk_int |
sc_mem_out, sc_mem_in, |
|
ram_addr => ram_addr, |
ram_dout => ram_dout, |
ram_din => ram_din, |
ram_dout_en => ram_dout_en, |
ram_ncs => ram_ncs, |
ram_noe => ram_noe, |
ram_nwe => ram_nwe |
); |
|
process(ram_dout_en, ram_dout) |
begin |
if ram_dout_en='1' then |
rama_d <= ram_dout(15 downto 0); |
ramb_d <= ram_dout(31 downto 16); |
else |
rama_d <= (others => 'Z'); |
ramb_d <= (others => 'Z'); |
end if; |
end process; |
|
ram_din <= ramb_d & rama_d; |
|
-- |
-- To put this RAM address in an output register |
-- we have to make an assignment (FAST_OUTPUT_REGISTER) |
-- |
rama_ncs <= ram_ncs; |
rama_nlb <= '0'; |
rama_nub <= '0'; |
|
ramb_ncs <= ram_ncs; |
ramb_nlb <= '0'; |
ramb_nub <= '0'; |
|
end rtl; |
/xram.vhd
0,0 → 1,119
-- |
-- This file is part of JOP, the Java Optimized Processor |
-- |
-- Copyright (C) 2001-2003, Martin Schoeberl (martin@jopdesign.com) |
-- Copyright (C) 2003, Ed Anuff |
-- |
-- 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/>. |
-- |
|
|
-- |
-- xram_xc2s_xcv.vhd |
-- |
-- internal memory for JOP3 |
-- Version for Xilinx Spartan II/IIe and Virtex Families |
-- |
-- Changes: |
-- 2003-12-29 EA - modified for Xilinx ISE to use Block SelectRAM+ |
-- |
-- |
|
Library IEEE ; |
use IEEE.std_logic_1164.all ; |
use IEEE.std_logic_arith.all ; |
use IEEE.std_logic_unsigned.all ; |
library unisim; |
use unisim.vcomponents.all; |
|
entity ram is |
generic (width : integer := 32; addr_width : integer := 8); |
port ( |
reset : in std_logic; |
data : in std_logic_vector(width-1 downto 0); |
wraddress : in std_logic_vector(addr_width-1 downto 0); |
rdaddress : in std_logic_vector(addr_width-1 downto 0); |
wren : in std_logic; |
clock : in std_logic; |
|
q : out std_logic_vector(width-1 downto 0) |
); |
end ram ; |
|
-- |
-- registered and delayed wraddress, wren |
-- registered din |
-- registered rdaddress |
-- unregistered dout |
-- |
-- with normal clock on wrclock: |
-- => read during write on same address!!! (ok in ACEX) |
-- for Cyclone use not clock for wrclock, but works also on ACEX |
-- |
architecture rtl of ram is |
|
signal wraddr_dly : std_logic_vector(addr_width-1 downto 0); |
signal wren_dly : std_logic; |
|
COMPONENT xram_block |
PORT( |
a_rst : IN std_logic; |
a_clk : IN std_logic; |
a_en : IN std_logic; |
a_wr : IN std_logic; |
a_addr : IN std_logic_vector(7 downto 0); |
a_din : IN std_logic_vector(31 downto 0); |
b_rst : IN std_logic; |
b_clk : IN std_logic; |
b_en : IN std_logic; |
b_wr : IN std_logic; |
b_addr : IN std_logic_vector(7 downto 0); |
b_din : IN std_logic_vector(31 downto 0); |
a_dout : OUT std_logic_vector(31 downto 0); |
b_dout : OUT std_logic_vector(31 downto 0) |
); |
END COMPONENT; |
|
|
begin |
|
-- |
-- delay wr addr and ena because of registerd indata |
-- |
process(clock) begin |
|
if rising_edge(clock) then |
wraddr_dly <= wraddress; |
wren_dly <= wren; |
end if; |
end process; |
|
cmp_xram_block: xram_block PORT MAP( |
a_rst => '0', |
a_clk => not clock, |
a_en => '1', |
a_wr => wren_dly, |
a_addr => wraddr_dly, |
a_din => data, |
a_dout => open, |
b_rst => '0', |
b_clk => clock, |
b_en => '1', |
b_wr => '0', |
b_addr => rdaddress, |
b_din => X"00000000", |
b_dout => q |
); |
|
end rtl; |
/extension.vhd
0,0 → 1,242
-- |
-- |
-- 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/>. |
-- |
|
|
-- |
-- extension.vhd |
-- |
-- contains interface to memory, multiplier and IO |
-- MUX for din from stack |
-- |
-- resources on Cyclone |
-- |
-- 55 LCs (+xxx for mul) |
-- |
-- ext_addr and wr are one cycle earlier than data |
-- dout is read one cycle after rd |
-- |
-- address mapping see jop_tpyes.vhd |
-- |
-- |
-- 2004-09-11 first version |
-- 2005-04-05 Reserve negative addresses for wishbone interface |
-- 2005-04-07 generate bsy from delayed wr or'ed with mem_out.bsy |
-- 2005-05-30 added wishbone interface |
-- 2005-11-28 Substitute WB interface by the SimpCon IO interface ;-) |
-- All IO devices are now memory mapped |
-- 2007-04-13 Changed memory connection to records |
-- New array instructions |
-- 2007-12-22 Correction of data MUX bug for array read access |
-- 2008-02-20 Removed memory - I/O muxing |
-- |
|
|
library ieee ; |
use ieee.std_logic_1164.all ; |
use ieee.numeric_std.all ; |
|
use work.jop_types.all; |
|
entity extension is |
|
port ( |
clk, reset : in std_logic; |
|
-- core interface |
|
ain : in std_logic_vector(31 downto 0); -- TOS |
bin : in std_logic_vector(31 downto 0); -- NOS |
ext_addr : in std_logic_vector(exta_width-1 downto 0); |
rd, wr : in std_logic; |
bsy : out std_logic; |
dout : out std_logic_vector(31 downto 0); -- to stack |
|
-- memory interface |
mem_in : out mem_in_type; |
mem_out : in mem_out_type |
|
); |
end extension; |
|
architecture rtl of extension is |
|
-- |
-- components: |
-- |
|
component mul is |
|
port ( |
clk : in std_logic; |
|
ain : in std_logic_vector(31 downto 0); |
bin : in std_logic_vector(31 downto 0); |
wr : in std_logic; -- write starts multiplier |
dout : out std_logic_vector(31 downto 0) |
); |
end component mul; |
|
-- |
-- signals for mulitiplier |
-- |
signal mul_dout : std_logic_vector(31 downto 0); |
signal mul_wr : std_logic; |
|
-- |
-- Signals |
-- |
signal mem_scio_rd : std_logic; -- memory or SimpCon IO read |
signal mem_scio_wr : std_logic; -- memory or SimpCon IO write |
signal wraddr_wr : std_logic; |
|
signal wr_dly : std_logic; -- generate a bsy with delayed wr |
|
signal exr : std_logic_vector(31 downto 0); -- extension data register |
|
begin |
|
cmp_mul : mul |
port map (clk, |
ain, bin, mul_wr, |
mul_dout |
); |
|
dout <= exr; |
|
-- |
-- read |
-- |
-- TODO: the read MUX could be set by using the |
-- according wr/ext_addr from JOP and not the |
-- following rd/ext_addr |
-- Than no intermixing of mul/mem and io operations |
-- is allowed. But we are not using interleaved mul/mem/io |
-- operations in jvm.asm anyway. |
-- |
-- TAKE CARE when mem_out.bcstart is read! |
-- |
-- ** bcstart is also read without a mem_bc_rd JOP wr !!! *** |
-- => a combinatorial mux select on rd and ext_adr==7! |
-- |
-- The rest could be set with JOP wr start transaction |
-- Is this also true for io_data? |
-- |
-- 29.11.2005 evening: I think this solution driving the exr |
-- mux from ext_addr is quite ok. The pipelining from rd/ext_adr |
-- to A is fixed. |
-- |
process(clk, reset) |
begin |
if (reset='1') then |
exr <= (others => '0'); |
elsif rising_edge(clk) then |
|
if (ext_addr=LDMRD) then |
exr <= mem_out.dout; |
elsif (ext_addr=LDMUL) then |
exr <= mul_dout; |
-- elsif (ext_addr=LDBCSTART) then |
else |
exr <= mem_out.bcstart; |
end if; |
|
end if; |
end process; |
|
|
-- |
-- write |
-- |
process(clk, reset) |
begin |
if (reset='1') then |
mem_scio_rd <= '0'; |
mem_scio_wr <= '0'; |
wraddr_wr <= '0'; |
mem_in.bc_rd <= '0'; |
mem_in.iaload <= '0'; |
mem_in.iastore <= '0'; |
mem_in.getfield <= '0'; |
mem_in.putfield <= '0'; |
mul_wr <= '0'; |
wr_dly <= '0'; |
|
|
elsif rising_edge(clk) then |
mem_scio_rd <= '0'; |
mem_scio_wr <= '0'; |
wraddr_wr <= '0'; |
mem_in.bc_rd <= '0'; |
mem_in.iaload <= '0'; |
mem_in.iastore <= '0'; |
mem_in.getfield <= '0'; |
mem_in.putfield <= '0'; |
mem_in.copy <= '0'; |
mul_wr <= '0'; |
|
wr_dly <= wr; |
|
-- |
-- wr is generated in decode and one cycle earlier than |
-- the data to be written (e.g. read address for the memory interface) |
-- |
if wr='1' then |
|
if ext_addr=STMRA then |
mem_scio_rd <= '1'; -- start memory or io read |
elsif ext_addr=STMWA then |
wraddr_wr <= '1'; -- store write address |
elsif ext_addr=STMWD then |
mem_scio_wr <= '1'; -- start memory or io write |
elsif ext_addr=STALD then |
mem_in.iaload <= '1'; -- start an array load |
elsif ext_addr=STAST then |
mem_in.iastore <= '1'; -- start an array store |
elsif ext_addr=STGF then |
mem_in.getfield <= '1'; -- start getfield |
elsif ext_addr=STPF then |
mem_in.putfield <= '1'; -- start getfield |
elsif ext_addr=STCP then |
mem_in.copy <= '1'; -- start copy |
elsif ext_addr=STMUL then |
mul_wr <= '1'; -- start multiplier |
-- elsif ext_addr=STBCR then |
else |
mem_in.bc_rd <= '1'; -- start bc read |
end if; |
end if; |
|
end if; |
end process; |
|
-- |
-- memory read/write |
-- |
mem_in.rd <= mem_scio_rd; |
mem_in.wr <= mem_scio_wr; |
mem_in.addr_wr <= wraddr_wr; |
|
-- a JOP wr generates the first bsy cycle |
-- the following are generated by the memory |
-- system or the SimpCon device |
bsy <= wr_dly or mem_out.bsy; |
|
|
end rtl; |
/offtbl.vhd
0,0 → 1,67
-- |
-- offtbl.vhd |
-- |
-- next bc or bc operand read for offtch. |
-- |
-- DONT edit this file! |
-- generated by Jopa.java |
-- |
|
library ieee; |
use ieee.std_logic_1164.all; |
use ieee.std_logic_arith.all; |
use ieee.std_logic_unsigned.all; |
|
entity offtbl is |
port ( |
idx : in std_logic_vector(4 downto 0); |
q : out std_logic_vector(10 downto 0) |
); |
end offtbl; |
|
architecture rtl of offtbl is |
|
begin |
|
process(idx) begin |
|
case idx is |
|
when "00000" => q <= "00000010100"; -- 20 |
when "00001" => q <= "11111111001"; -- -7 |
when "00010" => q <= "00001000000"; -- 64 |
when "00011" => q <= "11111110111"; -- -9 |
when "00100" => q <= "11111100000"; -- -32 |
when "00101" => q <= "00000000100"; -- 4 |
when "00110" => q <= "11111000110"; -- -58 |
when "00111" => q <= "00011110110"; -- 246 |
when "01000" => q <= "11111111011"; -- -5 |
when "01001" => q <= "00001000001"; -- 65 |
when "01010" => q <= "00000001100"; -- 12 |
when "01011" => q <= "00010000111"; -- 135 |
when "01100" => q <= "00011101110"; -- 238 |
when "01101" => q <= "00001010101"; -- 85 |
when "01110" => q <= "00010111100"; -- 188 |
when "01111" => q <= "00000100101"; -- 37 |
when "10000" => q <= "00010001101"; -- 141 |
when "10001" => q <= "11011101100"; -- -276 |
when "10010" => q <= "11011100010"; -- -286 |
when "10011" => q <= "11101111000"; -- -136 |
when "10100" => q <= "11101011100"; -- -164 |
when "10101" => q <= "11100111110"; -- -194 |
when "10110" => q <= "11100111000"; -- -200 |
when "10111" => q <= "11100010000"; -- -240 |
when "11000" => q <= "11100001010"; -- -246 |
when "11001" => q <= "10111010101"; -- -555 |
when "11010" => q <= "10111001001"; -- -567 |
when "11011" => q <= "10110110110"; -- -586 |
when "11100" => q <= "10110011001"; -- -615 |
when "11101" => q <= "10110000001"; -- -639 |
when "11110" => q <= "11111110010"; -- -14 |
when "11111" => q <= "11111110001"; -- -15 |
|
when others => q <= "00000000000"; |
end case; |
end process; |
|
end rtl; |
/shift.vhd
0,0 → 1,132
-- |
-- |
-- 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/>. |
-- |
|
|
-- |
-- shift.vhd |
-- |
-- barrel shifter |
-- |
-- resources on ACEX1K |
-- |
-- |
-- 227 LCs |
-- |
-- 2001-05-14 first version |
-- |
|
|
library ieee ; |
use ieee.std_logic_1164.all ; |
use ieee.numeric_std.all ; |
|
|
entity shift is |
|
generic ( |
width : integer := 32 -- one data word |
); |
|
port ( |
din : in std_logic_vector(width-1 downto 0); |
off : in std_logic_vector(4 downto 0); |
shtyp : in std_logic_vector(1 downto 0); |
dout : out std_logic_vector(width-1 downto 0) |
); |
end shift; |
|
|
architecture rtl of shift is |
|
-- |
-- Signals |
-- |
signal zero32 : std_logic_vector(width-1 downto 0); |
|
|
begin |
|
zero32 <= (others => '0'); |
|
process(din, off, shtyp, zero32) |
|
variable shiftin : std_logic_vector(63 downto 0); |
variable shiftcnt : std_logic_vector(4 downto 0); |
|
begin |
|
shiftin := zero32 & din; |
shiftcnt := off; |
|
if shtyp="01" then -- sll |
shiftin(31 downto 0) := zero32; |
shiftin(63 downto 31) := '0' & din; |
shiftcnt := not shiftcnt; |
elsif shtyp="10" then -- sra |
if din(31) = '1' then |
shiftin(63 downto 32) := (others => '1'); |
else |
shiftin(63 downto 32) := zero32; |
end if; |
end if; |
|
-- |
-- 00 ushr |
-- 01 shl |
-- 10 shr |
-- 11 not used! |
-- |
-- das geht aber nicht!!! TODO schaun warum |
-- |
-- if shtyp(0)='1' then -- sll |
-- shiftin := din & zero32; |
-- shiftcnt := not off; |
-- else -- sr |
-- shiftin(31 downto 0) := din; |
-- shiftcnt := off; |
-- |
-- if shtyp(1)='1' and din(31) = '1' then -- sra |
-- shiftin(63 downto 32) := (others => '1'); |
-- else |
-- shiftin(63 downto 32) := zero32; |
-- end if; |
-- end if; |
|
if shiftcnt (4) = '1' then |
shiftin(47 downto 0) := shiftin(63 downto 16); |
end if; |
if shiftcnt (3) = '1' then |
shiftin(39 downto 0) := shiftin(47 downto 8); |
end if; |
if shiftcnt (2) = '1' then |
shiftin(35 downto 0) := shiftin(39 downto 4); |
end if; |
if shiftcnt (1) = '1' then |
shiftin(33 downto 0) := shiftin(35 downto 2); |
end if; |
if shiftcnt (0) = '1' then |
shiftin(31 downto 0) := shiftin(32 downto 1); |
end if; |
|
dout <= shiftin(31 downto 0); |
|
end process; |
|
end rtl; |
/decode.vhd
0,0 → 1,384
-- |
-- |
-- 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/>. |
-- |
|
|
-- |
-- decode.vhd |
-- |
-- cpu decode of JOP3 |
-- |
-- generate control for pc and stack |
-- |
-- |
-- resources on ACEX1K30-3 |
-- |
-- xxx LCs, 42.0 MHz |
-- |
-- todo: |
-- |
-- |
-- 2001-07-03 extracted from core.vhd |
-- 2001-10-28 ldjpc, stjpc |
-- 2001-10-31 stbc |
-- 2001-12-04 cp removed |
-- 2001-12-05 sel_rda, sel_wra: logic from ir (not registered) |
-- sel_smux: logic from ir (not registered, no mix addr/rd-ex: nop befor stsp) |
-- 2001-12-06 moved ir from decode to fetch, jbr unregistered |
-- 2001-12-07 moved jbr decode to bcfetch, ldi loads consts from ram (addr > 31), jp removed |
-- 2001-12-08 instruction set changed to 8 bit |
-- 2002-03-24 new shift instructions |
-- 2002-12-02 wait instruction for memory |
-- 2003-02-12 added instruction ld_opd_8u/16u |
-- 2004-10-07 new alu selection with sel_sub, sel_amux and ena_a |
-- 2004-10-08 moved bsy/pcwait from decode to fetch |
-- 2006-01-12 new ar for local memory addressing: star, ldmi, stmi |
-- stioa, stiod, ldiod removed |
-- 2007-08-31 use addr_width for signal dir |
-- 2007-09-01 use ram_width from jop_config instead of parameter |
-- |
|
|
library ieee ; |
use ieee.std_logic_1164.all ; |
use ieee.numeric_std.all ; |
|
use work.jop_config.all; |
use work.jop_types.all; |
|
entity decode is |
generic ( |
i_width : integer -- instruction width |
); |
|
port ( |
clk, reset : in std_logic; |
|
instr : in std_logic_vector(i_width-1 downto 0); |
zf, nf : in std_logic; -- nf, eq and lt not used (only brz, brnz) |
eq, lt : in std_logic; |
|
br : out std_logic; |
jbr : out std_logic; |
|
ext_addr : out std_logic_vector(EXTA_WIDTH-1 downto 0); |
rd, wr : out std_logic; |
|
dir : out std_logic_vector(ram_width-1 downto 0); |
|
sel_sub : out std_logic; -- 0..add, 1..sub |
sel_amux : out std_logic; -- 0..sum, 1..lmux |
ena_a : out std_logic; -- 1..store new value |
sel_bmux : out std_logic; -- 0..a, 1..mem |
sel_log : out std_logic_vector(1 downto 0); -- pop/st, and, or, xor |
sel_shf : out std_logic_vector(1 downto 0); -- sr, sl, sra, (sr) |
sel_lmux : out std_logic_vector(2 downto 0); -- log, shift, mem, io, reg |
sel_imux : out std_logic_vector(1 downto 0); -- java opds |
sel_rmux : out std_logic_vector(1 downto 0); -- sp, vp, jpc |
sel_smux : out std_logic_vector(1 downto 0); -- sp, a, sp-1, sp+1 |
|
sel_mmux : out std_logic; -- 0..a, 1..b |
sel_rda : out std_logic_vector(2 downto 0); -- |
sel_wra : out std_logic_vector(2 downto 0); -- |
|
wr_ena : out std_logic; |
|
ena_b : out std_logic; |
ena_vp : out std_logic; |
ena_jpc : out std_logic; |
ena_ar : out std_logic |
); |
end decode; |
|
architecture rtl of decode is |
|
-- |
-- Signals |
-- |
|
-- |
-- intruction register, shortcut |
-- |
-- signal ir : std_logic_vector(i_width-1 downto 0); -- Xilinx does not like this... instruction register |
signal ir : std_logic_vector(7 downto 0); -- instruction register |
|
begin |
|
ir <= instr; -- registered in fetch |
|
ext_addr <= ir(EXTA_WIDTH-1 downto 0); -- address for extension select |
|
-- |
-- branch, jbranch |
-- |
|
process(clk, reset, ir, zf) |
begin |
if (reset='1') then |
br <= '0'; |
elsif rising_edge(clk) then |
|
br <= '0'; |
if((ir(7 downto 5)="010" and zf='1') or -- bz |
(ir(7 downto 5)="011" and zf='0')) then -- bnz |
br <= '1'; |
end if; |
|
end if; |
end process; |
|
-- wait is decoded direct in fetch.vhd! |
|
process(ir) |
begin |
|
jbr <= '0'; |
if (ir="10000010") then -- jbr: goto and if_xxx |
jbr <= '1'; |
end if; |
|
end process; |
|
-- |
-- addr, read stage: |
-- decode from ir (only logic, no register) |
-- |
process(ir) |
begin |
|
-- ram wraddress and wrena are registered |
|
wr_ena <= '0'; |
if (ir(7 downto 5)="101" or -- 'push' instructions |
ir(7 downto 5)="110" or |
ir(7 downto 5)="111" or |
ir(7 downto 5)="001" or -- stm |
ir(7 downto 3)="00010") then -- st, stn, stmi |
|
wr_ena <= '1'; |
end if; |
|
rd <= '0'; |
if ir(7 downto 3)="11100" then -- ld memio |
rd <= '1'; |
end if; |
wr <= '0'; |
if ir(7 downto 0)="00000110" |
or ir(7 downto 0)="00000111" |
or ir(7 downto 3)="00001" then -- st memio |
wr <= '1'; |
end if; |
|
sel_imux <= ir(1 downto 0); -- ld opd_x |
|
-- select for rd/wr address muxes |
|
dir <= std_logic_vector(to_unsigned(0, ram_width-5)) & ir(4 downto 0); |
|
sel_rda <= "110"; -- sp |
if (ir(7 downto 3)="11101") then -- ld, ldn, ldmi |
sel_rda <= ir(2 downto 0); |
end if; |
if (ir(7 downto 5)="101") then -- ldm |
sel_rda <= "111"; |
end if; |
if (ir(7 downto 5)="110") then -- ldi |
sel_rda <= "111"; |
dir <= std_logic_vector(to_unsigned(1, ram_width-5)) & |
ir(4 downto 0); -- addr > 31 constants |
end if; |
|
sel_wra <= "110"; -- spp |
if ir(7 downto 3)="00010" then -- st, stn, stmi |
sel_wra <= ir(2 downto 0); |
end if; |
if ir(7 downto 5)="001" then -- stm |
sel_wra <= "111"; |
end if; |
|
-- select for sp update |
|
sel_smux <= "00"; -- sp = sp |
if(ir(7)='0') then -- 'pop' instruction |
sel_smux <= "01"; -- --sp |
end if; |
if(ir(7 downto 5)="101" or -- 'push' instruction |
ir(7 downto 5)="110" or |
ir(7 downto 5)="111") then |
sel_smux <= "10"; -- ++sp |
end if; |
if (ir="00011011") then -- st sp |
sel_smux <= "11"; -- sp = a |
end if; |
|
end process; |
|
-- |
-- ex stage |
-- |
|
process(clk, reset) |
begin |
|
if (reset='1') then |
sel_sub <= '0'; |
sel_amux <= '0'; |
ena_a <= '0'; |
sel_bmux <= '0'; |
sel_log <= "00"; |
sel_shf <= "00"; |
sel_lmux <= "000"; |
sel_rmux <= "00"; |
sel_mmux <= '0'; |
ena_b <= '0'; |
ena_vp <= '0'; |
ena_jpc <= '0'; |
ena_ar <= '0'; |
|
elsif rising_edge(clk) then |
|
sel_log <= "00"; |
if (ir(7 downto 2)="000000") then -- pop, and, or, xor |
sel_log <= ir(1 downto 0); |
end if; |
|
sel_shf <= ir(1 downto 0); |
|
sel_sub <= '1'; -- default is subtract for lt-flag |
sel_amux <= '1'; -- default is lmux |
ena_a <= '1'; -- default is enable |
ena_vp <= '0'; |
ena_jpc <= '0'; |
ena_ar <= '0'; |
|
case ir is |
|
when "00000000" => -- pop |
when "00000001" => -- and |
when "00000010" => -- or |
when "00000011" => -- xor |
when "00000100" => -- add |
sel_sub <= '0'; |
sel_amux <= '0'; |
when "00000101" => -- sub |
sel_amux <= '0'; |
when "00001010" => -- stmra |
when "00001011" => -- stmwa |
when "00001100" => -- stmwd |
when "00001101" => -- stopa |
when "00001110" => -- stopb |
when "00010000" => -- st0 |
when "00010001" => -- st1 |
when "00010010" => -- st2 |
when "00010011" => -- st3 |
when "00010100" => -- st |
when "00010101" => -- stmi |
when "00011000" => -- stvp |
ena_vp <= '1'; |
when "00011001" => -- stjpc |
ena_jpc <= '1'; |
when "00011010" => -- star |
ena_ar <= '1'; |
when "00011011" => -- stsp |
when "00011100" => -- ushr |
when "00011101" => -- shl |
when "00011110" => -- shr |
-- when "001-----" => -- stm |
-- when "010-----" => -- bz |
-- when "011-----" => -- bnz |
when "10000000" => -- nop |
ena_a <= '0'; |
when "10000001" => -- wait |
ena_a <= '0'; |
when "10000010" => -- jbr |
ena_a <= '0'; |
-- when "101-----" => -- ldm |
-- when "110-----" => -- ldi |
when "11100010" => -- ldmrd |
when "11100011" => -- ldmbsy |
when "11100101" => -- ldmul |
when "11101000" => -- ld0 |
when "11101001" => -- ld1 |
when "11101010" => -- ld2 |
when "11101011" => -- ld3 |
when "11101100" => -- ld |
when "11101101" => -- ldmi |
when "11110000" => -- ldsp |
when "11110001" => -- ldvp |
when "11110010" => -- ldjpc |
when "11110100" => -- ld_opd_8u |
when "11110101" => -- ld_opd_8s |
when "11110110" => -- ld_opd_16u |
when "11110111" => -- ld_opd_16s |
when "11111000" => -- dup |
ena_a <= '0'; |
|
when others => |
null; |
end case; |
|
|
sel_lmux <= "000"; -- log |
|
if ir(7 downto 2)="000111" then -- ushr, shl, shr |
sel_lmux <= "001"; |
end if; |
|
if ir(7 downto 5)="101" then -- ldm |
sel_lmux <= "010"; |
end if; |
if ir(7 downto 5)="110" then -- ldi |
sel_lmux <= "010"; |
end if; |
|
if ir(7 downto 3)="11101" then -- ld, ldn, ldmi |
sel_lmux <= "010"; |
end if; |
|
if ir(7 downto 2)="111101" then -- ld_opd_x |
sel_lmux <= "011"; |
end if; |
|
if ir(7 downto 3)="11100" then -- ld io |
sel_lmux <= "100"; |
end if; |
|
if ir(7 downto 2)="111100" then -- ldsp, ldvp, ldjpc |
sel_lmux <= "101"; |
end if; |
|
-- default 'pop' |
sel_bmux <= '1'; -- mem |
sel_mmux <= '0'; -- a |
if (ir(7)='1') then -- 'push' and 'no stack change' |
sel_bmux <= '0'; -- a |
sel_mmux <= '1'; -- b |
end if; |
|
ena_b <= '1'; |
if (ir(7 downto 5)="100") then -- 'no stack change' (nop, jbr) |
ena_b <= '0'; |
end if; |
|
sel_rmux <= ir(1 downto 0); -- ldsp, ldvp, ldjpc |
|
end if; |
end process; |
|
end rtl; |
/fifo.vhd
0,0 → 1,179
-- |
-- |
-- 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/>. |
-- |
|
|
-- |
-- fifo.vhd |
-- |
-- simple fifo |
-- |
-- uses FF and every rd or wr has to 'bubble' through the hole fifo. |
-- |
-- Author: Martin Schoeberl martin.schoeberl@chello.at |
-- |
-- |
-- resources on ACEX1K |
-- |
-- (width+2)*depth-1 LCs |
-- |
-- |
-- 2002-01-06 first working version |
-- 2002-11-03 a signal for reaching threshold |
-- 2005-02-20 change entity order for modelsim vcom |
-- |
|
library ieee; |
use ieee.std_logic_1164.all; |
|
entity fifo_elem is |
|
generic (width : integer); |
port ( |
clk : in std_logic; |
reset : in std_logic; |
|
din : in std_logic_vector(width-1 downto 0); |
dout : out std_logic_vector(width-1 downto 0); |
|
rd : in std_logic; |
wr : in std_logic; |
|
rd_prev : out std_logic; |
full : out std_logic |
); |
end fifo_elem; |
|
architecture rtl of fifo_elem is |
|
signal buf : std_logic_vector(width-1 downto 0); |
signal f : std_logic; |
|
begin |
|
dout <= buf; |
|
process(clk, reset, f) |
|
begin |
|
full <= f; |
|
if (reset='1') then |
|
buf <= (others => '0'); |
f <= '0'; |
rd_prev <= '0'; |
|
elsif rising_edge(clk) then |
|
rd_prev <= '0'; |
if f='0' then |
if wr='1' then |
rd_prev <= '1'; |
buf <= din; |
f <= '1'; |
end if; |
else |
if rd='1' then |
f <= '0'; |
end if; |
end if; |
|
end if; |
|
end process; |
|
end rtl; |
|
library ieee; |
use ieee.std_logic_1164.all; |
|
entity fifo is |
|
generic (width : integer := 8; depth : integer := 4; thres : integer := 2); |
port ( |
clk : in std_logic; |
reset : in std_logic; |
|
din : in std_logic_vector(width-1 downto 0); |
dout : out std_logic_vector(width-1 downto 0); |
|
rd : in std_logic; |
wr : in std_logic; |
|
empty : out std_logic; |
full : out std_logic; |
half : out std_logic |
); |
end fifo ; |
|
architecture rtl of fifo is |
|
component fifo_elem is |
|
generic (width : integer); |
port ( |
clk : in std_logic; |
reset : in std_logic; |
|
din : in std_logic_vector(width-1 downto 0); |
dout : out std_logic_vector(width-1 downto 0); |
|
rd : in std_logic; |
wr : in std_logic; |
|
rd_prev : out std_logic; |
full : out std_logic |
); |
end component; |
|
signal r, w, rp, f : std_logic_vector(depth-1 downto 0); |
type d_array is array (0 to depth-1) of std_logic_vector(width-1 downto 0); |
signal di, do : d_array; |
|
|
|
begin |
|
|
g1: for i in 0 to depth-1 generate |
|
f1: fifo_elem generic map (width) |
port map (clk, reset, di(i), do(i), r(i), w(i), rp(i), f(i)); |
|
x: if i<depth-1 generate |
r(i) <= rp(i+1); |
w(i+1) <= f(i); |
di(i+1) <= do(i); |
end generate; |
|
end generate; |
|
di(0) <= din; |
dout <= do(depth-1); |
w(0) <= wr; |
r(depth-1) <= rd; |
|
full <= f(0); |
half <= f(depth-thres); |
empty <= not f(depth-1); |
|
end rtl; |
|
/sdpram.vhd
0,0 → 1,94
-- |
-- |
-- This file is a part of JOP, the Java Optimized Processor |
-- |
-- Copyright (C) 2006, 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/>. |
-- |
|
-- |
-- sdpram.vhd |
-- |
-- Simple dual port ram with read and write port |
-- and independent clocks |
-- Read and write address, write data is registered. Output is not |
-- registered. Read enable gates the read address. Is compatible |
-- with SimpCon. |
-- |
-- When using different clocks following warning is generated: |
-- Functionality differs from the original design. |
-- Read during write at the same address is undefined. |
-- |
-- If read enable is used a discrete output register is synthesized. |
-- Without read enable the |
-- |
-- Author: Martin Schoeberl (martin@jopdesign.com) |
-- |
-- 2006-08-03 adapted from simulation only version |
-- 2008-03-02 added read enable |
-- |
|
library ieee; |
use ieee.std_logic_1164.all; |
use ieee.numeric_std.all; |
|
entity sdpram is |
generic (width : integer := 32; addr_width : integer := 7); |
port ( |
wrclk : in std_logic; |
data : in std_logic_vector(width-1 downto 0); |
wraddress : in std_logic_vector(addr_width-1 downto 0); |
wren : in std_logic; |
|
rdclk : in std_logic; |
rdaddress : in std_logic_vector(addr_width-1 downto 0); |
rden : in std_logic; |
dout : out std_logic_vector(width-1 downto 0) |
); |
end sdpram ; |
|
architecture rtl of sdpram is |
|
signal reg_dout : std_logic_vector(width-1 downto 0); |
|
subtype word is std_logic_vector(width-1 downto 0); |
constant nwords : integer := 2 ** addr_width; |
type ram_type is array(0 to nwords-1) of word; |
|
signal ram : ram_type; |
|
begin |
|
process (wrclk) |
begin |
if rising_edge(wrclk) then |
if wren='1' then |
ram(to_integer(unsigned(wraddress))) <= data; |
end if; |
end if; |
end process; |
|
process (rdclk) |
begin |
if rising_edge(rdclk) then |
if rden='1' then |
reg_dout <= ram(to_integer(unsigned(rdaddress))); |
end if; |
end if; |
end process; |
|
dout <= reg_dout; |
|
end rtl; |
/sc_wizardry_processes.vhd
0,0 → 1,185
---------------------------------------------------------------------------------- |
-- Company: |
-- Engineer: |
-- |
-- Create Date: 10:07:42 01/30/2009 |
-- Design Name: |
-- Module Name: sc_wizardry_processes - Behavioral |
-- Project Name: |
-- Target Devices: |
-- Tool versions: |
-- Description: |
-- |
-- Dependencies: |
-- |
-- Revision: |
-- Revision 0.01 - File Created |
-- Additional Comments: |
-- |
---------------------------------------------------------------------------------- |
library IEEE; |
use IEEE.STD_LOGIC_1164.ALL; |
use IEEE.STD_LOGIC_ARITH.ALL; |
use IEEE.STD_LOGIC_UNSIGNED.ALL; |
|
---- Uncomment the following library declaration if instantiating |
---- any Xilinx primitives in this code. |
--library UNISIM; |
--use UNISIM.VComponents.all; |
|
entity sc_wizardry_processes is |
port( clk : in std_logic; |
reset : in std_logic; |
rd : in std_logic; |
wr : in std_logic; |
ack_i : in std_Logic; |
dat_i : in std_logic_Vector(31 downto 0); |
address : in std_logic_Vector(3 downto 0); |
wr_data : in std_Logic_Vector(31 downto 0); |
rd_data : out std_logic_Vector(31 downto 0); |
store_address : in std_Logic; |
store_data : in std_Logic; |
store_config_data : in STD_LOGIC; |
set_sc_data : in std_Logic; |
adr_o_reg : out std_logic_Vector(21 downto 0); |
dat_o_reg : out std_logic_Vector(31 downto 0); |
-- config_trigger_reg : out std_logic_vector(7 downto 0); |
eRCP_trigger_reg : out std_logic; |
address_reg : out std_logic_vector(3 downto 0)); |
end sc_wizardry_processes; |
|
architecture Behavioral of sc_wizardry_processes is |
|
signal adr_o_reg_s : std_logic_Vector(21 downto 0); |
signal dat_o_reg_s : std_logic_vector(31 downto 0); |
signal wr_data_reg : std_logic_vector(31 downto 0); |
signal address_reg_s : std_logic_vector(3 downto 0); |
signal rd_data_reg : std_logic_vector(31 downto 0); |
signal dat_i_reg : std_logic_vector(31 downto 0); |
signal config_trigger_reg_s : std_logic_vector(7 downto 0); |
signal eRCP_trigger_reg_s,eRCP_trigger_reg_s_1,eRCP_trigger_reg_s_2, |
eRCP_trigger_reg_s_3: std_logic; --_vector(7 downto 0); |
|
begin |
|
process(clk,reset,set_sc_data) |
begin |
if reset = '1' then |
rd_data_reg <= X"075bcd15";--(others => '0'); |
elsif rising_Edge(clk) then |
if set_sc_data = '1' then |
rd_data_reg <= dat_i_reg; |
else |
rd_data_reg <= rd_data_reg; |
end if; |
end if; |
end process; |
rd_data <= rd_data_reg; |
|
process(clk,reset,ack_i) |
begin |
if reset = '1' then |
dat_i_reg <= X"075BCD14";--(others => '0'); |
elsif rising_Edge(clk) then |
if ack_i = '1' then |
dat_i_reg <= dat_i; |
else |
dat_i_reg <= dat_i_reg; |
end if; |
end if; |
end process; |
|
process(clk,reset,wr) |
begin |
if reset = '1' then |
wr_data_reg <= (others => '0'); |
elsif rising_edge(clk) then |
if wr = '1' then |
wr_data_reg <= wr_data; |
else |
wr_data_reg <= wr_data_reg; |
end if; |
end if; |
end process; |
|
process(clk,reset,wr,rd,address) |
begin |
if reset = '1' then |
address_reg_s <= (others => '0'); |
elsif rising_Edge(clk) then |
if wr = '1' or rd = '1' then |
address_reg_s <= address; --(1 downto 0); |
else |
address_reg_s <= address_reg_s; |
end if; |
end if; |
end process; |
address_reg <= address_reg_s; |
process(clk,reset,store_data) |
begin |
if reset = '1' then |
dat_o_reg_s <= (others => '0'); |
elsif rising_edge(clk) then |
if store_data = '1' then |
dat_o_reg_s <= wr_data_reg; |
else |
dat_o_reg_s <= dat_o_reg_s; |
end if; |
end if; |
end process; |
dat_o_reg <= dat_o_reg_s; |
process(clk,reset,store_address) |
begin |
if reset = '1' then |
adr_o_reg_s <= (others => '0'); |
elsif rising_edge(clk) then |
if store_address = '1' then |
adr_o_reg_s <= wr_data_reg(21 downto 0); |
else |
adr_o_reg_s <= adr_o_reg_s; |
end if; |
end if; |
end process; |
adr_o_reg <= adr_o_reg_s; |
process(clk,reset,store_config_data,eRCP_trigger_reg_s_1,eRCP_trigger_reg_s_2, |
eRCP_trigger_reg_s_3) |
begin |
if reset = '1' then |
-- config_trigger_reg_s <= (others => '0'); |
eRCP_trigger_reg_s_1 <= '1'; |
eRCP_trigger_reg_s_2 <= '0'; |
eRCP_trigger_reg_s_3 <= '0'; |
eRCP_trigger_reg_s <= '0'; |
elsif rising_edge(clk) then |
if store_config_data = '1' then |
eRCP_trigger_reg_s_1 <= '1'; |
eRCP_trigger_reg_s_2 <= '0'; |
eRCP_trigger_reg_s_3 <= '0'; |
eRCP_trigger_reg_s <= '0'; |
else |
eRCP_trigger_reg_s_1 <= '0'; |
eRCP_trigger_reg_s_2 <= eRCP_trigger_reg_s_1; |
eRCP_trigger_reg_s_3 <= eRCP_trigger_reg_s_2; |
eRCP_trigger_reg_s <= eRCP_trigger_reg_s_3; |
|
-- eRCP_trigger_reg_s <= eRCP_trigger_reg_s; |
-- eRCP_trigger_reg_s <= eRCP_trigger_reg_s; |
end if; |
end if; |
end process; |
eRCP_trigger_reg <= eRCP_trigger_reg_s; |
--process(clk,reset,store_config_data) |
--begin |
-- if reset = '1' then |
-- config_trigger_reg_s <= (others => '0'); |
-- elsif rising_edge(clk) then |
-- if store_config_data = '1' then |
-- config_trigger_reg_s <= wr_data_reg(7 downto 0); |
-- else |
-- config_trigger_reg_s <= config_trigger_reg_s; |
-- end if; |
-- end if; |
--end process; |
--config_trigger_reg <= config_trigger_reg_s; |
end Behavioral; |
|
/core.vhd
0,0 → 1,329
-- |
-- |
-- 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/>. |
-- |
|
|
-- |
-- core.vhd |
-- |
-- cpu core of JOP3 |
-- |
-- stack, pc connections |
-- decode |
-- |
-- resources on ACEX1K30-3 |
-- |
-- |
-- 596 LCs, 54.3 MHz hirarchy preserve, opt. delay |
-- |
-- 917 LCs, 44.4 MHz hirarchy preserve, opt. delay |
-- |
-- 1069 LCs, xx.x MHz jtbl, no opt. |
-- 1045 LCs, xx.x MHz cp removed |
-- 1019 LCs, 26.4 MHz 2001-12-05 (???) |
-- 1030 LCs, 29.4 MHz instruction set change |
-- |
-- todo: |
-- |
-- |
-- 2001-05-14 first version |
-- 2001-05-16 first instructions working, download of a blinking LED to ACEX |
-- 2001-05-26 delayed branch!!! |
-- 2001-07-03 adapted for jop3 |
-- 2001-10-28 ldjpc, stjpc |
-- 2001-10-31 stbc (write content of jbc) |
-- 2001-12-04 cp removed |
-- 2001-12-08 instruction set changed to 8 bit |
-- 2002-03-24 shifter to stack |
-- 2003-08-14 moved bcfetch from fetch to core |
-- 2004-10-07 new alu selection with sel_sub, sel_amux and ena_a |
-- 2004-10-08 mul operands from a and b, single instruction |
-- 2006-01-12 new ar for local memory addressing |
-- 2006-12-29 changed rom size to 2K |
-- 2007-09-01 use ram_width from jop_config instead of parameter |
-- |
|
|
library ieee ; |
use ieee.std_logic_1164.all ; |
use ieee.numeric_std.all ; |
|
use work.jop_types.all; |
use work.jop_config.all; |
|
entity core is |
|
generic ( |
jpc_width : integer; -- address bits of java bytecode pc |
|
width : integer := 32; -- one data word |
pc_width : integer := 11; -- address bits of internal instruction rom (upper half) |
i_width : integer := 8 -- instruction width |
); |
|
port ( |
clk, reset : in std_logic; |
|
-- memio connection |
|
bsy : in std_logic; |
din : in std_logic_vector(width-1 downto 0); |
ext_addr : out std_logic_vector(EXTA_WIDTH-1 downto 0); |
rd, wr : out std_logic; |
|
-- jbc connections |
|
jbc_addr : out std_logic_vector(jpc_width-1 downto 0); |
jbc_data : in std_logic_vector(7 downto 0); |
|
-- interrupt from io |
|
irq_in : in irq_bcf_type; |
irq_out : out irq_ack_type; |
|
sp_ov : out std_logic; |
|
aout : out std_logic_vector(width-1 downto 0); |
bout : out std_logic_vector(width-1 downto 0) |
); |
end core; |
|
architecture rtl of core is |
|
-- |
-- components: |
-- |
component bcfetch is |
generic (jpc_width : integer; pc_width : integer); |
port ( |
clk, reset : in std_logic; |
|
jpc_out : out std_logic_vector(jpc_width downto 0); -- jpc read |
din : in std_logic_vector(31 downto 0); -- A from stack |
jpc_wr : in std_logic; |
|
-- connection to bytecode cache |
|
jbc_addr : out std_logic_vector(jpc_width-1 downto 0); |
jbc_data : in std_logic_vector(7 downto 0); |
|
jfetch : in std_logic; |
jopdfetch : in std_logic; |
|
zf, nf : in std_logic; |
eq, lt : in std_logic; |
|
jbr : in std_logic; |
|
irq_in : in irq_bcf_type; |
irq_out : out irq_ack_type; |
|
jpaddr : out std_logic_vector(pc_width-1 downto 0); -- address for JVM |
opd : out std_logic_vector(15 downto 0) -- operands |
); |
end component; |
|
component fetch is |
generic (pc_width : integer; i_width : integer); |
port ( |
clk, reset : in std_logic; |
|
nxt, opd : out std_logic; -- jfetch and jopdfetch from table |
|
br : in std_logic; |
bsy : in std_logic; |
jpaddr : in std_logic_vector(pc_width-1 downto 0); |
|
dout : out std_logic_vector(i_width-1 downto 0) -- internal instruction (rom) |
); |
end component; |
|
component stack is |
generic (width : integer; jpc_width : integer); |
port ( |
clk, reset : in std_logic; |
|
din : in std_logic_vector(width-1 downto 0); |
dir : in std_logic_vector(ram_width-1 downto 0); |
opd : in std_logic_vector(15 downto 0); -- index for vp load opd |
jpc : in std_logic_vector(jpc_width downto 0); -- jpc read |
|
sel_sub : in std_logic; -- 0..add, 1..sub |
sel_amux : in std_logic; -- 0..sum, 1..lmux |
ena_a : in std_logic; -- 1..store new value |
sel_bmux : in std_logic; -- 0..a, 1..mem |
sel_log : in std_logic_vector(1 downto 0); -- pop/st, and, or, xor |
sel_shf : in std_logic_vector(1 downto 0); -- sr, sl, sra, (sr) |
sel_lmux : in std_logic_vector(2 downto 0); -- log, shl, mem, io, reg |
sel_imux : in std_logic_vector(1 downto 0); -- java opds |
sel_rmux : in std_logic_vector(1 downto 0); -- sp, vp, jpc |
sel_smux : in std_logic_vector(1 downto 0); -- sp, a, sp-1, sp+1 |
|
sel_mmux : in std_logic; -- 0..a, 1..b |
sel_rda : in std_logic_vector(2 downto 0); -- |
sel_wra : in std_logic_vector(2 downto 0); -- |
|
wr_ena : in std_logic; |
|
ena_b : in std_logic; |
ena_vp : in std_logic; |
ena_ar : in std_logic; |
|
sp_ov : out std_logic; |
|
zf : out std_logic; |
nf : out std_logic; |
eq : out std_logic; |
lt : out std_logic; |
aout : out std_logic_vector(width-1 downto 0); |
bout : out std_logic_vector(width-1 downto 0) |
); |
end component; |
|
component decode is |
generic (i_width : integer); |
port ( |
clk, reset : in std_logic; |
|
instr : in std_logic_vector(i_width-1 downto 0); |
zf, nf : in std_logic; |
eq, lt : in std_logic; |
|
br : out std_logic; |
jbr : out std_logic; |
|
ext_addr : out std_logic_vector(EXTA_WIDTH-1 downto 0); |
rd, wr : out std_logic; |
|
dir : out std_logic_vector(ram_width-1 downto 0); |
|
sel_sub : out std_logic; -- 0..add, 1..sub |
sel_amux : out std_logic; -- 0..sum, 1..lmux |
ena_a : out std_logic; -- 1..store new value |
sel_bmux : out std_logic; -- 0..a, 1..mem |
sel_log : out std_logic_vector(1 downto 0); -- pop/st, and, or, xor |
sel_shf : out std_logic_vector(1 downto 0); -- sr, sl, sra, (sr) |
sel_lmux : out std_logic_vector(2 downto 0); -- log, shl, mem, io, reg |
sel_imux : out std_logic_vector(1 downto 0); -- java opds |
sel_rmux : out std_logic_vector(1 downto 0); -- sp, vp, jpc |
sel_smux : out std_logic_vector(1 downto 0); -- sp, a, sp-1, sp+1 |
|
sel_mmux : out std_logic; -- 0..a, 1..b |
sel_rda : out std_logic_vector(2 downto 0); -- |
sel_wra : out std_logic_vector(2 downto 0); -- |
|
wr_ena : out std_logic; |
|
ena_b : out std_logic; |
ena_vp : out std_logic; |
ena_jpc : out std_logic; |
ena_ar : out std_logic |
); |
end component; |
|
-- |
-- Signals |
-- |
|
-- |
-- (bc)fetch connections |
-- |
signal br : std_logic; |
signal jbr : std_logic; |
|
signal jfetch : std_logic; |
signal jopdfetch : std_logic; |
|
signal jpaddr : std_logic_vector(pc_width-1 downto 0); |
|
signal opd : std_logic_vector(15 downto 0); |
signal jpc_out : std_logic_vector(jpc_width downto 0); |
signal instr : std_logic_vector(i_width-1 downto 0); |
signal ena_jpc : std_logic; |
|
-- |
-- stack connections |
-- |
signal dir : std_logic_vector(ram_width-1 downto 0); |
|
signal sel_sub : std_logic; -- 0..add, 1..sub |
signal sel_amux : std_logic; -- 0..sum, 1..lmux |
signal ena_a : std_logic; -- 1..store new value |
signal sel_bmux : std_logic; -- 0..a, 1..mem |
signal sel_log : std_logic_vector(1 downto 0); -- ld, and, or, xor |
signal sel_shf : std_logic_vector(1 downto 0); -- sr, sl, sra, (sr) |
signal sel_lmux : std_logic_vector(2 downto 0); -- log, shl, mem, io, reg |
signal sel_imux : std_logic_vector(1 downto 0); -- java opds |
signal sel_rmux : std_logic_vector(1 downto 0); -- sp, vp, jpc |
signal sel_smux : std_logic_vector(1 downto 0); -- sp, a, sp-1, sp+1 |
|
signal sel_mmux : std_logic; -- 0..a, 1..b |
signal sel_rda : std_logic_vector(2 downto 0); -- |
signal sel_wra : std_logic_vector(2 downto 0); -- |
|
signal wr_ena : std_logic; |
|
signal ena_b : std_logic; |
signal ena_vp : std_logic; |
signal ena_ar : std_logic; |
|
signal stk_zf : std_logic; |
signal stk_nf : std_logic; |
signal stk_eq : std_logic; |
signal stk_lt : std_logic; |
signal stk_aout : std_logic_vector(width-1 downto 0); |
signal stk_bout : std_logic_vector(width-1 downto 0); |
|
begin |
|
cmp_bcf: bcfetch generic map(jpc_width, pc_width) |
port map (clk, reset, jpc_out, stk_aout, ena_jpc, |
jbc_addr, jbc_data, |
jfetch, jopdfetch, |
stk_zf, stk_nf, stk_eq, stk_lt, jbr, |
irq_in, irq_out, |
jpaddr, opd); |
|
cmp_fch: fetch generic map (pc_width, i_width) |
port map (clk, reset, jfetch, jopdfetch, |
br, bsy, jpaddr, instr); |
|
cmp_stk: stack generic map (width, jpc_width) |
port map (clk, reset, din, dir, opd, jpc_out, |
sel_sub, sel_amux, ena_a, |
sel_bmux, sel_log, sel_shf, sel_lmux, sel_imux, sel_rmux, sel_smux, |
sel_mmux, sel_rda, sel_wra, |
wr_ena, ena_b, ena_vp, ena_ar, |
sp_ov, |
stk_zf, stk_nf, stk_eq, stk_lt, stk_aout, stk_bout); |
|
cmp_dec: decode generic map (i_width) |
port map (clk, reset, instr, stk_zf, stk_nf, stk_eq, stk_lt, |
br, jbr, |
ext_addr, rd, wr, |
dir, |
sel_sub, sel_amux, ena_a, |
sel_bmux, sel_log, sel_shf, sel_lmux, sel_imux, sel_rmux, sel_smux, |
sel_mmux, sel_rda, sel_wra, |
wr_ena, ena_b, ena_vp, ena_jpc, ena_ar); |
|
aout <= stk_aout; |
bout <= stk_bout; |
|
end rtl; |
/fetch.vhd
0,0 → 1,183
-- |
-- |
-- 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/>. |
-- |
|
|
-- |
-- fetch.vhd |
-- |
-- jop instrcution fetch and branch |
-- |
-- |
-- resources on ACEX1K30-3 |
-- |
-- 132 LCs, max ca. 50 MHz |
-- |
-- todo: |
-- 5 stage pipeline (jtbl/rom) |
-- relativ address for jp, br |
-- load pc instead of addres mux befor rom! |
-- |
-- 2001-07-04 first version |
-- 2001-07-18 component pc_inc in own file for Xilinx |
-- 2001-10-24 added 2 delays for br address (address is now in br opcode!) |
-- 2001-10-28 ldjpc, stjpc |
-- 2001-10-31 stbc (write content of jbc) |
-- 2001-11-13 added jtbl (jtbl and rom in one pipline stage!) |
-- 2001-11-14 change jbc to 1024 bytes |
-- 2001-11-16 split to fetch and bcfetch |
-- 2001-12-06 ir from decode to rom, (one brdly removed) |
-- mux befor rom removed, unregistered jfetch conrols imput to |
-- pc, jpaddr unregistered! |
-- 2001-12-07 branch relativ |
-- 2001-12-08 use table for branch offsets |
-- 2001-12-08 instruction set changed to 8 bit, pc to 10 bits |
-- 2002-12-02 wait instruction for memory |
-- 2003-08-15 move bcfetch to core |
-- 2004-04-06 nxt and opd are in rom. rom address from jpc_mux and with |
-- positiv edge rdaddr. unregistered output in rom. |
-- 2004-10-08 moved bsy/pcwait from decode to fetch |
-- |
-- |
|
|
library ieee; |
use ieee.std_logic_1164.all; |
use ieee.numeric_std.all; |
|
entity fetch is |
|
generic ( |
pc_width : integer; -- address bits of internal instruction rom |
i_width : integer -- instruction width |
); |
port ( |
clk, reset : in std_logic; |
|
nxt, opd : out std_logic; -- jfetch and jopdfetch from table |
|
br : in std_logic; |
bsy : in std_logic; -- direct from the memory module |
jpaddr : in std_logic_vector(pc_width-1 downto 0); |
|
dout : out std_logic_vector(i_width-1 downto 0) -- internal instruction (rom) |
); |
end fetch; |
|
architecture rtl of fetch is |
|
-- |
-- rom component (use technology specific vhdl-file (arom/xrom)) |
-- or generic rom.vhd |
-- |
-- rom registered address, unregisterd out |
-- |
component rom is |
generic (width : integer; addr_width : integer); |
port ( |
clk : in std_logic; |
|
address : in std_logic_vector(pc_width-1 downto 0); |
|
q : out std_logic_vector(i_width+1 downto 0) |
); |
end component; |
-- |
-- offsets for relativ branches. |
-- |
component offtbl is |
port ( |
idx : in std_logic_vector(4 downto 0); |
q : out std_logic_vector(pc_width-1 downto 0) |
); |
end component; |
|
signal pc_mux : std_logic_vector(pc_width-1 downto 0); |
signal pc_inc : std_logic_vector(pc_width-1 downto 0); |
signal pc : std_logic_vector(pc_width-1 downto 0); |
signal brdly : std_logic_vector(pc_width-1 downto 0); |
|
signal off : std_logic_vector(pc_width-1 downto 0); |
|
signal jfetch : std_logic; -- fetch next byte code as opcode |
signal jopdfetch : std_logic; -- fetch next byte code as operand |
|
signal rom_data : std_logic_vector(i_width+1 downto 0); -- output from ROM |
signal ir : std_logic_vector(i_width-1 downto 0); -- instruction register |
signal pcwait : std_logic; |
|
begin |
|
|
-- |
-- pc_mux is 1 during reset! |
-- => first instruction from ROM gets NEVER executed. |
-- |
cmp_rom: rom generic map (i_width+2, pc_width) port map(clk, pc_mux, rom_data); |
jfetch <= rom_data(9); |
jopdfetch <= rom_data(8); |
|
cmp_off: offtbl port map(ir(4 downto 0), off); |
|
dout <= ir; |
nxt <= jfetch; |
opd <= jopdfetch; |
|
process(clk) |
begin |
if rising_edge(clk) then -- we don't need a reset |
ir <= rom_data(7 downto 0); -- better read (second) instruction from room |
pcwait <= '0'; |
-- decode wait instruction from unregistered rom |
if (rom_data(7 downto 0)="10000001") then -- wait instuction |
pcwait <= '1'; |
end if; |
end if; |
end process; |
|
process(clk, reset, pc, off) |
|
begin |
if (reset='1') then |
pc <= std_logic_vector(to_unsigned(0, pc_width)); |
brdly <= std_logic_vector(to_unsigned(0, pc_width)); |
elsif rising_edge(clk) then |
brdly <= std_logic_vector(unsigned(pc) + unsigned(off)); |
pc <= pc_mux; |
end if; |
end process; |
|
-- bsy is too late to register pcwait and bsy |
pc_inc <= std_logic_vector(to_unsigned(0, pc_width-1)) & not (pcwait and bsy); |
|
process(jfetch, br, jpaddr, brdly, pc, pc_inc) |
begin |
if (jfetch='1') then |
pc_mux <= jpaddr; |
else |
if (br='1') then |
pc_mux <= brdly; |
else |
pc_mux <= std_logic_vector(unsigned(pc) + unsigned(pc_inc)); |
end if; |
end if; |
end process; |
|
end rtl; |
|
/jop_config_ml401.vhd
0,0 → 1,42
-- |
-- |
-- 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/>. |
-- |
|
|
-- |
-- jop_config_ml401.vhd |
-- |
-- package for ML401 definitions |
-- |
|
library ieee; |
use ieee.std_logic_1164.all; |
|
package jop_config is |
|
constant clk_freq : integer := 100000000;--/2; |
|
-- constant for on-chip memory |
constant ram_width : integer := 8; -- address bits of internal ram (sp,...) |
|
end jop_config; |
|
package body jop_config is |
|
end jop_config; |
/xv4ram_block.vhd
0,0 → 1,222
-- |
-- xv4ram_block.vhd |
-- |
-- Generated by BlockGen |
-- Jan 30, 2009 11:29:28 AM |
-- |
-- This module will synthesize on Spartan3 and Virtex2/2Pro/2ProX devices. |
-- |
|
library IEEE; |
use IEEE.std_logic_1164.all; |
use IEEE.std_logic_arith.all; |
use IEEE.std_logic_unsigned.all; |
library unisim; |
use unisim.vcomponents.all; |
|
entity xram_block is |
port ( |
a_rst : in std_logic; |
a_clk : in std_logic; |
a_en : in std_logic; |
a_wr : in std_logic; |
a_addr : in std_logic_vector(7 downto 0); |
a_din : in std_logic_vector(31 downto 0); |
a_dout : out std_logic_vector(31 downto 0); |
b_rst : in std_logic; |
b_clk : in std_logic; |
b_en : in std_logic; |
b_wr : in std_logic; |
b_addr : in std_logic_vector(7 downto 0); |
b_din : in std_logic_vector(31 downto 0); |
b_dout : out std_logic_vector(31 downto 0) |
); |
end xram_block; |
|
architecture rtl of xram_block is |
|
component RAMB16_S36_S36 |
port ( |
DIA : in std_logic_vector (31 downto 0); |
DIB : in std_logic_vector (31 downto 0); |
ENA : in std_logic; |
ENB : in std_logic; |
WEA : in std_logic; |
WEB : in std_logic; |
SSRA : in std_logic; |
SSRB : in std_logic; |
DIPA : in std_logic_vector (3 downto 0); |
DIPB : in std_logic_vector (3 downto 0); |
DOPA : out std_logic_vector (3 downto 0); |
DOPB : out std_logic_vector (3 downto 0); |
CLKA : in std_logic; |
CLKB : in std_logic; |
ADDRA : in std_logic_vector (8 downto 0); |
ADDRB : in std_logic_vector (8 downto 0); |
DOA : out std_logic_vector (31 downto 0); |
DOB : out std_logic_vector (31 downto 0) |
); |
end component; |
|
attribute INIT: string; |
attribute INIT_00: string; |
attribute INIT_01: string; |
attribute INIT_02: string; |
attribute INIT_03: string; |
attribute INIT_04: string; |
attribute INIT_05: string; |
attribute INIT_06: string; |
attribute INIT_07: string; |
attribute INIT_08: string; |
attribute INIT_09: string; |
attribute INIT_0a: string; |
attribute INIT_0b: string; |
attribute INIT_0c: string; |
attribute INIT_0d: string; |
attribute INIT_0e: string; |
attribute INIT_0f: string; |
attribute INIT_10: string; |
attribute INIT_11: string; |
attribute INIT_12: string; |
attribute INIT_13: string; |
attribute INIT_14: string; |
attribute INIT_15: string; |
attribute INIT_16: string; |
attribute INIT_17: string; |
attribute INIT_18: string; |
attribute INIT_19: string; |
attribute INIT_1a: string; |
attribute INIT_1b: string; |
attribute INIT_1c: string; |
attribute INIT_1d: string; |
attribute INIT_1e: string; |
attribute INIT_1f: string; |
attribute INIT_20: string; |
attribute INIT_21: string; |
attribute INIT_22: string; |
attribute INIT_23: string; |
attribute INIT_24: string; |
attribute INIT_25: string; |
attribute INIT_26: string; |
attribute INIT_27: string; |
attribute INIT_28: string; |
attribute INIT_29: string; |
attribute INIT_2a: string; |
attribute INIT_2b: string; |
attribute INIT_2c: string; |
attribute INIT_2d: string; |
attribute INIT_2e: string; |
attribute INIT_2f: string; |
attribute INIT_30: string; |
attribute INIT_31: string; |
attribute INIT_32: string; |
attribute INIT_33: string; |
attribute INIT_34: string; |
attribute INIT_35: string; |
attribute INIT_36: string; |
attribute INIT_37: string; |
attribute INIT_38: string; |
attribute INIT_39: string; |
attribute INIT_3a: string; |
attribute INIT_3b: string; |
attribute INIT_3c: string; |
attribute INIT_3d: string; |
attribute INIT_3e: string; |
attribute INIT_3f: string; |
|
attribute INIT_00 of cmp_ram_0: label is "0000000000000000000000000000000000000000000000000000000000000000"; |
attribute INIT_01 of cmp_ram_0: label is "0000000000000000000000000000000000000000000000000000000000000000"; |
attribute INIT_02 of cmp_ram_0: label is "1234567800000000000000000000000000000000000000000000000000000000"; |
attribute INIT_03 of cmp_ram_0: label is "1234567812345678123456781234567812345678123456781234567812345678"; |
attribute INIT_04 of cmp_ram_0: label is "ffffff9100000002ffffff900000000400000000ffffff87ffffff8600000040"; |
attribute INIT_05 of cmp_ram_0: label is "ffffff80000000ff0000ffff0000000500000003ffffffff0000000100000008"; |
attribute INIT_06 of cmp_ram_0: label is "12345678123456781234567800000006800000000000001ffffffffeffffff85"; |
attribute INIT_07 of cmp_ram_0: label is "0000000001326a3a123456781234567812345678123456781234567812345678"; |
attribute INIT_08 of cmp_ram_0: label is "1234567812345678123456781234567812345678123456781234567812345678"; |
attribute INIT_09 of cmp_ram_0: label is "1234567812345678123456781234567812345678123456781234567812345678"; |
attribute INIT_0a of cmp_ram_0: label is "1234567812345678123456781234567812345678123456781234567812345678"; |
attribute INIT_0b of cmp_ram_0: label is "1234567812345678123456781234567812345678123456781234567812345678"; |
attribute INIT_0c of cmp_ram_0: label is "1234567812345678123456781234567812345678123456781234567812345678"; |
attribute INIT_0d of cmp_ram_0: label is "1234567812345678123456781234567812345678123456781234567812345678"; |
attribute INIT_0e of cmp_ram_0: label is "1234567812345678123456781234567812345678123456781234567812345678"; |
attribute INIT_0f of cmp_ram_0: label is "1234567812345678123456781234567812345678123456781234567812345678"; |
attribute INIT_10 of cmp_ram_0: label is "1234567812345678123456781234567812345678123456781234567812345678"; |
attribute INIT_11 of cmp_ram_0: label is "1234567812345678123456781234567812345678123456781234567812345678"; |
attribute INIT_12 of cmp_ram_0: label is "1234567812345678123456781234567812345678123456781234567812345678"; |
attribute INIT_13 of cmp_ram_0: label is "1234567812345678123456781234567812345678123456781234567812345678"; |
attribute INIT_14 of cmp_ram_0: label is "1234567812345678123456781234567812345678123456781234567812345678"; |
attribute INIT_15 of cmp_ram_0: label is "1234567812345678123456781234567812345678123456781234567812345678"; |
attribute INIT_16 of cmp_ram_0: label is "1234567812345678123456781234567812345678123456781234567812345678"; |
attribute INIT_17 of cmp_ram_0: label is "1234567812345678123456781234567812345678123456781234567812345678"; |
attribute INIT_18 of cmp_ram_0: label is "1234567812345678123456781234567812345678123456781234567812345678"; |
attribute INIT_19 of cmp_ram_0: label is "1234567812345678123456781234567812345678123456781234567812345678"; |
attribute INIT_1a of cmp_ram_0: label is "1234567812345678123456781234567812345678123456781234567812345678"; |
attribute INIT_1b of cmp_ram_0: label is "1234567812345678123456781234567812345678123456781234567812345678"; |
attribute INIT_1c of cmp_ram_0: label is "1234567812345678123456781234567812345678123456781234567812345678"; |
attribute INIT_1d of cmp_ram_0: label is "1234567812345678123456781234567812345678123456781234567812345678"; |
attribute INIT_1e of cmp_ram_0: label is "1234567812345678123456781234567812345678123456781234567812345678"; |
attribute INIT_1f of cmp_ram_0: label is "1234567812345678123456781234567812345678123456781234567812345678"; |
attribute INIT_20 of cmp_ram_0: label is "0000000000000000000000000000000000000000000000000000000000000000"; |
attribute INIT_21 of cmp_ram_0: label is "0000000000000000000000000000000000000000000000000000000000000000"; |
attribute INIT_22 of cmp_ram_0: label is "0000000000000000000000000000000000000000000000000000000000000000"; |
attribute INIT_23 of cmp_ram_0: label is "0000000000000000000000000000000000000000000000000000000000000000"; |
attribute INIT_24 of cmp_ram_0: label is "0000000000000000000000000000000000000000000000000000000000000000"; |
attribute INIT_25 of cmp_ram_0: label is "0000000000000000000000000000000000000000000000000000000000000000"; |
attribute INIT_26 of cmp_ram_0: label is "0000000000000000000000000000000000000000000000000000000000000000"; |
attribute INIT_27 of cmp_ram_0: label is "0000000000000000000000000000000000000000000000000000000000000000"; |
attribute INIT_28 of cmp_ram_0: label is "0000000000000000000000000000000000000000000000000000000000000000"; |
attribute INIT_29 of cmp_ram_0: label is "0000000000000000000000000000000000000000000000000000000000000000"; |
attribute INIT_2a of cmp_ram_0: label is "0000000000000000000000000000000000000000000000000000000000000000"; |
attribute INIT_2b of cmp_ram_0: label is "0000000000000000000000000000000000000000000000000000000000000000"; |
attribute INIT_2c of cmp_ram_0: label is "0000000000000000000000000000000000000000000000000000000000000000"; |
attribute INIT_2d of cmp_ram_0: label is "0000000000000000000000000000000000000000000000000000000000000000"; |
attribute INIT_2e of cmp_ram_0: label is "0000000000000000000000000000000000000000000000000000000000000000"; |
attribute INIT_2f of cmp_ram_0: label is "0000000000000000000000000000000000000000000000000000000000000000"; |
attribute INIT_30 of cmp_ram_0: label is "0000000000000000000000000000000000000000000000000000000000000000"; |
attribute INIT_31 of cmp_ram_0: label is "0000000000000000000000000000000000000000000000000000000000000000"; |
attribute INIT_32 of cmp_ram_0: label is "0000000000000000000000000000000000000000000000000000000000000000"; |
attribute INIT_33 of cmp_ram_0: label is "0000000000000000000000000000000000000000000000000000000000000000"; |
attribute INIT_34 of cmp_ram_0: label is "0000000000000000000000000000000000000000000000000000000000000000"; |
attribute INIT_35 of cmp_ram_0: label is "0000000000000000000000000000000000000000000000000000000000000000"; |
attribute INIT_36 of cmp_ram_0: label is "0000000000000000000000000000000000000000000000000000000000000000"; |
attribute INIT_37 of cmp_ram_0: label is "0000000000000000000000000000000000000000000000000000000000000000"; |
attribute INIT_38 of cmp_ram_0: label is "0000000000000000000000000000000000000000000000000000000000000000"; |
attribute INIT_39 of cmp_ram_0: label is "0000000000000000000000000000000000000000000000000000000000000000"; |
attribute INIT_3a of cmp_ram_0: label is "0000000000000000000000000000000000000000000000000000000000000000"; |
attribute INIT_3b of cmp_ram_0: label is "0000000000000000000000000000000000000000000000000000000000000000"; |
attribute INIT_3c of cmp_ram_0: label is "0000000000000000000000000000000000000000000000000000000000000000"; |
attribute INIT_3d of cmp_ram_0: label is "0000000000000000000000000000000000000000000000000000000000000000"; |
attribute INIT_3e of cmp_ram_0: label is "0000000000000000000000000000000000000000000000000000000000000000"; |
attribute INIT_3f of cmp_ram_0: label is "0000000000000000000000000000000000000000000000000000000000000000"; |
|
signal p_a_addr : std_logic_vector (8 downto 0); |
signal p_b_addr : std_logic_vector (8 downto 0); |
|
begin |
|
p_a_addr <= "0" & a_addr; |
p_b_addr <= "0" & b_addr; |
|
cmp_ram_0 : RAMB16_S36_S36 |
port map ( |
WEA => a_wr, |
WEB => b_wr, |
ENA => a_en, |
ENB => b_en, |
SSRA => a_rst, |
SSRB => b_rst, |
DIPA => "0000", |
DIPB => "0000", |
DOPA => open, |
DOPB => open, |
CLKA => a_clk, |
CLKB => b_clk, |
DIA => a_din(31 downto 0), |
ADDRA => p_a_addr, |
DOA => a_dout(31 downto 0), |
DIB => b_din(31 downto 0), |
ADDRB => p_b_addr, |
DOB => b_dout(31 downto 0) |
); |
|
end rtl; |
/xs3_jbc.vhd
0,0 → 1,128
-- |
-- |
-- 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/>. |
-- |
|
|
-- |
-- xs3_jbc.vhd |
-- |
-- bytecode memory/cache for JOP |
-- Version for Xilinx Spartan-3 |
-- |
-- address, data in are registered |
-- data out is unregistered |
-- |
-- |
-- Changes: |
-- 2003-08-14 load start address with jpc_wr and do autoincrement |
-- load 32 bit data and do the 4 byte writes serial |
-- 2005-02-17 extracted again from mem32.vhd |
-- 2005-05-03 address width is jpc_width |
-- 2005-11-24 adapted for S3 |
-- |
-- |
|
library ieee; |
use ieee.std_logic_1164.all; |
Library UNISIM; |
use UNISIM.vcomponents.all; |
|
entity jbc is |
generic (jpc_width : integer); |
port ( |
clk : in std_logic; |
data : in std_logic_vector(31 downto 0); |
rd_addr : in std_logic_vector(jpc_width-1 downto 0); |
wr_addr : in std_logic_vector(jpc_width-3 downto 0); |
wr_en : in std_logic; |
q : out std_logic_vector(7 downto 0) |
); |
end jbc; |
|
-- |
-- registered wraddress, wren |
-- registered din |
-- registered rdaddress |
-- unregistered dout |
-- |
architecture rtl of jbc is |
|
|
----- Component RAMB16_S9_S36 ----- |
component RAMB16_S9_S36 |
-- |
generic ( |
WRITE_MODE_A : string := "WRITE_FIRST"; |
WRITE_MODE_B : string := "WRITE_FIRST"; |
INIT_A : bit_vector := X"000"; |
SRVAL_A : bit_vector := X"000"; |
|
INIT_B : bit_vector := X"000000000"; |
SRVAL_B : bit_vector := X"000000000" |
); |
-- |
port (DIA : in STD_LOGIC_VECTOR (7 downto 0); |
DIB : in STD_LOGIC_VECTOR (31 downto 0); |
DIPA : in STD_LOGIC_VECTOR (0 downto 0); |
DIPB : in STD_LOGIC_VECTOR (3 downto 0); |
ENA : in STD_logic; |
ENB : in STD_logic; |
WEA : in STD_logic; |
WEB : in STD_logic; |
SSRA : in STD_logic; |
SSRB : in STD_logic; |
CLKA : in STD_logic; |
CLKB : in STD_logic; |
ADDRA : in STD_LOGIC_VECTOR (10 downto 0); |
ADDRB : in STD_LOGIC_VECTOR (8 downto 0); |
DOA : out STD_LOGIC_VECTOR (7 downto 0); |
DOB : out STD_LOGIC_VECTOR (31 downto 0); |
DOPA : out STD_LOGIC_VECTOR (0 downto 0); |
DOPB : out STD_LOGIC_VECTOR (3 downto 0) |
); |
|
end component; |
|
begin |
-- the block ram is 2KB |
assert jpc_width=11 report "Xilinx jbc is fixed to 2KB - use jbc_width of 11"; |
|
cmp_jbc : RAMB16_S9_S36 |
port map ( |
DIA => "00000000", |
DIB => data, |
DIPA => "0", |
DIPB => "0000", |
ENA => '1', |
ENB => '1', |
WEA => '0', |
WEB => wr_en, |
SSRA => '0', |
SSRB => '0', |
CLKA => clk, |
CLKB => clk, |
ADDRA => rd_addr, |
ADDRB => wr_addr, |
DOA => q, |
DOB => open, |
DOPA => open, |
DOPB => open |
); |
|
end rtl; |
/jtbl.vhd
0,0 → 1,219
-- |
-- jtbl.vhd |
-- |
-- jump table for java bc to jvm address |
-- |
-- DONT edit this file! |
-- generated by Jopa.java |
-- |
|
library ieee; |
use ieee.std_logic_1164.all; |
use ieee.std_logic_arith.all; |
use ieee.std_logic_unsigned.all; |
|
entity jtbl is |
port ( |
bcode : in std_logic_vector(7 downto 0); |
int_pend : in std_logic; |
exc_pend : in std_logic; |
q : out std_logic_vector(10 downto 0) |
); |
end jtbl; |
|
-- |
-- unregistered rdbcode |
-- unregistered dout |
-- |
architecture rtl of jtbl is |
|
signal addr : std_logic_vector(10 downto 0); |
|
begin |
|
process(bcode) begin |
|
case bcode is |
|
when "00000000" => addr <= "00001111010"; -- 007a nop |
when "00000010" => addr <= "00001111011"; -- 007b iconst_m1 |
when "00000001" => addr <= "00001111100"; -- 007c aconst_null |
when "00000011" => addr <= "00001111100"; -- 007c iconst_0 |
when "00000100" => addr <= "00001111101"; -- 007d iconst_1 |
when "00000101" => addr <= "00001111110"; -- 007e iconst_2 |
when "00000110" => addr <= "00001111111"; -- 007f iconst_3 |
when "00000111" => addr <= "00010000000"; -- 0080 iconst_4 |
when "00001000" => addr <= "00010000001"; -- 0081 iconst_5 |
when "00010000" => addr <= "00010000010"; -- 0082 bipush |
when "00010001" => addr <= "00010000100"; -- 0084 sipush |
when "00010010" => addr <= "00010000111"; -- 0087 ldc |
when "00010011" => addr <= "00010001110"; -- 008e ldc_w |
when "00011001" => addr <= "00010010110"; -- 0096 aload |
when "00010111" => addr <= "00010010110"; -- 0096 fload |
when "00010101" => addr <= "00010010110"; -- 0096 iload |
when "00101010" => addr <= "00010011000"; -- 0098 aload_0 |
when "00100010" => addr <= "00010011000"; -- 0098 fload_0 |
when "00011010" => addr <= "00010011000"; -- 0098 iload_0 |
when "00101011" => addr <= "00010011001"; -- 0099 aload_1 |
when "00100011" => addr <= "00010011001"; -- 0099 fload_1 |
when "00011011" => addr <= "00010011001"; -- 0099 iload_1 |
when "00101100" => addr <= "00010011010"; -- 009a aload_2 |
when "00100100" => addr <= "00010011010"; -- 009a fload_2 |
when "00011100" => addr <= "00010011010"; -- 009a iload_2 |
when "00101101" => addr <= "00010011011"; -- 009b aload_3 |
when "00100101" => addr <= "00010011011"; -- 009b fload_3 |
when "00011101" => addr <= "00010011011"; -- 009b iload_3 |
when "00111010" => addr <= "00010011100"; -- 009c astore |
when "00111000" => addr <= "00010011100"; -- 009c fstore |
when "00110110" => addr <= "00010011100"; -- 009c istore |
when "01001011" => addr <= "00010011110"; -- 009e astore_0 |
when "01000011" => addr <= "00010011110"; -- 009e fstore_0 |
when "00111011" => addr <= "00010011110"; -- 009e istore_0 |
when "01001100" => addr <= "00010011111"; -- 009f astore_1 |
when "01000100" => addr <= "00010011111"; -- 009f fstore_1 |
when "00111100" => addr <= "00010011111"; -- 009f istore_1 |
when "01001101" => addr <= "00010100000"; -- 00a0 astore_2 |
when "01000101" => addr <= "00010100000"; -- 00a0 fstore_2 |
when "00111101" => addr <= "00010100000"; -- 00a0 istore_2 |
when "01001110" => addr <= "00010100001"; -- 00a1 astore_3 |
when "01000110" => addr <= "00010100001"; -- 00a1 fstore_3 |
when "00111110" => addr <= "00010100001"; -- 00a1 istore_3 |
when "01010111" => addr <= "00010100010"; -- 00a2 pop |
when "01011000" => addr <= "00010100011"; -- 00a3 pop2 |
when "01011001" => addr <= "00010100101"; -- 00a5 dup |
when "01011010" => addr <= "00010100110"; -- 00a6 dup_x1 |
when "01011011" => addr <= "00010101011"; -- 00ab dup_x2 |
when "01011100" => addr <= "00010110010"; -- 00b2 dup2 |
when "01011101" => addr <= "00010111000"; -- 00b8 dup2_x1 |
when "01011110" => addr <= "00011000000"; -- 00c0 dup2_x2 |
when "01011111" => addr <= "00011001010"; -- 00ca swap |
when "01100000" => addr <= "00011001110"; -- 00ce iadd |
when "01100100" => addr <= "00011001111"; -- 00cf isub |
when "01110100" => addr <= "00011010000"; -- 00d0 ineg |
when "01111110" => addr <= "00011010100"; -- 00d4 iand |
when "10000000" => addr <= "00011010101"; -- 00d5 ior |
when "10000010" => addr <= "00011010110"; -- 00d6 ixor |
when "01111000" => addr <= "00011010111"; -- 00d7 ishl |
when "01111010" => addr <= "00011011000"; -- 00d8 ishr |
when "01111100" => addr <= "00011011001"; -- 00d9 iushr |
when "01101000" => addr <= "00011011010"; -- 00da imul |
when "10000100" => addr <= "00011100110"; -- 00e6 iinc |
when "10010010" => addr <= "00011101110"; -- 00ee i2c |
when "11000110" => addr <= "00011110000"; -- 00f0 ifnull |
when "11000111" => addr <= "00011110000"; -- 00f0 ifnonnull |
when "10011001" => addr <= "00011110000"; -- 00f0 ifeq |
when "10011010" => addr <= "00011110000"; -- 00f0 ifne |
when "10011011" => addr <= "00011110000"; -- 00f0 iflt |
when "10011100" => addr <= "00011110000"; -- 00f0 ifge |
when "10011101" => addr <= "00011110000"; -- 00f0 ifgt |
when "10011110" => addr <= "00011110000"; -- 00f0 ifle |
when "10100101" => addr <= "00011110100"; -- 00f4 if_acmpeq |
when "10100110" => addr <= "00011110100"; -- 00f4 if_acmpne |
when "10011111" => addr <= "00011110100"; -- 00f4 if_icmpeq |
when "10100000" => addr <= "00011110100"; -- 00f4 if_icmpne |
when "10100001" => addr <= "00011110100"; -- 00f4 if_icmplt |
when "10100010" => addr <= "00011110100"; -- 00f4 if_icmpge |
when "10100011" => addr <= "00011110100"; -- 00f4 if_icmpgt |
when "10100100" => addr <= "00011110100"; -- 00f4 if_icmple |
when "10100111" => addr <= "00011111000"; -- 00f8 goto |
when "11100000" => addr <= "00011111100"; -- 00fc getstatic_ref |
when "10110010" => addr <= "00011111100"; -- 00fc getstatic |
when "10110011" => addr <= "00100000011"; -- 0103 putstatic |
when "11100010" => addr <= "00100001011"; -- 010b getfield_ref |
when "10110100" => addr <= "00100001011"; -- 010b getfield |
when "11101001" => addr <= "00100001110"; -- 010e jopsys_getfield |
when "10110101" => addr <= "00100010011"; -- 0113 putfield |
when "11101010" => addr <= "00100010111"; -- 0117 jopsys_putfield |
when "10111100" => addr <= "00100011100"; -- 011c newarray |
when "10111110" => addr <= "00100110011"; -- 0133 arraylength |
when "01010100" => addr <= "00100111001"; -- 0139 bastore |
when "01010101" => addr <= "00100111001"; -- 0139 castore |
when "01010001" => addr <= "00100111001"; -- 0139 fastore |
when "01001111" => addr <= "00100111001"; -- 0139 iastore |
when "01010110" => addr <= "00100111001"; -- 0139 sastore |
when "00110010" => addr <= "00100111111"; -- 013f aaload |
when "00110011" => addr <= "00100111111"; -- 013f baload |
when "00110100" => addr <= "00100111111"; -- 013f caload |
when "00110000" => addr <= "00100111111"; -- 013f faload |
when "00101110" => addr <= "00100111111"; -- 013f iaload |
when "00110101" => addr <= "00100111111"; -- 013f saload |
when "11000010" => addr <= "00101000100"; -- 0144 monitorenter |
when "11000011" => addr <= "00101010110"; -- 0156 monitorexit |
when "10110111" => addr <= "00101101010"; -- 016a invokespecial |
when "10111000" => addr <= "00101101010"; -- 016a invokestatic |
when "11011110" => addr <= "00101110010"; -- 0172 jopsys_invoke |
when "10111001" => addr <= "00101110110"; -- 0176 invokeinterface |
when "11101100" => addr <= "00110101000"; -- 01a8 invokesuper |
when "10110110" => addr <= "00111010111"; -- 01d7 invokevirtual |
when "10110000" => addr <= "01000111001"; -- 0239 areturn |
when "10101110" => addr <= "01000111001"; -- 0239 freturn |
when "10101100" => addr <= "01000111001"; -- 0239 ireturn |
when "10101111" => addr <= "01001010000"; -- 0250 dreturn |
when "10101101" => addr <= "01001010000"; -- 0250 lreturn |
when "10110001" => addr <= "01001101001"; -- 0269 return |
when "00010100" => addr <= "01010010010"; -- 0292 ldc2_w |
when "00001001" => addr <= "01010100011"; -- 02a3 lconst_0 |
when "00001010" => addr <= "01010100101"; -- 02a5 lconst_1 |
when "10001000" => addr <= "01010100111"; -- 02a7 l2i |
when "00100110" => addr <= "01010101010"; -- 02aa dload_0 |
when "00011110" => addr <= "01010101010"; -- 02aa lload_0 |
when "00100111" => addr <= "01010101100"; -- 02ac dload_1 |
when "00011111" => addr <= "01010101100"; -- 02ac lload_1 |
when "00101000" => addr <= "01010101110"; -- 02ae dload_2 |
when "00100000" => addr <= "01010101110"; -- 02ae lload_2 |
when "00101001" => addr <= "01010110000"; -- 02b0 dload_3 |
when "00100001" => addr <= "01010110000"; -- 02b0 lload_3 |
when "00011000" => addr <= "01010111011"; -- 02bb dload |
when "00010110" => addr <= "01010111011"; -- 02bb lload |
when "01000111" => addr <= "01011000110"; -- 02c6 dstore_0 |
when "00111111" => addr <= "01011000110"; -- 02c6 lstore_0 |
when "01001000" => addr <= "01011001000"; -- 02c8 dstore_1 |
when "01000000" => addr <= "01011001000"; -- 02c8 lstore_1 |
when "01001001" => addr <= "01011001010"; -- 02ca dstore_2 |
when "01000001" => addr <= "01011001010"; -- 02ca lstore_2 |
when "01001010" => addr <= "01011001100"; -- 02cc dstore_3 |
when "01000010" => addr <= "01011001100"; -- 02cc lstore_3 |
when "00111001" => addr <= "01011010111"; -- 02d7 dstore |
when "00110111" => addr <= "01011010111"; -- 02d7 lstore |
when "11100100" => addr <= "01011100010"; -- 02e2 getstatic_long |
when "11100101" => addr <= "01011110010"; -- 02f2 putstatic_long |
when "11100110" => addr <= "01100000011"; -- 0303 getfield_long |
when "11100111" => addr <= "01100011101"; -- 031d putfield_long |
when "01010000" => addr <= "01100111010"; -- 033a lastore |
when "00101111" => addr <= "01101101010"; -- 036a laload |
when "10111011" => addr <= "01110111110"; -- 03be new |
when "10111101" => addr <= "01110111110"; -- 03be anewarray |
when "11000000" => addr <= "01110111110"; -- 03be checkcast |
when "11000001" => addr <= "01110111110"; -- 03be instanceof |
when "11100011" => addr <= "01111011011"; -- 03db putfield_ref |
when "11100001" => addr <= "01111011011"; -- 03db putstatic_ref |
when "11010001" => addr <= "01111110011"; -- 03f3 jopsys_rd |
when "11010011" => addr <= "01111110011"; -- 03f3 jopsys_rdmem |
when "11010010" => addr <= "01111110111"; -- 03f7 jopsys_wr |
when "11010100" => addr <= "01111110111"; -- 03f7 jopsys_wrmem |
when "11010101" => addr <= "01111111100"; -- 03fc jopsys_rdint |
when "11010110" => addr <= "01111111111"; -- 03ff jopsys_wrint |
when "11010111" => addr <= "10000000010"; -- 0402 jopsys_getsp |
when "11011000" => addr <= "10000000101"; -- 0405 jopsys_setsp |
when "11011001" => addr <= "10000001001"; -- 0409 jopsys_getvp |
when "11011010" => addr <= "10000001010"; -- 040a jopsys_setvp |
when "11011011" => addr <= "10000001100"; -- 040c jopsys_int2ext |
when "11011100" => addr <= "10000100111"; -- 0427 jopsys_ext2int |
when "11101000" => addr <= "10001000011"; -- 0443 jopsys_memcpy |
when "11011101" => addr <= "10001001000"; -- 0448 jopsys_nop |
|
when others => addr <= "01110101011"; -- 03ab sys_noim |
end case; |
end process; |
|
process(int_pend, exc_pend, addr) begin |
|
q <= addr; |
if exc_pend='1' then |
q <= "01110011111"; -- 039f sys_exc |
elsif int_pend='1' then |
q <= "01110010101"; -- 0395 sys_int |
end if; |
end process; |
|
end rtl; |
/sc_sram32.vhd
0,0 → 1,287
-- |
-- |
-- 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_sram32.vhd |
-- |
-- SimpCon compliant external memory interface |
-- for 32-bit SRAM (e.g. Cyclone board, Spartan-3 Starter Kit) |
-- |
-- Connection between mem_sc and the external memory bus |
-- |
-- memory mapping |
-- |
-- 000000-x7ffff external SRAM (w mirror) max. 512 kW (4*4 MBit) |
-- |
-- RAM: 32 bit word |
-- |
-- |
-- 2005-11-22 first version |
-- 2007-03-17 changed SimpCon to records |
-- 2008-05-29 nwe on pos edge, additional wait state for write |
-- |
|
Library IEEE; |
use IEEE.std_logic_1164.all; |
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); |
|
port ( |
|
clk, reset : in std_logic; |
|
-- |
-- SimpCon memory interface |
-- |
sc_mem_out : in sc_out_type; |
sc_mem_in : out sc_in_type; |
|
-- memory interface |
|
ram_addr : out std_logic_vector(addr_bits-1 downto 0); |
ram_dout : out std_logic_vector(31 downto 0); |
ram_din : in std_logic_vector(31 downto 0); |
ram_dout_en : out std_logic; |
ram_ncs : out std_logic; |
ram_noe : out std_logic; |
ram_nwe : out std_logic |
|
); |
end sc_mem_if; |
|
architecture rtl of sc_mem_if is |
|
-- |
-- signals for mem interface |
-- |
type state_type is ( |
idl, rd1, rd2, |
wr1, wr2 |
); |
signal state : state_type; |
signal next_state : state_type; |
|
signal wait_state : unsigned(3 downto 0); |
signal cnt : unsigned(1 downto 0); |
|
signal dout_ena : std_logic; |
signal rd_data_ena : std_logic; |
|
signal ram_ws_wr : integer; |
|
begin |
|
ram_ws_wr <= ram_ws+1; -- additional wait state for SRAM |
|
assert SC_ADDR_SIZE>=addr_bits report "Too less address bits"; |
ram_dout_en <= dout_ena; |
|
sc_mem_in.rdy_cnt <= cnt; |
|
-- |
-- Register memory address, write data and read data |
-- |
process(clk, reset) |
begin |
if reset='1' then |
|
ram_addr <= (others => '0'); |
ram_dout <= (others => '0'); |
sc_mem_in.rd_data <= (others => '0'); |
|
elsif rising_edge(clk) then |
|
if sc_mem_out.rd='1' or sc_mem_out.wr='1' then |
ram_addr <= sc_mem_out.address(addr_bits-1 downto 0); |
end if; |
if sc_mem_out.wr='1' then |
ram_dout <= sc_mem_out.wr_data; |
end if; |
if rd_data_ena='1' then |
sc_mem_in.rd_data <= ram_din; |
end if; |
|
end if; |
end process; |
|
-- |
-- next state logic |
-- |
process(state, sc_mem_out.rd, sc_mem_out.wr, wait_state) |
|
begin |
|
next_state <= state; |
|
|
case state is |
|
when idl => |
if sc_mem_out.rd='1' then |
if ram_ws=0 then |
-- then we omit state rd1! |
next_state <= rd2; |
else |
next_state <= rd1; |
end if; |
elsif sc_mem_out.wr='1' then |
next_state <= wr1; |
end if; |
|
-- the WS state |
when rd1 => |
if wait_state=2 then |
next_state <= rd2; |
end if; |
|
-- last read state |
when rd2 => |
next_state <= idl; |
-- This should do to give us a pipeline |
-- level of 2 for read |
if sc_mem_out.rd='1' then |
if ram_ws=0 then |
-- then we omit state rd1! |
next_state <= rd2; |
else |
next_state <= rd1; |
end if; |
elsif sc_mem_out.wr='1' then |
next_state <= wr1; |
end if; |
|
-- the WS state |
when wr1 => |
if wait_state=2 then |
next_state <= wr2; |
end if; |
|
-- last write state |
when wr2 => |
next_state <= idl; |
|
end case; |
|
end process; |
|
-- |
-- state machine register |
-- output register |
-- |
process(clk, reset) |
|
begin |
if (reset='1') then |
state <= idl; |
dout_ena <= '0'; |
ram_ncs <= '1'; |
ram_noe <= '1'; |
rd_data_ena <= '0'; |
ram_nwe <= '1'; |
|
elsif rising_edge(clk) then |
|
state <= next_state; |
dout_ena <= '0'; |
ram_ncs <= '1'; |
ram_noe <= '1'; |
rd_data_ena <= '0'; |
ram_nwe <= '1'; |
|
case next_state is |
|
when idl => |
|
-- the wait state |
when rd1 => |
ram_ncs <= '0'; |
ram_noe <= '0'; |
|
-- last read state |
when rd2 => |
ram_ncs <= '0'; |
ram_noe <= '0'; |
rd_data_ena <= '1'; |
|
-- the WS state |
when wr1 => |
ram_nwe <= '0'; |
dout_ena <= '1'; |
ram_ncs <= '0'; |
|
-- last write state |
when wr2 => |
dout_ena <= '1'; |
ram_ncs <= '0'; |
|
end case; |
|
end if; |
end process; |
|
-- |
-- wait_state processing |
-- cs delay, dout enable |
-- |
process(clk, reset) |
begin |
if (reset='1') then |
wait_state <= (others => '1'); |
cnt <= "00"; |
elsif rising_edge(clk) then |
|
wait_state <= wait_state-1; |
|
cnt <= "11"; |
if next_state=idl then |
cnt <= "00"; |
-- if wait_state<4 then |
elsif wait_state(3 downto 2)="00" then |
cnt <= wait_state(1 downto 0)-1; |
end if; |
|
if sc_mem_out.rd='1' then |
wait_state <= to_unsigned(ram_ws+1, 4); |
if ram_ws<3 then |
cnt <= to_unsigned(ram_ws+1, 2); |
else |
cnt <= "11"; |
end if; |
end if; |
|
if sc_mem_out.wr='1' then |
wait_state <= to_unsigned(ram_ws_wr+1, 4); |
if ram_ws_wr<3 then |
cnt <= to_unsigned(ram_ws_wr+1, 2); |
else |
cnt <= "11"; |
end if; |
end if; |
|
end if; |
end process; |
|
end rtl; |
/rom.vhd
0,0 → 1,1147
-- |
-- rom.vhd |
-- |
-- generic VHDL version of ROM |
-- |
-- DONT edit this file! |
-- generated by Jopa.java |
-- |
|
library ieee; |
use ieee.std_logic_1164.all; |
use ieee.std_logic_arith.all; |
use ieee.std_logic_unsigned.all; |
|
entity rom is |
generic (width : integer; addr_width : integer); -- for compatibility |
port ( |
clk : in std_logic; |
address : in std_logic_vector(10 downto 0); |
q : out std_logic_vector(9 downto 0) |
); |
end rom; |
|
architecture rtl of rom is |
|
signal areg : std_logic_vector(10 downto 0); |
signal data : std_logic_vector(9 downto 0); |
|
begin |
|
process(clk) begin |
|
if rising_edge(clk) then |
areg <= address; |
end if; |
|
end process; |
|
q <= data; |
|
process(areg) begin |
|
case areg is |
|
when "00000000000" => data <= "0010000000"; -- TODO: comment |
when "00000000001" => data <= "0010000000"; -- TODO: comment |
when "00000000010" => data <= "0011000000"; -- TODO: comment |
when "00000000011" => data <= "0010000000"; -- TODO: comment |
when "00000000100" => data <= "0000011011"; -- TODO: comment |
when "00000000101" => data <= "0011000001"; -- TODO: comment |
when "00000000110" => data <= "0000001000"; -- TODO: comment |
when "00000000111" => data <= "0010000001"; -- TODO: comment |
when "00000001000" => data <= "0010000001"; -- TODO: comment |
when "00000001001" => data <= "0011100000"; -- TODO: comment |
when "00000001010" => data <= "0010000000"; -- TODO: comment |
when "00000001011" => data <= "0001000000"; -- TODO: comment |
when "00000001100" => data <= "0010000000"; -- TODO: comment |
when "00000001101" => data <= "0010000000"; -- TODO: comment |
when "00000001110" => data <= "0011000010"; -- TODO: comment |
when "00000001111" => data <= "0000001000"; -- TODO: comment |
when "00000010000" => data <= "0010000001"; -- TODO: comment |
when "00000010001" => data <= "0010000001"; -- TODO: comment |
when "00000010010" => data <= "0011100000"; -- TODO: comment |
when "00000010011" => data <= "0010000000"; -- TODO: comment |
when "00000010100" => data <= "0001000001"; -- TODO: comment |
when "00000010101" => data <= "0010000000"; -- TODO: comment |
when "00000010110" => data <= "0010000000"; -- TODO: comment |
when "00000010111" => data <= "0011000010"; -- TODO: comment |
when "00000011000" => data <= "0000001000"; -- TODO: comment |
when "00000011001" => data <= "0010000001"; -- TODO: comment |
when "00000011010" => data <= "0010000001"; -- TODO: comment |
when "00000011011" => data <= "0011100000"; -- TODO: comment |
when "00000011100" => data <= "0010000000"; -- TODO: comment |
when "00000011101" => data <= "0001100010"; -- TODO: comment |
when "00000011110" => data <= "0010000000"; -- TODO: comment |
when "00000011111" => data <= "0010000000"; -- TODO: comment |
when "00000100000" => data <= "0011000011"; -- TODO: comment |
when "00000100001" => data <= "0000100010"; -- TODO: comment |
when "00000100010" => data <= "0011000100"; -- TODO: comment |
when "00000100011" => data <= "0011000101"; -- TODO: comment |
when "00000100100" => data <= "0000001000"; -- TODO: comment |
when "00000100101" => data <= "0011000110"; -- TODO: comment |
when "00000100110" => data <= "0010000001"; -- TODO: comment |
when "00000100111" => data <= "0010000001"; -- TODO: comment |
when "00000101000" => data <= "0011100000"; -- TODO: comment |
when "00000101001" => data <= "0000000001"; -- TODO: comment |
when "00000101010" => data <= "0010000000"; -- TODO: comment |
when "00000101011" => data <= "0001000011"; -- TODO: comment |
when "00000101100" => data <= "0010000000"; -- TODO: comment |
when "00000101101" => data <= "0010000000"; -- TODO: comment |
when "00000101110" => data <= "0011000111"; -- TODO: comment |
when "00000101111" => data <= "0000001000"; -- TODO: comment |
when "00000110000" => data <= "0010000001"; -- TODO: comment |
when "00000110001" => data <= "0010000001"; -- TODO: comment |
when "00000110010" => data <= "0011100000"; -- TODO: comment |
when "00000110011" => data <= "0011000111"; -- TODO: comment |
when "00000110100" => data <= "0000000111"; -- TODO: comment |
when "00000110101" => data <= "0011111000"; -- TODO: comment |
when "00000110110" => data <= "0000001001"; -- TODO: comment |
when "00000110111" => data <= "0010000001"; -- TODO: comment |
when "00000111000" => data <= "0010000001"; -- TODO: comment |
when "00000111001" => data <= "0010101000"; -- TODO: comment |
when "00000111010" => data <= "0011001000"; -- TODO: comment |
when "00000111011" => data <= "0000011101"; -- TODO: comment |
when "00000111100" => data <= "0000000010"; -- TODO: comment |
when "00000111101" => data <= "0000101000"; -- TODO: comment |
when "00000111110" => data <= "0011001001"; -- TODO: comment |
when "00000111111" => data <= "0000000101"; -- TODO: comment |
when "00001000000" => data <= "0011111000"; -- TODO: comment |
when "00001000001" => data <= "0010000000"; -- TODO: comment |
when "00001000010" => data <= "0001100100"; -- TODO: comment |
when "00001000011" => data <= "0010000000"; -- TODO: comment |
when "00001000100" => data <= "0010000000"; -- TODO: comment |
when "00001000101" => data <= "0000000000"; -- TODO: comment |
when "00001000110" => data <= "0010100010"; -- TODO: comment |
when "00001000111" => data <= "0000000111"; -- TODO: comment |
when "00001001000" => data <= "0010101000"; -- TODO: comment |
when "00001001001" => data <= "0000001001"; -- TODO: comment |
when "00001001010" => data <= "0010000001"; -- TODO: comment |
when "00001001011" => data <= "0010000001"; -- TODO: comment |
when "00001001100" => data <= "0010100010"; -- TODO: comment |
when "00001001101" => data <= "0010000000"; -- TODO: comment |
when "00001001110" => data <= "0001100101"; -- TODO: comment |
when "00001001111" => data <= "0010000000"; -- TODO: comment |
when "00001010000" => data <= "0010000000"; -- TODO: comment |
when "00001010001" => data <= "0010101000"; -- TODO: comment |
when "00001010010" => data <= "0000100110"; -- TODO: comment |
when "00001010011" => data <= "0010100010"; -- TODO: comment |
when "00001010100" => data <= "0011001001"; -- TODO: comment |
when "00001010101" => data <= "0000000100"; -- TODO: comment |
when "00001010110" => data <= "0000100010"; -- TODO: comment |
when "00001010111" => data <= "0010100010"; -- TODO: comment |
when "00001011000" => data <= "0010100110"; -- TODO: comment |
when "00001011001" => data <= "0000000011"; -- TODO: comment |
when "00001011010" => data <= "0010000000"; -- TODO: comment |
when "00001011011" => data <= "0001100110"; -- TODO: comment |
when "00001011100" => data <= "0010000000"; -- TODO: comment |
when "00001011101" => data <= "0010000000"; -- TODO: comment |
when "00001011110" => data <= "0011001001"; -- TODO: comment |
when "00001011111" => data <= "0000001000"; -- TODO: comment |
when "00001100000" => data <= "0010000001"; -- TODO: comment |
when "00001100001" => data <= "0010000001"; -- TODO: comment |
when "00001100010" => data <= "0011100000"; -- TODO: comment |
when "00001100011" => data <= "0000100000"; -- TODO: comment |
when "00001100100" => data <= "0010100000"; -- TODO: comment |
when "00001100101" => data <= "0011001001"; -- TODO: comment |
when "00001100110" => data <= "0000000100"; -- TODO: comment |
when "00001100111" => data <= "0011111000"; -- TODO: comment |
when "00001101000" => data <= "0000001000"; -- TODO: comment |
when "00001101001" => data <= "0010000001"; -- TODO: comment |
when "00001101010" => data <= "0010000001"; -- TODO: comment |
when "00001101011" => data <= "0011100000"; -- TODO: comment |
when "00001101100" => data <= "0000100011"; -- TODO: comment |
when "00001101101" => data <= "0011001001"; -- TODO: comment |
when "00001101110" => data <= "0000000100"; -- TODO: comment |
when "00001101111" => data <= "0000001000"; -- TODO: comment |
when "00001110000" => data <= "0010000001"; -- TODO: comment |
when "00001110001" => data <= "0010000001"; -- TODO: comment |
when "00001110010" => data <= "0011100000"; -- TODO: comment |
when "00001110011" => data <= "0000100100"; -- TODO: comment |
when "00001110100" => data <= "0010100000"; -- TODO: comment |
when "00001110101" => data <= "0011001001"; -- TODO: comment |
when "00001110110" => data <= "0010000000"; -- TODO: comment |
when "00001110111" => data <= "0001100111"; -- TODO: comment |
when "00001111000" => data <= "0010000000"; -- TODO: comment |
when "00001111001" => data <= "0010000000"; -- TODO: comment |
when "00001111010" => data <= "1010000000"; -- TODO: comment |
when "00001111011" => data <= "1011001010"; -- TODO: comment |
when "00001111100" => data <= "1011000011"; -- TODO: comment |
when "00001111101" => data <= "1011001001"; -- TODO: comment |
when "00001111110" => data <= "1011000110"; -- TODO: comment |
when "00001111111" => data <= "1011001011"; -- TODO: comment |
when "00010000000" => data <= "1011000100"; -- TODO: comment |
when "00010000001" => data <= "1011001100"; -- TODO: comment |
when "00010000010" => data <= "0110000000"; -- TODO: comment |
when "00010000011" => data <= "1011110101"; -- TODO: comment |
when "00010000100" => data <= "0110000000"; -- TODO: comment |
when "00010000101" => data <= "0110000000"; -- TODO: comment |
when "00010000110" => data <= "1011110111"; -- TODO: comment |
when "00010000111" => data <= "0110100001"; -- TODO: comment |
when "00010001000" => data <= "0011110100"; -- TODO: comment |
when "00010001001" => data <= "0000000100"; -- TODO: comment |
when "00010001010" => data <= "0000001000"; -- TODO: comment |
when "00010001011" => data <= "0010000001"; -- TODO: comment |
when "00010001100" => data <= "0010000001"; -- TODO: comment |
when "00010001101" => data <= "1011100000"; -- TODO: comment |
when "00010001110" => data <= "0110100001"; -- TODO: comment |
when "00010001111" => data <= "0110000000"; -- TODO: comment |
when "00010010000" => data <= "0011110110"; -- TODO: comment |
when "00010010001" => data <= "0000000100"; -- TODO: comment |
when "00010010010" => data <= "0000001000"; -- TODO: comment |
when "00010010011" => data <= "0010000001"; -- TODO: comment |
when "00010010100" => data <= "0010000001"; -- TODO: comment |
when "00010010101" => data <= "1011100000"; -- TODO: comment |
when "00010010110" => data <= "0110000000"; -- TODO: comment |
when "00010010111" => data <= "1011101100"; -- TODO: comment |
when "00010011000" => data <= "1011101000"; -- TODO: comment |
when "00010011001" => data <= "1011101001"; -- TODO: comment |
when "00010011010" => data <= "1011101010"; -- TODO: comment |
when "00010011011" => data <= "1011101011"; -- TODO: comment |
when "00010011100" => data <= "0110000000"; -- TODO: comment |
when "00010011101" => data <= "1000010100"; -- TODO: comment |
when "00010011110" => data <= "1000010000"; -- TODO: comment |
when "00010011111" => data <= "1000010001"; -- TODO: comment |
when "00010100000" => data <= "1000010010"; -- TODO: comment |
when "00010100001" => data <= "1000010011"; -- TODO: comment |
when "00010100010" => data <= "1000000000"; -- TODO: comment |
when "00010100011" => data <= "0000000000"; -- TODO: comment |
when "00010100100" => data <= "1000000000"; -- TODO: comment |
when "00010100101" => data <= "1011111000"; -- TODO: comment |
when "00010100110" => data <= "0000100110"; -- TODO: comment |
when "00010100111" => data <= "0000100111"; -- TODO: comment |
when "00010101000" => data <= "0010100110"; -- TODO: comment |
when "00010101001" => data <= "0010100111"; -- TODO: comment |
when "00010101010" => data <= "1010100110"; -- TODO: comment |
when "00010101011" => data <= "0000100110"; -- TODO: comment |
when "00010101100" => data <= "0000100111"; -- TODO: comment |
when "00010101101" => data <= "0000101000"; -- TODO: comment |
when "00010101110" => data <= "0010100110"; -- TODO: comment |
when "00010101111" => data <= "0010101000"; -- TODO: comment |
when "00010110000" => data <= "0010100111"; -- TODO: comment |
when "00010110001" => data <= "1010100110"; -- TODO: comment |
when "00010110010" => data <= "0000100110"; -- TODO: comment |
when "00010110011" => data <= "0000100111"; -- TODO: comment |
when "00010110100" => data <= "0010100111"; -- TODO: comment |
when "00010110101" => data <= "0010100110"; -- TODO: comment |
when "00010110110" => data <= "0010100111"; -- TODO: comment |
when "00010110111" => data <= "1010100110"; -- TODO: comment |
when "00010111000" => data <= "0000100110"; -- TODO: comment |
when "00010111001" => data <= "0000100111"; -- TODO: comment |
when "00010111010" => data <= "0000101000"; -- TODO: comment |
when "00010111011" => data <= "0010100111"; -- TODO: comment |
when "00010111100" => data <= "0010100110"; -- TODO: comment |
when "00010111101" => data <= "0010101000"; -- TODO: comment |
when "00010111110" => data <= "0010100111"; -- TODO: comment |
when "00010111111" => data <= "1010100110"; -- TODO: comment |
when "00011000000" => data <= "0000100110"; -- TODO: comment |
when "00011000001" => data <= "0000100111"; -- TODO: comment |
when "00011000010" => data <= "0000101000"; -- TODO: comment |
when "00011000011" => data <= "0000101001"; -- TODO: comment |
when "00011000100" => data <= "0010100111"; -- TODO: comment |
when "00011000101" => data <= "0010100110"; -- TODO: comment |
when "00011000110" => data <= "0010101001"; -- TODO: comment |
when "00011000111" => data <= "0010101000"; -- TODO: comment |
when "00011001000" => data <= "0010100111"; -- TODO: comment |
when "00011001001" => data <= "1010100110"; -- TODO: comment |
when "00011001010" => data <= "0000100110"; -- TODO: comment |
when "00011001011" => data <= "0000100111"; -- TODO: comment |
when "00011001100" => data <= "0010100110"; -- TODO: comment |
when "00011001101" => data <= "1010100111"; -- TODO: comment |
when "00011001110" => data <= "1000000100"; -- TODO: comment |
when "00011001111" => data <= "1000000101"; -- TODO: comment |
when "00011010000" => data <= "0011001010"; -- TODO: comment |
when "00011010001" => data <= "0000000011"; -- TODO: comment |
when "00011010010" => data <= "0011001001"; -- TODO: comment |
when "00011010011" => data <= "1000000100"; -- TODO: comment |
when "00011010100" => data <= "1000000001"; -- TODO: comment |
when "00011010101" => data <= "1000000010"; -- TODO: comment |
when "00011010110" => data <= "1000000011"; -- TODO: comment |
when "00011010111" => data <= "1000011101"; -- TODO: comment |
when "00011011000" => data <= "1000011110"; -- TODO: comment |
when "00011011001" => data <= "1000011100"; -- TODO: comment |
when "00011011010" => data <= "0000000110"; -- TODO: comment |
when "00011011011" => data <= "0000000000"; -- TODO: comment |
when "00011011100" => data <= "0011000110"; -- TODO: comment |
when "00011011101" => data <= "0011001010"; -- TODO: comment |
when "00011011110" => data <= "0000000100"; -- TODO: comment |
when "00011011111" => data <= "0011111000"; -- TODO: comment |
when "00011100000" => data <= "0010000000"; -- TODO: comment |
when "00011100001" => data <= "0001101000"; -- TODO: comment |
when "00011100010" => data <= "0010000000"; -- TODO: comment |
when "00011100011" => data <= "0010000000"; -- TODO: comment |
when "00011100100" => data <= "0000000000"; -- TODO: comment |
when "00011100101" => data <= "1011100110"; -- TODO: comment |
when "00011100110" => data <= "0111110001"; -- TODO: comment |
when "00011100111" => data <= "0011110100"; -- TODO: comment |
when "00011101000" => data <= "0000000100"; -- TODO: comment |
when "00011101001" => data <= "0100011010"; -- TODO: comment |
when "00011101010" => data <= "0011110101"; -- TODO: comment |
when "00011101011" => data <= "0011101101"; -- TODO: comment |
when "00011101100" => data <= "0000000100"; -- TODO: comment |
when "00011101101" => data <= "1000010101"; -- TODO: comment |
when "00011101110" => data <= "0011001101"; -- TODO: comment |
when "00011101111" => data <= "1000000001"; -- TODO: comment |
when "00011110000" => data <= "0110000000"; -- TODO: comment |
when "00011110001" => data <= "0110000010"; -- TODO: comment |
when "00011110010" => data <= "0000000000"; -- TODO: comment |
when "00011110011" => data <= "1010000000"; -- TODO: comment |
when "00011110100" => data <= "0110000000"; -- TODO: comment |
when "00011110101" => data <= "0110000010"; -- TODO: comment |
when "00011110110" => data <= "0000000000"; -- TODO: comment |
when "00011110111" => data <= "1000000000"; -- TODO: comment |
when "00011111000" => data <= "0110000000"; -- TODO: comment |
when "00011111001" => data <= "0110000010"; -- TODO: comment |
when "00011111010" => data <= "0010000000"; -- TODO: comment |
when "00011111011" => data <= "1010000000"; -- TODO: comment |
when "00011111100" => data <= "0110000000"; -- TODO: comment |
when "00011111101" => data <= "0110000000"; -- TODO: comment |
when "00011111110" => data <= "0011110110"; -- TODO: comment |
when "00011111111" => data <= "0000001000"; -- TODO: comment |
when "00100000000" => data <= "0010000001"; -- TODO: comment |
when "00100000001" => data <= "0010000001"; -- TODO: comment |
when "00100000010" => data <= "1011100000"; -- TODO: comment |
when "00100000011" => data <= "0110000000"; -- TODO: comment |
when "00100000100" => data <= "0110000000"; -- TODO: comment |
when "00100000101" => data <= "0011110110"; -- TODO: comment |
when "00100000110" => data <= "0000000111"; -- TODO: comment |
when "00100000111" => data <= "0000001001"; -- TODO: comment |
when "00100001000" => data <= "0010000001"; -- TODO: comment |
when "00100001001" => data <= "0010000001"; -- TODO: comment |
when "00100001010" => data <= "1010000000"; -- TODO: comment |
when "00100001011" => data <= "0110000000"; -- TODO: comment |
when "00100001100" => data <= "0110000000"; -- TODO: comment |
when "00100001101" => data <= "0011110110"; -- TODO: comment |
when "00100001110" => data <= "0000001100"; -- TODO: comment |
when "00100001111" => data <= "0000000000"; -- TODO: comment |
when "00100010000" => data <= "0010000001"; -- TODO: comment |
when "00100010001" => data <= "0010000001"; -- TODO: comment |
when "00100010010" => data <= "1011100000"; -- TODO: comment |
when "00100010011" => data <= "0100100110"; -- TODO: comment |
when "00100010100" => data <= "0110000000"; -- TODO: comment |
when "00100010101" => data <= "0011110110"; -- TODO: comment |
when "00100010110" => data <= "0010100110"; -- TODO: comment |
when "00100010111" => data <= "0000001101"; -- TODO: comment |
when "00100011000" => data <= "0000000000"; -- TODO: comment |
when "00100011001" => data <= "0010000001"; -- TODO: comment |
when "00100011010" => data <= "0010000001"; -- TODO: comment |
when "00100011011" => data <= "1000000000"; -- TODO: comment |
when "00100011100" => data <= "0110000000"; -- TODO: comment |
when "00100011101" => data <= "0011110100"; -- TODO: comment |
when "00100011110" => data <= "0000100110"; -- TODO: comment |
when "00100011111" => data <= "0011110010"; -- TODO: comment |
when "00100100000" => data <= "0011000110"; -- TODO: comment |
when "00100100001" => data <= "0000000101"; -- TODO: comment |
when "00100100010" => data <= "0000011001"; -- TODO: comment |
when "00100100011" => data <= "0010000000"; -- TODO: comment |
when "00100100100" => data <= "0010000000"; -- TODO: comment |
when "00100100101" => data <= "0010100110"; -- TODO: comment |
when "00100100110" => data <= "0010100011"; -- TODO: comment |
when "00100100111" => data <= "0110000000"; -- TODO: comment |
when "00100101000" => data <= "0011110100"; -- TODO: comment |
when "00100101001" => data <= "0011001110"; -- TODO: comment |
when "00100101010" => data <= "0100000001"; -- TODO: comment |
when "00100101011" => data <= "0011111000"; -- TODO: comment |
when "00100101100" => data <= "0000000100"; -- TODO: comment |
when "00100101101" => data <= "0000000100"; -- TODO: comment |
when "00100101110" => data <= "0011001001"; -- TODO: comment |
when "00100101111" => data <= "0010000000"; -- TODO: comment |
when "00100110000" => data <= "0001101001"; -- TODO: comment |
when "00100110001" => data <= "0010000000"; -- TODO: comment |
when "00100110010" => data <= "0010000000"; -- TODO: comment |
when "00100110011" => data <= "0011001001"; -- TODO: comment |
when "00100110100" => data <= "0000000100"; -- TODO: comment |
when "00100110101" => data <= "0000001000"; -- TODO: comment |
when "00100110110" => data <= "0010000001"; -- TODO: comment |
when "00100110111" => data <= "0010000001"; -- TODO: comment |
when "00100111000" => data <= "1011100000"; -- TODO: comment |
when "00100111001" => data <= "0000001011"; -- TODO: comment |
when "00100111010" => data <= "0000000000"; -- TODO: comment |
when "00100111011" => data <= "0000000000"; -- TODO: comment |
when "00100111100" => data <= "0010000001"; -- TODO: comment |
when "00100111101" => data <= "0010000001"; -- TODO: comment |
when "00100111110" => data <= "1010000000"; -- TODO: comment |
when "00100111111" => data <= "0000001010"; -- TODO: comment |
when "00101000000" => data <= "0000000000"; -- TODO: comment |
when "00101000001" => data <= "0010000001"; -- TODO: comment |
when "00101000010" => data <= "0010000001"; -- TODO: comment |
when "00101000011" => data <= "1011100000"; -- TODO: comment |
when "00101000100" => data <= "0000000000"; -- TODO: comment |
when "00101000101" => data <= "0011001111"; -- TODO: comment |
when "00101000110" => data <= "0000000111"; -- TODO: comment |
when "00101000111" => data <= "0011000011"; -- TODO: comment |
when "00101001000" => data <= "0000001001"; -- TODO: comment |
when "00101001001" => data <= "0010100101"; -- TODO: comment |
when "00101001010" => data <= "0011001001"; -- TODO: comment |
when "00101001011" => data <= "0000000100"; -- TODO: comment |
when "00101001100" => data <= "0010000001"; -- TODO: comment |
when "00101001101" => data <= "0010000001"; -- TODO: comment |
when "00101001110" => data <= "0000100101"; -- TODO: comment |
when "00101001111" => data <= "0011010000"; -- TODO: comment |
when "00101010000" => data <= "0000000111"; -- TODO: comment |
when "00101010001" => data <= "0011001001"; -- TODO: comment |
when "00101010010" => data <= "0000001001"; -- TODO: comment |
when "00101010011" => data <= "0010000001"; -- TODO: comment |
when "00101010100" => data <= "0010000001"; -- TODO: comment |
when "00101010101" => data <= "1010000000"; -- TODO: comment |
when "00101010110" => data <= "0000000000"; -- TODO: comment |
when "00101010111" => data <= "0010100101"; -- TODO: comment |
when "00101011000" => data <= "0011001001"; -- TODO: comment |
when "00101011001" => data <= "0000000101"; -- TODO: comment |
when "00101011010" => data <= "0011111000"; -- TODO: comment |
when "00101011011" => data <= "0000100101"; -- TODO: comment |
when "00101011100" => data <= "0001101010"; -- TODO: comment |
when "00101011101" => data <= "0011010000"; -- TODO: comment |
when "00101011110" => data <= "0000000111"; -- TODO: comment |
when "00101011111" => data <= "0011000011"; -- TODO: comment |
when "00101100000" => data <= "0000001001"; -- TODO: comment |
when "00101100001" => data <= "0010000001"; -- TODO: comment |
when "00101100010" => data <= "0010000001"; -- TODO: comment |
when "00101100011" => data <= "0011001111"; -- TODO: comment |
when "00101100100" => data <= "0000000111"; -- TODO: comment |
when "00101100101" => data <= "0011001001"; -- TODO: comment |
when "00101100110" => data <= "0000001001"; -- TODO: comment |
when "00101100111" => data <= "0010000001"; -- TODO: comment |
when "00101101000" => data <= "0010000001"; -- TODO: comment |
when "00101101001" => data <= "1010000000"; -- TODO: comment |
when "00101101010" => data <= "0110100001"; -- TODO: comment |
when "00101101011" => data <= "0110000000"; -- TODO: comment |
when "00101101100" => data <= "0011110110"; -- TODO: comment |
when "00101101101" => data <= "0000000100"; -- TODO: comment |
when "00101101110" => data <= "0000001000"; -- TODO: comment |
when "00101101111" => data <= "0010000001"; -- TODO: comment |
when "00101110000" => data <= "0010000001"; -- TODO: comment |
when "00101110001" => data <= "0011100000"; -- TODO: comment |
when "00101110010" => data <= "0011001001"; -- TODO: comment |
when "00101110011" => data <= "0001101011"; -- TODO: comment |
when "00101110100" => data <= "0011110001"; -- TODO: comment |
when "00101110101" => data <= "0000101110"; -- TODO: comment |
when "00101110110" => data <= "0110100001"; -- TODO: comment |
when "00101110111" => data <= "0110000000"; -- TODO: comment |
when "00101111000" => data <= "0011110110"; -- TODO: comment |
when "00101111001" => data <= "0100000100"; -- TODO: comment |
when "00101111010" => data <= "0100001000"; -- TODO: comment |
when "00101111011" => data <= "0010000001"; -- TODO: comment |
when "00101111100" => data <= "0010000001"; -- TODO: comment |
when "00101111101" => data <= "0011100000"; -- TODO: comment |
when "00101111110" => data <= "0011111000"; -- TODO: comment |
when "00101111111" => data <= "0011001110"; -- TODO: comment |
when "00110000000" => data <= "0000000001"; -- TODO: comment |
when "00110000001" => data <= "0000100110"; -- TODO: comment |
when "00110000010" => data <= "0011001000"; -- TODO: comment |
when "00110000011" => data <= "0000011100"; -- TODO: comment |
when "00110000100" => data <= "0000100111"; -- TODO: comment |
when "00110000101" => data <= "0011110000"; -- TODO: comment |
when "00110000110" => data <= "0011001001"; -- TODO: comment |
when "00110000111" => data <= "0000000100"; -- TODO: comment |
when "00110001000" => data <= "0010100110"; -- TODO: comment |
when "00110001001" => data <= "0000000101"; -- TODO: comment |
when "00110001010" => data <= "0000011010"; -- TODO: comment |
when "00110001011" => data <= "0010000000"; -- TODO: comment |
when "00110001100" => data <= "0011101101"; -- TODO: comment |
when "00110001101" => data <= "0011111000"; -- TODO: comment |
when "00110001110" => data <= "0010000000"; -- TODO: comment |
when "00110001111" => data <= "0001001100"; -- TODO: comment |
when "00110010000" => data <= "0011110001"; -- TODO: comment |
when "00110010001" => data <= "0000101110"; -- TODO: comment |
when "00110010010" => data <= "0011001001"; -- TODO: comment |
when "00110010011" => data <= "0000000100"; -- TODO: comment |
when "00110010100" => data <= "0000001000"; -- TODO: comment |
when "00110010101" => data <= "0010000001"; -- TODO: comment |
when "00110010110" => data <= "0010000001"; -- TODO: comment |
when "00110010111" => data <= "0011100000"; -- TODO: comment |
when "00110011000" => data <= "0011001001"; -- TODO: comment |
when "00110011001" => data <= "0000000101"; -- TODO: comment |
when "00110011010" => data <= "0000001000"; -- TODO: comment |
when "00110011011" => data <= "0010000001"; -- TODO: comment |
when "00110011100" => data <= "0010000001"; -- TODO: comment |
when "00110011101" => data <= "0011100000"; -- TODO: comment |
when "00110011110" => data <= "0010100111"; -- TODO: comment |
when "00110011111" => data <= "0000000100"; -- TODO: comment |
when "00110100000" => data <= "0000001000"; -- TODO: comment |
when "00110100001" => data <= "0010000001"; -- TODO: comment |
when "00110100010" => data <= "0010000001"; -- TODO: comment |
when "00110100011" => data <= "0011100000"; -- TODO: comment |
when "00110100100" => data <= "0011001001"; -- TODO: comment |
when "00110100101" => data <= "0001101101"; -- TODO: comment |
when "00110100110" => data <= "0010000000"; -- TODO: comment |
when "00110100111" => data <= "0010000000"; -- TODO: comment |
when "00110101000" => data <= "0110100001"; -- TODO: comment |
when "00110101001" => data <= "0110000000"; -- TODO: comment |
when "00110101010" => data <= "0011110110"; -- TODO: comment |
when "00110101011" => data <= "0000000100"; -- TODO: comment |
when "00110101100" => data <= "0000001000"; -- TODO: comment |
when "00110101101" => data <= "0010000001"; -- TODO: comment |
when "00110101110" => data <= "0010000001"; -- TODO: comment |
when "00110101111" => data <= "0011100000"; -- TODO: comment |
when "00110110000" => data <= "0011111000"; -- TODO: comment |
when "00110110001" => data <= "0011001110"; -- TODO: comment |
when "00110110010" => data <= "0000000001"; -- TODO: comment |
when "00110110011" => data <= "0000100110"; -- TODO: comment |
when "00110110100" => data <= "0011001000"; -- TODO: comment |
when "00110110101" => data <= "0000011100"; -- TODO: comment |
when "00110110110" => data <= "0000100111"; -- TODO: comment |
when "00110110111" => data <= "0011110000"; -- TODO: comment |
when "00110111000" => data <= "0011001001"; -- TODO: comment |
when "00110111001" => data <= "0000000100"; -- TODO: comment |
when "00110111010" => data <= "0010100110"; -- TODO: comment |
when "00110111011" => data <= "0000000101"; -- TODO: comment |
when "00110111100" => data <= "0000011010"; -- TODO: comment |
when "00110111101" => data <= "0010000000"; -- TODO: comment |
when "00110111110" => data <= "0011101101"; -- TODO: comment |
when "00110111111" => data <= "0011111000"; -- TODO: comment |
when "00111000000" => data <= "0010000000"; -- TODO: comment |
when "00111000001" => data <= "0001001110"; -- TODO: comment |
when "00111000010" => data <= "0011110001"; -- TODO: comment |
when "00111000011" => data <= "0000101110"; -- TODO: comment |
when "00111000100" => data <= "0011001001"; -- TODO: comment |
when "00111000101" => data <= "0000000100"; -- TODO: comment |
when "00111000110" => data <= "0000001000"; -- TODO: comment |
when "00111000111" => data <= "0010000001"; -- TODO: comment |
when "00111001000" => data <= "0010000001"; -- TODO: comment |
when "00111001001" => data <= "0011100000"; -- TODO: comment |
when "00111001010" => data <= "0011010001"; -- TODO: comment |
when "00111001011" => data <= "0000000100"; -- TODO: comment |
when "00111001100" => data <= "0000001000"; -- TODO: comment |
when "00111001101" => data <= "0010000001"; -- TODO: comment |
when "00111001110" => data <= "0010000001"; -- TODO: comment |
when "00111001111" => data <= "0011100000"; -- TODO: comment |
when "00111010000" => data <= "0011001100"; -- TODO: comment |
when "00111010001" => data <= "0000000100"; -- TODO: comment |
when "00111010010" => data <= "0011001001"; -- TODO: comment |
when "00111010011" => data <= "0001101111"; -- TODO: comment |
when "00111010100" => data <= "0010000000"; -- TODO: comment |
when "00111010101" => data <= "0010000000"; -- TODO: comment |
when "00111010110" => data <= "0010000000"; -- TODO: comment |
when "00111010111" => data <= "0110100001"; -- TODO: comment |
when "00111011000" => data <= "0110000000"; -- TODO: comment |
when "00111011001" => data <= "0011110110"; -- TODO: comment |
when "00111011010" => data <= "0000000100"; -- TODO: comment |
when "00111011011" => data <= "0000001000"; -- TODO: comment |
when "00111011100" => data <= "0010000001"; -- TODO: comment |
when "00111011101" => data <= "0010000001"; -- TODO: comment |
when "00111011110" => data <= "0011100000"; -- TODO: comment |
when "00111011111" => data <= "0011111000"; -- TODO: comment |
when "00111100000" => data <= "0011001110"; -- TODO: comment |
when "00111100001" => data <= "0000000001"; -- TODO: comment |
when "00111100010" => data <= "0000100110"; -- TODO: comment |
when "00111100011" => data <= "0011001000"; -- TODO: comment |
when "00111100100" => data <= "0000011100"; -- TODO: comment |
when "00111100101" => data <= "0000100111"; -- TODO: comment |
when "00111100110" => data <= "0011110000"; -- TODO: comment |
when "00111100111" => data <= "0011001001"; -- TODO: comment |
when "00111101000" => data <= "0000000100"; -- TODO: comment |
when "00111101001" => data <= "0010100110"; -- TODO: comment |
when "00111101010" => data <= "0000000101"; -- TODO: comment |
when "00111101011" => data <= "0000011010"; -- TODO: comment |
when "00111101100" => data <= "0010000000"; -- TODO: comment |
when "00111101101" => data <= "0011101101"; -- TODO: comment |
when "00111101110" => data <= "0011111000"; -- TODO: comment |
when "00111101111" => data <= "0010000000"; -- TODO: comment |
when "00111110000" => data <= "0001010000"; -- TODO: comment |
when "00111110001" => data <= "0011110001"; -- TODO: comment |
when "00111110010" => data <= "0000101110"; -- TODO: comment |
when "00111110011" => data <= "0011001001"; -- TODO: comment |
when "00111110100" => data <= "0000000100"; -- TODO: comment |
when "00111110101" => data <= "0000001000"; -- TODO: comment |
when "00111110110" => data <= "0010000001"; -- TODO: comment |
when "00111110111" => data <= "0010000001"; -- TODO: comment |
when "00111111000" => data <= "0011100000"; -- TODO: comment |
when "00111111001" => data <= "0010100111"; -- TODO: comment |
when "00111111010" => data <= "0000000100"; -- TODO: comment |
when "00111111011" => data <= "0011111000"; -- TODO: comment |
when "00111111100" => data <= "0011001001"; -- TODO: comment |
when "00111111101" => data <= "0000000100"; -- TODO: comment |
when "00111111110" => data <= "0000001000"; -- TODO: comment |
when "00111111111" => data <= "0010100000"; -- TODO: comment |
when "01000000000" => data <= "0000101101"; -- TODO: comment |
when "01000000001" => data <= "0000100000"; -- TODO: comment |
when "01000000010" => data <= "0010000001"; -- TODO: comment |
when "01000000011" => data <= "0010000001"; -- TODO: comment |
when "01000000100" => data <= "0011100000"; -- TODO: comment |
when "01000000101" => data <= "0011110010"; -- TODO: comment |
when "01000000110" => data <= "0011100111"; -- TODO: comment |
when "01000000111" => data <= "0000000101"; -- TODO: comment |
when "01000001000" => data <= "0000101111"; -- TODO: comment |
when "01000001001" => data <= "0010100000"; -- TODO: comment |
when "01000001010" => data <= "0000001000"; -- TODO: comment |
when "01000001011" => data <= "0010100001"; -- TODO: comment |
when "01000001100" => data <= "0000110000"; -- TODO: comment |
when "01000001101" => data <= "0010000001"; -- TODO: comment |
when "01000001110" => data <= "0010000001"; -- TODO: comment |
when "01000001111" => data <= "0011100000"; -- TODO: comment |
when "01000010000" => data <= "0000001111"; -- TODO: comment |
when "01000010001" => data <= "0011111000"; -- TODO: comment |
when "01000010010" => data <= "0011010010"; -- TODO: comment |
when "01000010011" => data <= "0000000001"; -- TODO: comment |
when "01000010100" => data <= "0000110011"; -- TODO: comment |
when "01000010101" => data <= "0011001100"; -- TODO: comment |
when "01000010110" => data <= "0000011100"; -- TODO: comment |
when "01000010111" => data <= "0011111000"; -- TODO: comment |
when "01000011000" => data <= "0011010010"; -- TODO: comment |
when "01000011001" => data <= "0000000001"; -- TODO: comment |
when "01000011010" => data <= "0000110100"; -- TODO: comment |
when "01000011011" => data <= "0011001100"; -- TODO: comment |
when "01000011100" => data <= "0000011100"; -- TODO: comment |
when "01000011101" => data <= "0000100001"; -- TODO: comment |
when "01000011110" => data <= "0011110000"; -- TODO: comment |
when "01000011111" => data <= "0011001001"; -- TODO: comment |
when "01000100000" => data <= "0000000100"; -- TODO: comment |
when "01000100001" => data <= "0011111000"; -- TODO: comment |
when "01000100010" => data <= "0010110011"; -- TODO: comment |
when "01000100011" => data <= "0000000101"; -- TODO: comment |
when "01000100100" => data <= "0000110101"; -- TODO: comment |
when "01000100101" => data <= "0010110101"; -- TODO: comment |
when "01000100110" => data <= "0011001001"; -- TODO: comment |
when "01000100111" => data <= "0000000100"; -- TODO: comment |
when "01000101000" => data <= "0000011000"; -- TODO: comment |
when "01000101001" => data <= "0010110100"; -- TODO: comment |
when "01000101010" => data <= "0000000100"; -- TODO: comment |
when "01000101011" => data <= "0010000000"; -- TODO: comment |
when "01000101100" => data <= "0000011011"; -- TODO: comment |
when "01000101101" => data <= "0000000000"; -- TODO: comment |
when "01000101110" => data <= "0000000000"; -- TODO: comment |
when "01000101111" => data <= "0010110101"; -- TODO: comment |
when "01000110000" => data <= "0010101111"; -- TODO: comment |
when "01000110001" => data <= "0011100111"; -- TODO: comment |
when "01000110010" => data <= "0000011001"; -- TODO: comment |
when "01000110011" => data <= "0010101110"; -- TODO: comment |
when "01000110100" => data <= "0010110000"; -- TODO: comment |
when "01000110101" => data <= "0010101101"; -- TODO: comment |
when "01000110110" => data <= "0010000001"; -- TODO: comment |
when "01000110111" => data <= "0010000001"; -- TODO: comment |
when "01000111000" => data <= "1010000000"; -- TODO: comment |
when "01000111001" => data <= "0000100110"; -- TODO: comment |
when "01000111010" => data <= "0011111000"; -- TODO: comment |
when "01000111011" => data <= "0000001000"; -- TODO: comment |
when "01000111100" => data <= "0000100000"; -- TODO: comment |
when "01000111101" => data <= "0000100001"; -- TODO: comment |
when "01000111110" => data <= "0000011000"; -- TODO: comment |
when "01000111111" => data <= "0010000001"; -- TODO: comment |
when "01001000000" => data <= "0010000001"; -- TODO: comment |
when "01001000001" => data <= "0011100000"; -- TODO: comment |
when "01001000010" => data <= "0000001111"; -- TODO: comment |
when "01001000011" => data <= "0000101111"; -- TODO: comment |
when "01001000100" => data <= "0010000000"; -- TODO: comment |
when "01001000101" => data <= "0000011011"; -- TODO: comment |
when "01001000110" => data <= "0000000000"; -- TODO: comment |
when "01001000111" => data <= "0000000000"; -- TODO: comment |
when "01001001000" => data <= "0011100111"; -- TODO: comment |
when "01001001001" => data <= "0010101111"; -- TODO: comment |
when "01001001010" => data <= "0000000100"; -- TODO: comment |
when "01001001011" => data <= "0000011001"; -- TODO: comment |
when "01001001100" => data <= "0010100110"; -- TODO: comment |
when "01001001101" => data <= "0010000001"; -- TODO: comment |
when "01001001110" => data <= "0010000001"; -- TODO: comment |
when "01001001111" => data <= "1010000000"; -- TODO: comment |
when "01001010000" => data <= "0000100110"; -- TODO: comment |
when "01001010001" => data <= "0000100111"; -- TODO: comment |
when "01001010010" => data <= "0011111000"; -- TODO: comment |
when "01001010011" => data <= "0000001000"; -- TODO: comment |
when "01001010100" => data <= "0000100000"; -- TODO: comment |
when "01001010101" => data <= "0000100001"; -- TODO: comment |
when "01001010110" => data <= "0000011000"; -- TODO: comment |
when "01001010111" => data <= "0010000001"; -- TODO: comment |
when "01001011000" => data <= "0010000001"; -- TODO: comment |
when "01001011001" => data <= "0011100000"; -- TODO: comment |
when "01001011010" => data <= "0000001111"; -- TODO: comment |
when "01001011011" => data <= "0000101111"; -- TODO: comment |
when "01001011100" => data <= "0010000000"; -- TODO: comment |
when "01001011101" => data <= "0000011011"; -- TODO: comment |
when "01001011110" => data <= "0000000000"; -- TODO: comment |
when "01001011111" => data <= "0000000000"; -- TODO: comment |
when "01001100000" => data <= "0011100111"; -- TODO: comment |
when "01001100001" => data <= "0010101111"; -- TODO: comment |
when "01001100010" => data <= "0000000100"; -- TODO: comment |
when "01001100011" => data <= "0000011001"; -- TODO: comment |
when "01001100100" => data <= "0010100111"; -- TODO: comment |
when "01001100101" => data <= "0010100110"; -- TODO: comment |
when "01001100110" => data <= "0010000001"; -- TODO: comment |
when "01001100111" => data <= "0010000001"; -- TODO: comment |
when "01001101000" => data <= "1010000000"; -- TODO: comment |
when "01001101001" => data <= "0011111000"; -- TODO: comment |
when "01001101010" => data <= "0000001000"; -- TODO: comment |
when "01001101011" => data <= "0000100000"; -- TODO: comment |
when "01001101100" => data <= "0000100001"; -- TODO: comment |
when "01001101101" => data <= "0000011000"; -- TODO: comment |
when "01001101110" => data <= "0010000001"; -- TODO: comment |
when "01001101111" => data <= "0010000001"; -- TODO: comment |
when "01001110000" => data <= "0011100000"; -- TODO: comment |
when "01001110001" => data <= "0000001111"; -- TODO: comment |
when "01001110010" => data <= "0000101111"; -- TODO: comment |
when "01001110011" => data <= "0010000000"; -- TODO: comment |
when "01001110100" => data <= "0000011011"; -- TODO: comment |
when "01001110101" => data <= "0011100111"; -- TODO: comment |
when "01001110110" => data <= "0010101111"; -- TODO: comment |
when "01001110111" => data <= "0000000100"; -- TODO: comment |
when "01001111000" => data <= "0000011001"; -- TODO: comment |
when "01001111001" => data <= "0000000000"; -- TODO: comment |
when "01001111010" => data <= "0000000000"; -- TODO: comment |
when "01001111011" => data <= "0010000001"; -- TODO: comment |
when "01001111100" => data <= "0010000001"; -- TODO: comment |
when "01001111101" => data <= "1010000000"; -- TODO: comment |
when "01001111110" => data <= "0010000001"; -- TODO: comment |
when "01001111111" => data <= "0010000001"; -- TODO: comment |
when "01010000000" => data <= "0010100100"; -- TODO: comment |
when "01010000001" => data <= "0011000110"; -- TODO: comment |
when "01010000010" => data <= "0000000100"; -- TODO: comment |
when "01010000011" => data <= "0011001001"; -- TODO: comment |
when "01010000100" => data <= "0010000000"; -- TODO: comment |
when "01010000101" => data <= "0001110001"; -- TODO: comment |
when "01010000110" => data <= "0010000000"; -- TODO: comment |
when "01010000111" => data <= "0010000000"; -- TODO: comment |
when "01010001000" => data <= "0010000001"; -- TODO: comment |
when "01010001001" => data <= "0010000001"; -- TODO: comment |
when "01010001010" => data <= "0010100100"; -- TODO: comment |
when "01010001011" => data <= "0011000100"; -- TODO: comment |
when "01010001100" => data <= "0000000100"; -- TODO: comment |
when "01010001101" => data <= "0011001001"; -- TODO: comment |
when "01010001110" => data <= "0010000000"; -- TODO: comment |
when "01010001111" => data <= "0001110010"; -- TODO: comment |
when "01010010000" => data <= "0010000000"; -- TODO: comment |
when "01010010001" => data <= "0010000000"; -- TODO: comment |
when "01010010010" => data <= "0110100001"; -- TODO: comment |
when "01010010011" => data <= "0110000000"; -- TODO: comment |
when "01010010100" => data <= "0011110110"; -- TODO: comment |
when "01010010101" => data <= "0000000100"; -- TODO: comment |
when "01010010110" => data <= "0011111000"; -- TODO: comment |
when "01010010111" => data <= "0000001000"; -- TODO: comment |
when "01010011000" => data <= "0011001001"; -- TODO: comment |
when "01010011001" => data <= "0000000100"; -- TODO: comment |
when "01010011010" => data <= "0010000001"; -- TODO: comment |
when "01010011011" => data <= "0010000001"; -- TODO: comment |
when "01010011100" => data <= "0011100000"; -- TODO: comment |
when "01010011101" => data <= "0000100110"; -- TODO: comment |
when "01010011110" => data <= "0000001000"; -- TODO: comment |
when "01010011111" => data <= "0010100110"; -- TODO: comment |
when "01010100000" => data <= "0010000001"; -- TODO: comment |
when "01010100001" => data <= "0010000001"; -- TODO: comment |
when "01010100010" => data <= "1011100000"; -- TODO: comment |
when "01010100011" => data <= "0011000011"; -- TODO: comment |
when "01010100100" => data <= "1011000011"; -- TODO: comment |
when "01010100101" => data <= "0011000011"; -- TODO: comment |
when "01010100110" => data <= "1011001001"; -- TODO: comment |
when "01010100111" => data <= "0000100110"; -- TODO: comment |
when "01010101000" => data <= "0000000000"; -- TODO: comment |
when "01010101001" => data <= "1010100110"; -- TODO: comment |
when "01010101010" => data <= "0011101000"; -- TODO: comment |
when "01010101011" => data <= "1011101001"; -- TODO: comment |
when "01010101100" => data <= "0011101001"; -- TODO: comment |
when "01010101101" => data <= "1011101010"; -- TODO: comment |
when "01010101110" => data <= "0011101010"; -- TODO: comment |
when "01010101111" => data <= "1011101011"; -- TODO: comment |
when "01010110000" => data <= "0011110001"; -- TODO: comment |
when "01010110001" => data <= "0011111000"; -- TODO: comment |
when "01010110010" => data <= "0011001001"; -- TODO: comment |
when "01010110011" => data <= "0000000100"; -- TODO: comment |
when "01010110100" => data <= "0000011000"; -- TODO: comment |
when "01010110101" => data <= "0000100110"; -- TODO: comment |
when "01010110110" => data <= "0011101010"; -- TODO: comment |
when "01010110111" => data <= "0011101011"; -- TODO: comment |
when "01010111000" => data <= "0010100110"; -- TODO: comment |
when "01010111001" => data <= "0000011000"; -- TODO: comment |
when "01010111010" => data <= "1010000000"; -- TODO: comment |
when "01010111011" => data <= "0011110001"; -- TODO: comment |
when "01010111100" => data <= "0111111000"; -- TODO: comment |
when "01010111101" => data <= "0011110100"; -- TODO: comment |
when "01010111110" => data <= "0000000100"; -- TODO: comment |
when "01010111111" => data <= "0000011000"; -- TODO: comment |
when "01011000000" => data <= "0000100110"; -- TODO: comment |
when "01011000001" => data <= "0011101000"; -- TODO: comment |
when "01011000010" => data <= "0011101001"; -- TODO: comment |
when "01011000011" => data <= "0010100110"; -- TODO: comment |
when "01011000100" => data <= "0000011000"; -- TODO: comment |
when "01011000101" => data <= "1010000000"; -- TODO: comment |
when "01011000110" => data <= "0000010001"; -- TODO: comment |
when "01011000111" => data <= "1000010000"; -- TODO: comment |
when "01011001000" => data <= "0000010010"; -- TODO: comment |
when "01011001001" => data <= "1000010001"; -- TODO: comment |
when "01011001010" => data <= "0000010011"; -- TODO: comment |
when "01011001011" => data <= "1000010010"; -- TODO: comment |
when "01011001100" => data <= "0011110001"; -- TODO: comment |
when "01011001101" => data <= "0011111000"; -- TODO: comment |
when "01011001110" => data <= "0011001001"; -- TODO: comment |
when "01011001111" => data <= "0000000100"; -- TODO: comment |
when "01011010000" => data <= "0000011000"; -- TODO: comment |
when "01011010001" => data <= "0000100110"; -- TODO: comment |
when "01011010010" => data <= "0000010011"; -- TODO: comment |
when "01011010011" => data <= "0000010010"; -- TODO: comment |
when "01011010100" => data <= "0010100110"; -- TODO: comment |
when "01011010101" => data <= "0000011000"; -- TODO: comment |
when "01011010110" => data <= "1010000000"; -- TODO: comment |
when "01011010111" => data <= "0011110001"; -- TODO: comment |
when "01011011000" => data <= "0111111000"; -- TODO: comment |
when "01011011001" => data <= "0011110100"; -- TODO: comment |
when "01011011010" => data <= "0000000100"; -- TODO: comment |
when "01011011011" => data <= "0000011000"; -- TODO: comment |
when "01011011100" => data <= "0000100110"; -- TODO: comment |
when "01011011101" => data <= "0000010001"; -- TODO: comment |
when "01011011110" => data <= "0000010000"; -- TODO: comment |
when "01011011111" => data <= "0010100110"; -- TODO: comment |
when "01011100000" => data <= "0000011000"; -- TODO: comment |
when "01011100001" => data <= "1010000000"; -- TODO: comment |
when "01011100010" => data <= "0110000000"; -- TODO: comment |
when "01011100011" => data <= "0110000000"; -- TODO: comment |
when "01011100100" => data <= "0011110110"; -- TODO: comment |
when "01011100101" => data <= "0011111000"; -- TODO: comment |
when "01011100110" => data <= "0000001000"; -- TODO: comment |
when "01011100111" => data <= "0011001001"; -- TODO: comment |
when "01011101000" => data <= "0000000100"; -- TODO: comment |
when "01011101001" => data <= "0000100110"; -- TODO: comment |
when "01011101010" => data <= "0010000001"; -- TODO: comment |
when "01011101011" => data <= "0010000001"; -- TODO: comment |
when "01011101100" => data <= "0011100000"; -- TODO: comment |
when "01011101101" => data <= "0010100110"; -- TODO: comment |
when "01011101110" => data <= "0000001000"; -- TODO: comment |
when "01011101111" => data <= "0010000001"; -- TODO: comment |
when "01011110000" => data <= "0010000001"; -- TODO: comment |
when "01011110001" => data <= "1011100000"; -- TODO: comment |
when "01011110010" => data <= "0100100111"; -- TODO: comment |
when "01011110011" => data <= "0100100110"; -- TODO: comment |
when "01011110100" => data <= "0011110110"; -- TODO: comment |
when "01011110101" => data <= "0011111000"; -- TODO: comment |
when "01011110110" => data <= "0000000111"; -- TODO: comment |
when "01011110111" => data <= "0010100110"; -- TODO: comment |
when "01011111000" => data <= "0000001001"; -- TODO: comment |
when "01011111001" => data <= "0011001001"; -- TODO: comment |
when "01011111010" => data <= "0000000100"; -- TODO: comment |
when "01011111011" => data <= "0010000001"; -- TODO: comment |
when "01011111100" => data <= "0010000001"; -- TODO: comment |
when "01011111101" => data <= "0000000111"; -- TODO: comment |
when "01011111110" => data <= "0010100111"; -- TODO: comment |
when "01011111111" => data <= "0000001001"; -- TODO: comment |
when "01100000000" => data <= "0010000001"; -- TODO: comment |
when "01100000001" => data <= "0010000001"; -- TODO: comment |
when "01100000010" => data <= "1010000000"; -- TODO: comment |
when "01100000011" => data <= "0011111000"; -- TODO: comment |
when "01100000100" => data <= "0010000000"; -- TODO: comment |
when "01100000101" => data <= "0001010011"; -- TODO: comment |
when "01100000110" => data <= "0010000000"; -- TODO: comment |
when "01100000111" => data <= "0010000000"; -- TODO: comment |
when "01100001000" => data <= "0000001000"; -- TODO: comment |
when "01100001001" => data <= "0010000001"; -- TODO: comment |
when "01100001010" => data <= "0010000001"; -- TODO: comment |
when "01100001011" => data <= "0011100000"; -- TODO: comment |
when "01100001100" => data <= "0110000000"; -- TODO: comment |
when "01100001101" => data <= "0110000000"; -- TODO: comment |
when "01100001110" => data <= "0011110110"; -- TODO: comment |
when "01100001111" => data <= "0000000100"; -- TODO: comment |
when "01100010000" => data <= "0011111000"; -- TODO: comment |
when "01100010001" => data <= "0000001000"; -- TODO: comment |
when "01100010010" => data <= "0011001001"; -- TODO: comment |
when "01100010011" => data <= "0000000100"; -- TODO: comment |
when "01100010100" => data <= "0000100110"; -- TODO: comment |
when "01100010101" => data <= "0010000001"; -- TODO: comment |
when "01100010110" => data <= "0010000001"; -- TODO: comment |
when "01100010111" => data <= "0011100000"; -- TODO: comment |
when "01100011000" => data <= "0010100110"; -- TODO: comment |
when "01100011001" => data <= "0000001000"; -- TODO: comment |
when "01100011010" => data <= "0010000001"; -- TODO: comment |
when "01100011011" => data <= "0010000001"; -- TODO: comment |
when "01100011100" => data <= "1011100000"; -- TODO: comment |
when "01100011101" => data <= "0000100111"; -- TODO: comment |
when "01100011110" => data <= "0000100110"; -- TODO: comment |
when "01100011111" => data <= "0011111000"; -- TODO: comment |
when "01100100000" => data <= "0010000000"; -- TODO: comment |
when "01100100001" => data <= "0001010100"; -- TODO: comment |
when "01100100010" => data <= "0010000000"; -- TODO: comment |
when "01100100011" => data <= "0010000000"; -- TODO: comment |
when "01100100100" => data <= "0000001000"; -- TODO: comment |
when "01100100101" => data <= "0010000001"; -- TODO: comment |
when "01100100110" => data <= "0010000001"; -- TODO: comment |
when "01100100111" => data <= "0011100000"; -- TODO: comment |
when "01100101000" => data <= "0110000000"; -- TODO: comment |
when "01100101001" => data <= "0110000000"; -- TODO: comment |
when "01100101010" => data <= "0011110110"; -- TODO: comment |
when "01100101011" => data <= "0000000100"; -- TODO: comment |
when "01100101100" => data <= "0011111000"; -- TODO: comment |
when "01100101101" => data <= "0000000111"; -- TODO: comment |
when "01100101110" => data <= "0010100110"; -- TODO: comment |
when "01100101111" => data <= "0000001001"; -- TODO: comment |
when "01100110000" => data <= "0011001001"; -- TODO: comment |
when "01100110001" => data <= "0000000100"; -- TODO: comment |
when "01100110010" => data <= "0010000001"; -- TODO: comment |
when "01100110011" => data <= "0010000001"; -- TODO: comment |
when "01100110100" => data <= "0000000111"; -- TODO: comment |
when "01100110101" => data <= "0010100111"; -- TODO: comment |
when "01100110110" => data <= "0000001001"; -- TODO: comment |
when "01100110111" => data <= "0010000001"; -- TODO: comment |
when "01100111000" => data <= "0010000001"; -- TODO: comment |
when "01100111001" => data <= "1010000000"; -- TODO: comment |
when "01100111010" => data <= "0000100110"; -- TODO: comment |
when "01100111011" => data <= "0000101000"; -- TODO: comment |
when "01100111100" => data <= "0000100111"; -- TODO: comment |
when "01100111101" => data <= "0011111000"; -- TODO: comment |
when "01100111110" => data <= "0011111000"; -- TODO: comment |
when "01100111111" => data <= "0001010101"; -- TODO: comment |
when "01101000000" => data <= "0011001001"; -- TODO: comment |
when "01101000001" => data <= "0000000100"; -- TODO: comment |
when "01101000010" => data <= "0000001000"; -- TODO: comment |
when "01101000011" => data <= "0010000001"; -- TODO: comment |
when "01101000100" => data <= "0010000001"; -- TODO: comment |
when "01101000101" => data <= "0011100000"; -- TODO: comment |
when "01101000110" => data <= "0011001001"; -- TODO: comment |
when "01101000111" => data <= "0000000101"; -- TODO: comment |
when "01101001000" => data <= "0010100111"; -- TODO: comment |
when "01101001001" => data <= "0000000101"; -- TODO: comment |
when "01101001010" => data <= "0010100111"; -- TODO: comment |
when "01101001011" => data <= "0000000010"; -- TODO: comment |
when "01101001100" => data <= "0011010011"; -- TODO: comment |
when "01101001101" => data <= "0000000001"; -- TODO: comment |
when "01101001110" => data <= "0010000000"; -- TODO: comment |
when "01101001111" => data <= "0001110110"; -- TODO: comment |
when "01101010000" => data <= "0010000000"; -- TODO: comment |
when "01101010001" => data <= "0010000000"; -- TODO: comment |
when "01101010010" => data <= "0000001000"; -- TODO: comment |
when "01101010011" => data <= "0010000001"; -- TODO: comment |
when "01101010100" => data <= "0010000001"; -- TODO: comment |
when "01101010101" => data <= "0011100000"; -- TODO: comment |
when "01101010110" => data <= "0010100111"; -- TODO: comment |
when "01101010111" => data <= "0011001001"; -- TODO: comment |
when "01101011000" => data <= "0000011101"; -- TODO: comment |
when "01101011001" => data <= "0000000100"; -- TODO: comment |
when "01101011010" => data <= "0000101001"; -- TODO: comment |
when "01101011011" => data <= "0010101001"; -- TODO: comment |
when "01101011100" => data <= "0000000111"; -- TODO: comment |
when "01101011101" => data <= "0010101000"; -- TODO: comment |
when "01101011110" => data <= "0000001001"; -- TODO: comment |
when "01101011111" => data <= "0010101001"; -- TODO: comment |
when "01101100000" => data <= "0011001001"; -- TODO: comment |
when "01101100001" => data <= "0000000100"; -- TODO: comment |
when "01101100010" => data <= "0010000001"; -- TODO: comment |
when "01101100011" => data <= "0010000001"; -- TODO: comment |
when "01101100100" => data <= "0000000111"; -- TODO: comment |
when "01101100101" => data <= "0010100110"; -- TODO: comment |
when "01101100110" => data <= "0000001001"; -- TODO: comment |
when "01101100111" => data <= "0010000001"; -- TODO: comment |
when "01101101000" => data <= "0010000001"; -- TODO: comment |
when "01101101001" => data <= "1010000000"; -- TODO: comment |
when "01101101010" => data <= "0000100111"; -- TODO: comment |
when "01101101011" => data <= "0011111000"; -- TODO: comment |
when "01101101100" => data <= "0011111000"; -- TODO: comment |
when "01101101101" => data <= "0001010111"; -- TODO: comment |
when "01101101110" => data <= "0011001001"; -- TODO: comment |
when "01101101111" => data <= "0000000100"; -- TODO: comment |
when "01101110000" => data <= "0000001000"; -- TODO: comment |
when "01101110001" => data <= "0010000001"; -- TODO: comment |
when "01101110010" => data <= "0010000001"; -- TODO: comment |
when "01101110011" => data <= "0011100000"; -- TODO: comment |
when "01101110100" => data <= "0011001001"; -- TODO: comment |
when "01101110101" => data <= "0000000101"; -- TODO: comment |
when "01101110110" => data <= "0010100111"; -- TODO: comment |
when "01101110111" => data <= "0000000101"; -- TODO: comment |
when "01101111000" => data <= "0010100111"; -- TODO: comment |
when "01101111001" => data <= "0000000010"; -- TODO: comment |
when "01101111010" => data <= "0011010011"; -- TODO: comment |
when "01101111011" => data <= "0000000001"; -- TODO: comment |
when "01101111100" => data <= "0010000000"; -- TODO: comment |
when "01101111101" => data <= "0001111000"; -- TODO: comment |
when "01101111110" => data <= "0010000000"; -- TODO: comment |
when "01101111111" => data <= "0010000000"; -- TODO: comment |
when "01110000000" => data <= "0000001000"; -- TODO: comment |
when "01110000001" => data <= "0010000001"; -- TODO: comment |
when "01110000010" => data <= "0010000001"; -- TODO: comment |
when "01110000011" => data <= "0011100000"; -- TODO: comment |
when "01110000100" => data <= "0010100111"; -- TODO: comment |
when "01110000101" => data <= "0011001001"; -- TODO: comment |
when "01110000110" => data <= "0000011101"; -- TODO: comment |
when "01110000111" => data <= "0000000100"; -- TODO: comment |
when "01110001000" => data <= "0011111000"; -- TODO: comment |
when "01110001001" => data <= "0000101001"; -- TODO: comment |
when "01110001010" => data <= "0000001000"; -- TODO: comment |
when "01110001011" => data <= "0010000001"; -- TODO: comment |
when "01110001100" => data <= "0010000001"; -- TODO: comment |
when "01110001101" => data <= "0011100000"; -- TODO: comment |
when "01110001110" => data <= "0010101001"; -- TODO: comment |
when "01110001111" => data <= "0011001001"; -- TODO: comment |
when "01110010000" => data <= "0000000100"; -- TODO: comment |
when "01110010001" => data <= "0000001000"; -- TODO: comment |
when "01110010010" => data <= "0010000001"; -- TODO: comment |
when "01110010011" => data <= "0010000001"; -- TODO: comment |
when "01110010100" => data <= "1011100000"; -- TODO: comment |
when "01110010101" => data <= "0011110010"; -- TODO: comment |
when "01110010110" => data <= "0011001001"; -- TODO: comment |
when "01110010111" => data <= "0000000101"; -- TODO: comment |
when "01110011000" => data <= "0000011001"; -- TODO: comment |
when "01110011001" => data <= "0010100100"; -- TODO: comment |
when "01110011010" => data <= "0011001001"; -- TODO: comment |
when "01110011011" => data <= "0010000000"; -- TODO: comment |
when "01110011100" => data <= "0001111001"; -- TODO: comment |
when "01110011101" => data <= "0010000000"; -- TODO: comment |
when "01110011110" => data <= "0010000000"; -- TODO: comment |
when "01110011111" => data <= "0011110010"; -- TODO: comment |
when "01110100000" => data <= "0011001001"; -- TODO: comment |
when "01110100001" => data <= "0000000101"; -- TODO: comment |
when "01110100010" => data <= "0000011001"; -- TODO: comment |
when "01110100011" => data <= "0010100100"; -- TODO: comment |
when "01110100100" => data <= "0011010100"; -- TODO: comment |
when "01110100101" => data <= "0000000100"; -- TODO: comment |
when "01110100110" => data <= "0011001001"; -- TODO: comment |
when "01110100111" => data <= "0010000000"; -- TODO: comment |
when "01110101000" => data <= "0001111010"; -- TODO: comment |
when "01110101001" => data <= "0010000000"; -- TODO: comment |
when "01110101010" => data <= "0010000000"; -- TODO: comment |
when "01110101011" => data <= "0011110010"; -- TODO: comment |
when "01110101100" => data <= "0011001001"; -- TODO: comment |
when "01110101101" => data <= "0000000101"; -- TODO: comment |
when "01110101110" => data <= "0000011001"; -- TODO: comment |
when "01110101111" => data <= "0010000000"; -- TODO: comment |
when "01110110000" => data <= "0010000000"; -- TODO: comment |
when "01110110001" => data <= "0010100011"; -- TODO: comment |
when "01110110010" => data <= "0110000000"; -- TODO: comment |
when "01110110011" => data <= "0011110100"; -- TODO: comment |
when "01110110100" => data <= "0011001110"; -- TODO: comment |
when "01110110101" => data <= "0000000001"; -- TODO: comment |
when "01110110110" => data <= "0011111000"; -- TODO: comment |
when "01110110111" => data <= "0000000100"; -- TODO: comment |
when "01110111000" => data <= "0000000100"; -- TODO: comment |
when "01110111001" => data <= "0011001001"; -- TODO: comment |
when "01110111010" => data <= "0010000000"; -- TODO: comment |
when "01110111011" => data <= "0001111011"; -- TODO: comment |
when "01110111100" => data <= "0010000000"; -- TODO: comment |
when "01110111101" => data <= "0010000000"; -- TODO: comment |
when "01110111110" => data <= "0011110010"; -- TODO: comment |
when "01110111111" => data <= "0011001001"; -- TODO: comment |
when "01111000000" => data <= "0000000101"; -- TODO: comment |
when "01111000001" => data <= "0000011001"; -- TODO: comment |
when "01111000010" => data <= "0010000000"; -- TODO: comment |
when "01111000011" => data <= "0010000000"; -- TODO: comment |
when "01111000100" => data <= "0010100011"; -- TODO: comment |
when "01111000101" => data <= "0110000000"; -- TODO: comment |
when "01111000110" => data <= "0011110100"; -- TODO: comment |
when "01111000111" => data <= "0011001110"; -- TODO: comment |
when "01111001000" => data <= "0000000001"; -- TODO: comment |
when "01111001001" => data <= "0011111000"; -- TODO: comment |
when "01111001010" => data <= "0000000100"; -- TODO: comment |
when "01111001011" => data <= "0000000100"; -- TODO: comment |
when "01111001100" => data <= "0000100110"; -- TODO: comment |
when "01111001101" => data <= "0110100001"; -- TODO: comment |
when "01111001110" => data <= "0110000000"; -- TODO: comment |
when "01111001111" => data <= "0011110110"; -- TODO: comment |
when "01111010000" => data <= "0000000100"; -- TODO: comment |
when "01111010001" => data <= "0000001000"; -- TODO: comment |
when "01111010010" => data <= "0010000001"; -- TODO: comment |
when "01111010011" => data <= "0010000001"; -- TODO: comment |
when "01111010100" => data <= "0011100000"; -- TODO: comment |
when "01111010101" => data <= "0010100110"; -- TODO: comment |
when "01111010110" => data <= "0011001001"; -- TODO: comment |
when "01111010111" => data <= "0010000000"; -- TODO: comment |
when "01111011000" => data <= "0001111100"; -- TODO: comment |
when "01111011001" => data <= "0010000000"; -- TODO: comment |
when "01111011010" => data <= "0010000000"; -- TODO: comment |
when "01111011011" => data <= "0011110010"; -- TODO: comment |
when "01111011100" => data <= "0011001001"; -- TODO: comment |
when "01111011101" => data <= "0000000101"; -- TODO: comment |
when "01111011110" => data <= "0000011001"; -- TODO: comment |
when "01111011111" => data <= "0010000000"; -- TODO: comment |
when "01111100000" => data <= "0010000000"; -- TODO: comment |
when "01111100001" => data <= "0010100011"; -- TODO: comment |
when "01111100010" => data <= "0110000000"; -- TODO: comment |
when "01111100011" => data <= "0011110100"; -- TODO: comment |
when "01111100100" => data <= "0011001110"; -- TODO: comment |
when "01111100101" => data <= "0000000001"; -- TODO: comment |
when "01111100110" => data <= "0011111000"; -- TODO: comment |
when "01111100111" => data <= "0000000100"; -- TODO: comment |
when "01111101000" => data <= "0000000100"; -- TODO: comment |
when "01111101001" => data <= "0000100110"; -- TODO: comment |
when "01111101010" => data <= "0110000000"; -- TODO: comment |
when "01111101011" => data <= "0110000000"; -- TODO: comment |
when "01111101100" => data <= "0011110110"; -- TODO: comment |
when "01111101101" => data <= "0010100110"; -- TODO: comment |
when "01111101110" => data <= "0011001001"; -- TODO: comment |
when "01111101111" => data <= "0010000000"; -- TODO: comment |
when "01111110000" => data <= "0001111101"; -- TODO: comment |
when "01111110001" => data <= "0010000000"; -- TODO: comment |
when "01111110010" => data <= "0010000000"; -- TODO: comment |
when "01111110011" => data <= "0000001000"; -- TODO: comment |
when "01111110100" => data <= "0010000001"; -- TODO: comment |
when "01111110101" => data <= "0010000001"; -- TODO: comment |
when "01111110110" => data <= "1011100000"; -- TODO: comment |
when "01111110111" => data <= "0000000111"; -- TODO: comment |
when "01111111000" => data <= "0000001001"; -- TODO: comment |
when "01111111001" => data <= "0010000001"; -- TODO: comment |
when "01111111010" => data <= "0010000001"; -- TODO: comment |
when "01111111011" => data <= "1010000000"; -- TODO: comment |
when "01111111100" => data <= "0000011010"; -- TODO: comment |
when "01111111101" => data <= "0010000000"; -- TODO: comment |
when "01111111110" => data <= "1011101101"; -- TODO: comment |
when "01111111111" => data <= "0000011010"; -- TODO: comment |
when "10000000000" => data <= "0010000000"; -- TODO: comment |
when "10000000001" => data <= "1000010101"; -- TODO: comment |
when "10000000010" => data <= "0011110000"; -- TODO: comment |
when "10000000011" => data <= "0011001001"; -- TODO: comment |
when "10000000100" => data <= "1000000100"; -- TODO: comment |
when "10000000101" => data <= "0010000000"; -- TODO: comment |
when "10000000110" => data <= "0000011011"; -- TODO: comment |
when "10000000111" => data <= "0000000000"; -- TODO: comment |
when "10000001000" => data <= "1000000000"; -- TODO: comment |
when "10000001001" => data <= "1011110001"; -- TODO: comment |
when "10000001010" => data <= "0000011000"; -- TODO: comment |
when "10000001011" => data <= "1010000000"; -- TODO: comment |
when "10000001100" => data <= "0011001010"; -- TODO: comment |
when "10000001101" => data <= "0000000100"; -- TODO: comment |
when "10000001110" => data <= "0000101000"; -- TODO: comment |
when "10000001111" => data <= "0000001000"; -- TODO: comment |
when "10000010000" => data <= "0000100111"; -- TODO: comment |
when "10000010001" => data <= "0010000001"; -- TODO: comment |
when "10000010010" => data <= "0010000001"; -- TODO: comment |
when "10000010011" => data <= "0011100000"; -- TODO: comment |
when "10000010100" => data <= "0000100110"; -- TODO: comment |
when "10000010101" => data <= "0010101000"; -- TODO: comment |
when "10000010110" => data <= "0011111000"; -- TODO: comment |
when "10000010111" => data <= "0010100111"; -- TODO: comment |
when "10000011000" => data <= "0000000100"; -- TODO: comment |
when "10000011001" => data <= "0000011010"; -- TODO: comment |
when "10000011010" => data <= "0011111000"; -- TODO: comment |
when "10000011011" => data <= "0010100110"; -- TODO: comment |
when "10000011100" => data <= "0000000100"; -- TODO: comment |
when "10000011101" => data <= "0000000111"; -- TODO: comment |
when "10000011110" => data <= "0011101101"; -- TODO: comment |
when "10000011111" => data <= "0000001001"; -- TODO: comment |
when "10000100000" => data <= "0011111000"; -- TODO: comment |
when "10000100001" => data <= "0010000001"; -- TODO: comment |
when "10000100010" => data <= "0010000001"; -- TODO: comment |
when "10000100011" => data <= "0001111110"; -- TODO: comment |
when "10000100100" => data <= "0011001010"; -- TODO: comment |
when "10000100101" => data <= "0000000100"; -- TODO: comment |
when "10000100110" => data <= "1000000000"; -- TODO: comment |
when "10000100111" => data <= "0011001010"; -- TODO: comment |
when "10000101000" => data <= "0000000100"; -- TODO: comment |
when "10000101001" => data <= "0000101000"; -- TODO: comment |
when "10000101010" => data <= "0000100111"; -- TODO: comment |
when "10000101011" => data <= "0000001000"; -- TODO: comment |
when "10000101100" => data <= "0010000001"; -- TODO: comment |
when "10000101101" => data <= "0010000001"; -- TODO: comment |
when "10000101110" => data <= "0011100000"; -- TODO: comment |
when "10000101111" => data <= "0000100110"; -- TODO: comment |
when "10000110000" => data <= "0010101000"; -- TODO: comment |
when "10000110001" => data <= "0011111000"; -- TODO: comment |
when "10000110010" => data <= "0010100110"; -- TODO: comment |
when "10000110011" => data <= "0000000100"; -- TODO: comment |
when "10000110100" => data <= "0000001000"; -- TODO: comment |
when "10000110101" => data <= "0011111000"; -- TODO: comment |
when "10000110110" => data <= "0010100111"; -- TODO: comment |
when "10000110111" => data <= "0000000100"; -- TODO: comment |
when "10000111000" => data <= "0000011010"; -- TODO: comment |
when "10000111001" => data <= "0010000001"; -- TODO: comment |
when "10000111010" => data <= "0010000001"; -- TODO: comment |
when "10000111011" => data <= "0011100000"; -- TODO: comment |
when "10000111100" => data <= "0000010101"; -- TODO: comment |
when "10000111101" => data <= "0011111000"; -- TODO: comment |
when "10000111110" => data <= "0010000000"; -- TODO: comment |
when "10000111111" => data <= "0001111111"; -- TODO: comment |
when "10001000000" => data <= "0011001010"; -- TODO: comment |
when "10001000001" => data <= "0000000100"; -- TODO: comment |
when "10001000010" => data <= "1000000000"; -- TODO: comment |
when "10001000011" => data <= "0000001110"; -- TODO: comment |
when "10001000100" => data <= "0000000000"; -- TODO: comment |
when "10001000101" => data <= "0010000001"; -- TODO: comment |
when "10001000110" => data <= "0010000001"; -- TODO: comment |
when "10001000111" => data <= "1000000000"; -- TODO: comment |
when "10001001000" => data <= "1010000000"; -- TODO: comment |
|
when others => data <= "0000000000"; |
end case; |
end process; |
|
end rtl; |
/mul.vhd
0,0 → 1,99
-- |
-- This file is a part of JOP, the Java Optimized Processor |
-- |
-- Copyright (C) 2001-2008, Martin Schoeberl (martin@jopdesign.com) |
-- Copyright (C) 2008, Wolfgang Puffitsch |
-- |
-- 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/>. |
-- |
|
|
-- |
-- mul.vhd |
-- |
-- bit-serial multiplier |
-- |
-- 244 LCs only mul |
-- |
-- 2002-03-22 first version |
-- 2004-10-07 changed to Koljas version |
-- 2004-10-08 mul operands from a and b, single instruction |
-- 2008-02-15 changed from booth to bit-serial |
-- |
|
|
library ieee ; |
use ieee.std_logic_1164.all ; |
use ieee.numeric_std.all ; |
use ieee.std_logic_unsigned.all; |
|
|
entity mul is |
|
generic ( |
width : integer := 32 -- one data word |
); |
|
port ( |
clk : in std_logic; |
|
ain : in std_logic_vector(width-1 downto 0); |
bin : in std_logic_vector(width-1 downto 0); |
wr : in std_logic; -- write starts multiplier |
dout : out std_logic_vector(width-1 downto 0) |
); |
end mul; |
|
|
architecture rtl of mul is |
-- |
-- Signals |
-- |
signal count : integer range 0 to width/2; |
signal p : unsigned(width-1 downto 0); |
signal a, b : unsigned(width-1 downto 0); |
|
begin |
|
process(clk) |
|
variable prod : unsigned(width-1 downto 0); |
|
begin |
if rising_edge(clk) then |
if wr='1' then |
p <= (others => '0'); |
a <= unsigned(ain); |
b <= unsigned(bin); |
else |
|
prod := p; |
if b(0) = '1' then |
prod := prod + a; |
end if; |
if b(1) = '1' then |
prod := (prod(width-1 downto 1) + a(width-2 downto 0)) & prod(0); |
end if; |
p <= prod; |
|
a <= a(width-3 downto 0) & "00"; |
b <= "00" & b(width-1 downto 2); |
|
end if; |
end if; |
end process; |
|
dout <= std_logic_vector(p); |
|
end rtl; |
/bcfetch.vhd
0,0 → 1,384
-- |
-- |
-- 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/>. |
-- |
|
|
-- |
-- bcfetch.vhd |
-- |
-- Java bc fetch and address translation for JVM |
-- |
-- resources on ACEX1K30-3 |
-- |
-- bytecode LCs, max ca. xx MHz |
-- |
-- todo: |
-- |
-- 2001-11-16 split from fetch.vhd, register jpaddr instead of jinstr |
-- 2001-12-06 unregistered!!! jpaddr, jbr registered (moved from decode) |
-- 2001-12-07 removed mux befor jbc ram, jbr unregistered selects addr. for jpc |
-- decode goto and if_bytecode from jinstr |
-- 2002-03-24 autoincrement of jpc on bc_wr |
-- 2002-10-21 added if(non)null |
-- 2003-02-22 registered jbc ram |
-- 2003-08-14 move wr-addr load and autoincrement to ajbc.vhd (now 32 bit interface) |
-- 2003-08-15 interrupt handling |
-- 2004-04-06 removed signal jfetch from interrupt mux (is in fetch allready) |
-- different mux for jpc and jbc rdaddr, register jump address calculation |
-- 2004-09-11 move jbc to mem |
-- 2005-01-17 move interrupt mux to jtbl.vhd (mux after the table) |
-- 2007-12-01 move most interrupt processing to sc_sys |
-- |
-- TODO: use 'running' bit and generate jbr here! |
-- |
|
|
library ieee; |
use ieee.std_logic_1164.all; |
use ieee.numeric_std.all; |
|
use work.jop_types.all; |
|
entity bcfetch is |
|
generic ( |
jpc_width : integer; -- address bits of java byte code pc |
pc_width : integer -- address bits of internal instruction rom |
); |
port ( |
clk, reset : in std_logic; |
|
jpc_out : out std_logic_vector(jpc_width downto 0); -- jpc read |
din : in std_logic_vector(31 downto 0); -- A from stack |
jpc_wr : in std_logic; |
|
-- connection to bytecode cache |
|
jbc_addr : out std_logic_vector(jpc_width-1 downto 0); |
jbc_data : in std_logic_vector(7 downto 0); |
|
jfetch : in std_logic; |
jopdfetch : in std_logic; |
|
zf, nf : in std_logic; |
eq, lt : in std_logic; |
|
jbr : in std_logic; |
|
irq_in : in irq_bcf_type; |
irq_out : out irq_ack_type; |
|
jpaddr : out std_logic_vector(pc_width-1 downto 0); -- address for JVM |
opd : out std_logic_vector(15 downto 0) -- operands |
); |
end bcfetch; |
|
architecture rtl of bcfetch is |
|
-- |
-- jtbl component (generated vhdl file from Jopa!) |
-- |
-- logic rom (unregistered) |
-- |
component jtbl is |
port ( |
bcode : in std_logic_vector(7 downto 0); |
int_pend : in std_logic; |
exc_pend : in std_logic; |
q : out std_logic_vector(pc_width-1 downto 0) |
); |
end component; |
|
|
signal jbc_mux : std_logic_vector(jpc_width downto 0); |
signal jbc_q : std_logic_vector(7 downto 0); |
|
signal jpc : std_logic_vector(jpc_width downto 0); |
signal jpc_br : std_logic_vector(jpc_width downto 0); |
signal jmp_addr : std_logic_vector(jpc_width downto 0); |
|
signal jinstr : std_logic_vector(7 downto 0); |
signal tp : std_logic_vector(3 downto 0); |
signal jmp : std_logic; |
|
signal jopd : std_logic_vector(15 downto 0); |
|
-- |
-- signals for interrupt handling |
-- |
signal int_pend : std_logic; |
signal int_req : std_logic; |
signal int_taken : std_logic; |
|
signal exc_pend : std_logic; |
signal exc_taken : std_logic; |
|
signal bytecode : std_logic_vector(7 downto 0); |
|
-- synthesis translate_off |
-- synthesis translate_on |
|
begin |
|
-- |
-- interrupt processing at bytecode fetch level |
-- |
process(clk, reset) begin |
|
if (reset='1') then |
int_pend <= '0'; |
exc_pend <= '0'; |
|
elsif rising_edge(clk) then |
|
if irq_in.irq='1' then |
int_pend <= '1'; |
elsif int_taken='1' then |
int_pend <= '0'; |
end if; |
|
if irq_in.exc='1' then |
exc_pend <= '1'; |
elsif exc_taken='1' then |
exc_pend <= '0'; |
end if; |
end if; |
|
end process; |
|
-- |
-- TODO: exception and int in the same cycle: int gets lost |
-- |
int_req <= int_pend and irq_in.ena; |
int_taken <= int_req and jfetch; |
exc_taken <= exc_pend and jfetch; |
|
irq_out.ack_irq <= int_taken; |
irq_out.ack_exc <= exc_taken; |
|
-- |
-- bytecode mux on interrupt |
-- jpc is one too high after generating int_taken |
-- this is corrected in jvm.asm |
-- |
|
-- |
-- java byte code fetch and branch |
-- interrupt and exception mux are in jtbl |
-- |
|
bytecode <= jbc_q; -- register this for an additional pipeline stage |
|
cmp_jtbl: jtbl port map(bytecode, int_req, exc_pend, jpaddr); |
|
jbc_addr <= jbc_mux(jpc_width-1 downto 0); |
jbc_q <= jbc_data; |
|
|
-- |
-- decode if and goto byte codes |
-- |
process(clk, jinstr) begin |
|
if rising_edge(clk) then |
case jinstr is |
|
-- when "10011001" => tp <= "1001"; -- ifeq |
-- when "10011010" => tp <= "1010"; -- ifne |
-- when "10011011" => tp <= "1011"; -- iflt |
-- when "10011100" => tp <= "1100"; -- ifge |
-- when "10011101" => tp <= "1101"; -- ifgt |
-- when "10011110" => tp <= "1110"; -- ifle |
|
-- when "10011111" => tp <= "1111"; -- if_icmpeq |
-- when "10100000" => tp <= "0000"; -- if_icmpne |
-- when "10100001" => tp <= "0001"; -- if_icmplt |
-- when "10100010" => tp <= "0010"; -- if_icmpge |
-- when "10100011" => tp <= "0011"; -- if_icmpgt |
-- when "10100100" => tp <= "0100"; -- if_icmple |
|
when "10100101" => tp <= "1111"; -- if_acmpeq |
when "10100110" => tp <= "0000"; -- if_acmpne |
-- when "10100111" => tp <= "0111"; -- goto |
|
when "11000110" => tp <= "1001"; -- ifnull |
when "11000111" => tp <= "1010"; -- ifnonnull |
|
when others => tp <= jinstr(3 downto 0); |
end case; |
end if; |
|
end process; |
|
process(tp, jbr, zf, nf, eq, lt) |
begin |
|
jmp <= '0'; |
if (jbr='1') then |
case tp is |
when "1001" => -- ifeq, ifnull |
if (zf='1') then |
jmp <= '1'; |
end if; |
when "1010" => -- ifne, ifnonnull |
if (zf='0') then |
jmp <= '1'; |
end if; |
when "1011" => -- iflt |
if (nf='1') then |
jmp <= '1'; |
end if; |
when "1100" => -- ifge |
if (nf='0') then |
jmp <= '1'; |
end if; |
when "1101" => -- ifgt |
if (zf='0' and nf='0') then |
jmp <= '1'; |
end if; |
when "1110" => -- ifle |
if (zf='1' or nf='1') then |
jmp <= '1'; |
end if; |
|
when "1111" => -- if_icmpeq, if_acmpeq |
if (eq='1') then |
jmp <= '1'; |
end if; |
when "0000" => -- if_icmpne, if_acmpne |
if (eq='0') then |
jmp <= '1'; |
end if; |
when "0001" => -- if_icmplt |
if (lt='1') then |
jmp <= '1'; |
end if; |
when "0010" => -- if_icmpge |
if (lt='0') then |
jmp <= '1'; |
end if; |
when "0011" => -- if_icmpgt |
if (eq='0' and lt='0') then |
jmp <= '1'; |
end if; |
when "0100" => -- if_icmple |
if (eq='1' or lt='1') then |
jmp <= '1'; |
end if; |
|
when "0111" => -- goto |
jmp <= '1'; |
|
when others => |
null; |
end case; |
end if; |
|
end process; |
|
-- |
-- jbc read address mux (is registered in ram) |
-- no write from din |
-- |
process(din, jpc, jmp_addr, jopd, jfetch, jopdfetch, jmp) |
|
begin |
|
if (jmp='1') then |
jbc_mux <= jmp_addr; |
elsif (jfetch='1' or jopdfetch='1') then |
jbc_mux <= std_logic_vector(unsigned(jpc) + 1); |
else |
jbc_mux <= jpc; |
end if; |
|
end process; |
|
-- |
-- jpc mux conatins also din |
-- |
process(clk, reset) |
|
begin |
if (reset='1') then |
|
jpc <= std_logic_vector(to_unsigned(0, jpc_width+1)); |
|
elsif rising_edge(clk) then |
|
if (jpc_wr='1') then |
jpc <= din(jpc_width downto 0); |
elsif (jmp='1') then |
jpc <= jmp_addr; |
elsif (jfetch='1' or jopdfetch='1') then |
jpc <= std_logic_vector(unsigned(jpc) + 1); |
else |
jpc <= jpc; |
end if; |
|
end if; |
end process; |
|
jpc_out <= jpc; |
|
|
-- |
-- use this without register |
-- |
-- jmp_addr <= std_logic_vector(unsigned(jpc_br) + |
-- unsigned(jopd(jpc_width-1 downto 0))); |
|
process(clk) |
begin |
if rising_edge(clk) then |
|
-- from jbc_q + jopd low! |
jmp_addr <= std_logic_vector(unsigned(jpc_br) + |
unsigned(jopd(jpc_width-8 downto 0) & jbc_q)); |
|
if (jfetch='1') then |
jpc_br <= jpc; -- save start address of instruction for branch |
jinstr <= jbc_q; |
end if; |
|
end if; |
end process; |
|
process(clk, reset) |
|
begin |
if (reset='1') then |
jopd <= (others => '0'); |
elsif rising_edge(clk) then |
jopd(7 downto 0) <= jbc_q; |
if (jopdfetch='1') then |
jopd(15 downto 8) <= jopd(7 downto 0); |
end if; |
end if; |
end process; |
|
opd <= jopd; |
|
-- synthesis translate_off |
-- show jinstr with bytecode mnemonic |
bc: entity work.bytecode port map(jinstr); |
-- synthesis translate_on |
|
end rtl; |
|