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

Subversion Repositories lxp32

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /lxp32/trunk/verify/lxp32/src/platform
    from Rev 9 to Rev 6
    Reverse comparison

Rev 9 → Rev 6

/dbus_monitor.vhd
1,117 → 1,117
---------------------------------------------------------------------
-- DBUS monitor
--
-- Part of the LXP32 test platform
--
-- Copyright (c) 2016 by Alex I. Kuznetsov
--
-- Monitors LXP32 data bus transactions, optionally throttles them.
--
-- Note: regardless of whether this description is synthesizable,
-- it was designed exclusively for simulation purposes.
---------------------------------------------------------------------
 
library ieee;
use ieee.std_logic_1164.all;
 
entity dbus_monitor is
generic(
THROTTLE: boolean
);
port(
clk_i: in std_logic;
rst_i: in std_logic;
wbs_cyc_i: in std_logic;
wbs_stb_i: in std_logic;
wbs_we_i: in std_logic;
wbs_sel_i: in std_logic_vector(3 downto 0);
wbs_ack_o: out std_logic;
wbs_adr_i: in std_logic_vector(31 downto 2);
wbs_dat_i: in std_logic_vector(31 downto 0);
wbs_dat_o: out std_logic_vector(31 downto 0);
wbm_cyc_o: out std_logic;
wbm_stb_o: out std_logic;
wbm_we_o: out std_logic;
wbm_sel_o: out std_logic_vector(3 downto 0);
wbm_ack_i: in std_logic;
wbm_adr_o: out std_logic_vector(31 downto 2);
wbm_dat_o: out std_logic_vector(31 downto 0);
wbm_dat_i: in std_logic_vector(31 downto 0)
);
end entity;
 
architecture rtl of dbus_monitor is
 
signal prbs: std_logic;
signal cycle: std_logic:='0';
 
signal cyc_ff: std_logic:='0';
signal ack_ff: std_logic:='0';
 
begin
 
-- Manage throttling
 
gen_throttling: if THROTTLE generate
throttle_inst: entity work.scrambler(rtl)
generic map(TAP1=>6,TAP2=>7)
port map(clk_i=>clk_i,rst_i=>rst_i,ce_i=>'1',d_o=>prbs);
end generate;
 
gen_no_throttling: if not THROTTLE generate
prbs<='0';
end generate;
 
-- CPU interface
 
wbs_ack_o<=wbm_ack_i;
wbs_dat_o<=wbm_dat_i when wbm_ack_i='1' else (others=>'-');
 
-- Interconnect interface
 
process (clk_i) is
begin
if rising_edge(clk_i) then
if rst_i='1' then
cycle<='0';
elsif prbs='0' and wbs_cyc_i='1' then
cycle<='1';
elsif wbs_cyc_i='0' then
cycle<='0';
end if;
end if;
end process;
 
wbm_cyc_o<=wbs_cyc_i and (not prbs or cycle);
wbm_stb_o<=wbs_stb_i and (not prbs or cycle);
wbm_we_o<=wbs_we_i;
wbm_sel_o<=wbs_sel_i;
wbm_adr_o<=wbs_adr_i;
wbm_dat_o<=wbs_dat_i;
 
-- Check handshake correctness
 
process (clk_i) is
begin
if rising_edge(clk_i) then
if rst_i='1' then
cyc_ff<='0';
ack_ff<='0';
else
cyc_ff<=wbs_cyc_i;
ack_ff<=wbm_ack_i;
assert wbm_ack_i='0' or (wbs_cyc_i and (not prbs or cycle))='1'
report "DBUS error: ACK asserted without CYC"
severity failure;
assert not (wbs_cyc_i='0' and cyc_ff='1' and ack_ff/='1')
report "DBUS error: cycle terminated prematurely"
severity failure;
end if;
end if;
end process;
 
end architecture;
---------------------------------------------------------------------
-- DBUS monitor
--
-- Part of the LXP32 test platform
--
-- Copyright (c) 2016 by Alex I. Kuznetsov
--
-- Monitors LXP32 data bus transactions, optionally throttles them.
--
-- Note: regardless of whether this description is synthesizable,
-- it was designed exclusively for simulation purposes.
---------------------------------------------------------------------
 
library ieee;
use ieee.std_logic_1164.all;
 
entity dbus_monitor is
generic(
THROTTLE: boolean
);
port(
clk_i: in std_logic;
rst_i: in std_logic;
wbs_cyc_i: in std_logic;
wbs_stb_i: in std_logic;
wbs_we_i: in std_logic;
wbs_sel_i: in std_logic_vector(3 downto 0);
wbs_ack_o: out std_logic;
wbs_adr_i: in std_logic_vector(31 downto 2);
wbs_dat_i: in std_logic_vector(31 downto 0);
wbs_dat_o: out std_logic_vector(31 downto 0);
wbm_cyc_o: out std_logic;
wbm_stb_o: out std_logic;
wbm_we_o: out std_logic;
wbm_sel_o: out std_logic_vector(3 downto 0);
wbm_ack_i: in std_logic;
wbm_adr_o: out std_logic_vector(31 downto 2);
wbm_dat_o: out std_logic_vector(31 downto 0);
wbm_dat_i: in std_logic_vector(31 downto 0)
);
end entity;
 
architecture rtl of dbus_monitor is
 
signal prbs: std_logic;
signal cycle: std_logic:='0';
 
signal cyc_ff: std_logic:='0';
signal ack_ff: std_logic:='0';
 
begin
 
-- Manage throttling
 
gen_throttling: if THROTTLE generate
throttle_inst: entity work.scrambler(rtl)
generic map(TAP1=>6,TAP2=>7)
port map(clk_i=>clk_i,rst_i=>rst_i,ce_i=>'1',d_o=>prbs);
end generate;
 
gen_no_throttling: if not THROTTLE generate
prbs<='0';
end generate;
 
-- CPU interface
 
wbs_ack_o<=wbm_ack_i;
wbs_dat_o<=wbm_dat_i when wbm_ack_i='1' else (others=>'-');
 
-- Interconnect interface
 
process (clk_i) is
begin
if rising_edge(clk_i) then
if rst_i='1' then
cycle<='0';
elsif prbs='0' and wbs_cyc_i='1' then
cycle<='1';
elsif wbs_cyc_i='0' then
cycle<='0';
end if;
end if;
end process;
 
wbm_cyc_o<=wbs_cyc_i and (not prbs or cycle);
wbm_stb_o<=wbs_stb_i and (not prbs or cycle);
wbm_we_o<=wbs_we_i;
wbm_sel_o<=wbs_sel_i;
wbm_adr_o<=wbs_adr_i;
wbm_dat_o<=wbs_dat_i;
 
-- Check handshake correctness
 
process (clk_i) is
begin
if rising_edge(clk_i) then
if rst_i='1' then
cyc_ff<='0';
ack_ff<='0';
else
cyc_ff<=wbs_cyc_i;
ack_ff<=wbm_ack_i;
assert wbm_ack_i='0' or (wbs_cyc_i and (not prbs or cycle))='1'
report "DBUS error: ACK asserted without CYC"
severity failure;
assert not (wbs_cyc_i='0' and cyc_ff='1' and ack_ff/='1')
report "DBUS error: cycle terminated prematurely"
severity failure;
end if;
end if;
end process;
 
end architecture;
/generic_dpram.vhd
1,162 → 1,162
---------------------------------------------------------------------
-- Generic FPGA memory block
--
-- Copyright (c) 2015 by Alex I. Kuznetsov
--
-- Portable description of a dual-port memory block with one write
-- port.
--
-- Parameters:
-- * DATA_WIDTH: data port width
-- * ADDR_WIDTH: address port width
-- * SIZE: memory size
-- * MODE: read/write synchronization mode for port A
-- DONTCARE: choose the most efficient design
-- WR_FIRST: feed written value to the output
-- RD_FIRST: read old value
-- NOCHANGE: don't change output during write
---------------------------------------------------------------------
 
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
 
entity generic_dpram is
generic(
DATA_WIDTH: integer;
ADDR_WIDTH: integer;
SIZE: integer;
MODE: string:="DONTCARE"
);
port(
clka_i: in std_logic;
cea_i: in std_logic;
wea_i: in std_logic;
addra_i: in std_logic_vector(ADDR_WIDTH-1 downto 0);
da_i: in std_logic_vector(DATA_WIDTH-1 downto 0);
da_o: out std_logic_vector(DATA_WIDTH-1 downto 0);
clkb_i: in std_logic;
ceb_i: in std_logic;
addrb_i: in std_logic_vector(ADDR_WIDTH-1 downto 0);
db_o: out std_logic_vector(DATA_WIDTH-1 downto 0)
);
end entity;
 
architecture rtl of generic_dpram is
 
type ram_type is array(SIZE-1 downto 0) of std_logic_vector(DATA_WIDTH-1 downto 0);
signal ram: ram_type;
 
attribute syn_ramstyle: string;
attribute syn_ramstyle of ram: signal is "no_rw_check";
attribute ram_style: string; -- for Xilinx
attribute ram_style of ram: signal is "block";
 
begin
 
-- Ensure that generics have valid values
 
assert SIZE<=2**ADDR_WIDTH
report "SIZE must be less or equal than 2^ADDR_WIDTH"
severity failure;
 
assert MODE="DONTCARE" or MODE="WR_FIRST" or MODE="RD_FIRST" or MODE="NOCHANGE"
report "Unrecognized MODE value (DONTCARE, WR_FIRST, RD_FIRST or NOCHANGE expected)"
severity failure;
 
-- Port A (read/write)
 
port_a_dont_care_gen: if MODE="DONTCARE" generate
process (clka_i) is
begin
if rising_edge(clka_i) then
if cea_i='1' then
if wea_i='1' then
ram(to_integer(unsigned(addra_i)))<=da_i;
da_o<=(others=>'-');
else
if is_x(addra_i) then
da_o<=(others=>'X');
else
da_o<=ram(to_integer(unsigned(addra_i)));
end if;
end if;
end if;
end if;
end process;
end generate;
 
port_a_write_first_gen: if MODE="WR_FIRST" generate
process (clka_i) is
begin
if rising_edge(clka_i) then
if cea_i='1' then
if wea_i='1' then
ram(to_integer(unsigned(addra_i)))<=da_i;
da_o<=da_i;
else
if is_x(addra_i) then
da_o<=(others=>'X');
else
da_o<=ram(to_integer(unsigned(addra_i)));
end if;
end if;
end if;
end if;
end process;
end generate;
 
port_a_read_first_gen: if MODE="RD_FIRST" generate
process (clka_i) is
begin
if rising_edge(clka_i) then
if cea_i='1' then
if wea_i='1' then
ram(to_integer(unsigned(addra_i)))<=da_i;
end if;
if is_x(addra_i) then
da_o<=(others=>'X');
else
da_o<=ram(to_integer(unsigned(addra_i)));
end if;
end if;
end if;
end process;
end generate;
 
port_a_no_change_gen: if MODE="NOCHANGE" generate
process (clka_i) is
begin
if rising_edge(clka_i) then
if cea_i='1' then
if wea_i='1' then
ram(to_integer(unsigned(addra_i)))<=da_i;
else
if is_x(addra_i) then
da_o<=(others=>'X');
else
da_o<=ram(to_integer(unsigned(addra_i)));
end if;
end if;
end if;
end if;
end process;
end generate;
 
-- Port B (read only)
 
process (clkb_i) is
begin
if rising_edge(clkb_i) then
if ceb_i='1' then
if is_x(addrb_i) then
db_o<=(others=>'X');
else
db_o<=ram(to_integer(unsigned(addrb_i)));
end if;
end if;
end if;
end process;
 
end architecture;
---------------------------------------------------------------------
-- Generic FPGA memory block
--
-- Copyright (c) 2015 by Alex I. Kuznetsov
--
-- Portable description of a dual-port memory block with one write
-- port.
--
-- Parameters:
-- * DATA_WIDTH: data port width
-- * ADDR_WIDTH: address port width
-- * SIZE: memory size
-- * MODE: read/write synchronization mode for port A
-- DONTCARE: choose the most efficient design
-- WR_FIRST: feed written value to the output
-- RD_FIRST: read old value
-- NOCHANGE: don't change output during write
---------------------------------------------------------------------
 
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
 
entity generic_dpram is
generic(
DATA_WIDTH: integer;
ADDR_WIDTH: integer;
SIZE: integer;
MODE: string:="DONTCARE"
);
port(
clka_i: in std_logic;
cea_i: in std_logic;
wea_i: in std_logic;
addra_i: in std_logic_vector(ADDR_WIDTH-1 downto 0);
da_i: in std_logic_vector(DATA_WIDTH-1 downto 0);
da_o: out std_logic_vector(DATA_WIDTH-1 downto 0);
clkb_i: in std_logic;
ceb_i: in std_logic;
addrb_i: in std_logic_vector(ADDR_WIDTH-1 downto 0);
db_o: out std_logic_vector(DATA_WIDTH-1 downto 0)
);
end entity;
 
architecture rtl of generic_dpram is
 
type ram_type is array(SIZE-1 downto 0) of std_logic_vector(DATA_WIDTH-1 downto 0);
signal ram: ram_type;
 
attribute syn_ramstyle: string;
attribute syn_ramstyle of ram: signal is "no_rw_check";
attribute ram_style: string; -- for Xilinx
attribute ram_style of ram: signal is "block";
 
begin
 
-- Ensure that generics have valid values
 
assert SIZE<=2**ADDR_WIDTH
report "SIZE must be less or equal than 2^ADDR_WIDTH"
severity failure;
 
assert MODE="DONTCARE" or MODE="WR_FIRST" or MODE="RD_FIRST" or MODE="NOCHANGE"
report "Unrecognized MODE value (DONTCARE, WR_FIRST, RD_FIRST or NOCHANGE expected)"
severity failure;
 
-- Port A (read/write)
 
port_a_dont_care_gen: if MODE="DONTCARE" generate
process (clka_i) is
begin
if rising_edge(clka_i) then
if cea_i='1' then
if wea_i='1' then
ram(to_integer(unsigned(addra_i)))<=da_i;
da_o<=(others=>'-');
else
if is_x(addra_i) then
da_o<=(others=>'X');
else
da_o<=ram(to_integer(unsigned(addra_i)));
end if;
end if;
end if;
end if;
end process;
end generate;
 
port_a_write_first_gen: if MODE="WR_FIRST" generate
process (clka_i) is
begin
if rising_edge(clka_i) then
if cea_i='1' then
if wea_i='1' then
ram(to_integer(unsigned(addra_i)))<=da_i;
da_o<=da_i;
else
if is_x(addra_i) then
da_o<=(others=>'X');
else
da_o<=ram(to_integer(unsigned(addra_i)));
end if;
end if;
end if;
end if;
end process;
end generate;
 
port_a_read_first_gen: if MODE="RD_FIRST" generate
process (clka_i) is
begin
if rising_edge(clka_i) then
if cea_i='1' then
if wea_i='1' then
ram(to_integer(unsigned(addra_i)))<=da_i;
end if;
if is_x(addra_i) then
da_o<=(others=>'X');
else
da_o<=ram(to_integer(unsigned(addra_i)));
end if;
end if;
end if;
end process;
end generate;
 
port_a_no_change_gen: if MODE="NOCHANGE" generate
process (clka_i) is
begin
if rising_edge(clka_i) then
if cea_i='1' then
if wea_i='1' then
ram(to_integer(unsigned(addra_i)))<=da_i;
else
if is_x(addra_i) then
da_o<=(others=>'X');
else
da_o<=ram(to_integer(unsigned(addra_i)));
end if;
end if;
end if;
end if;
end process;
end generate;
 
-- Port B (read only)
 
process (clkb_i) is
begin
if rising_edge(clkb_i) then
if ceb_i='1' then
if is_x(addrb_i) then
db_o<=(others=>'X');
else
db_o<=ram(to_integer(unsigned(addrb_i)));
end if;
end if;
end if;
end process;
 
end architecture;
/platform.vhd
1,356 → 1,356
---------------------------------------------------------------------
-- LXP32 platform top-level design unit
--
-- Part of the LXP32 test platform
--
-- Copyright (c) 2016 by Alex I. Kuznetsov
--
-- A SoC-like simulation platform for the LXP32 CPU, containing
-- a few peripherals such as program RAM, timer and coprocessor.
--
-- Note: regardless of whether this description is synthesizable,
-- it was designed exclusively for simulation purposes.
---------------------------------------------------------------------
 
library ieee;
use ieee.std_logic_1164.all;
 
entity platform is
generic(
CPU_DBUS_RMW: boolean;
CPU_MUL_ARCH: string;
MODEL_LXP32C: boolean;
THROTTLE_DBUS: boolean;
THROTTLE_IBUS: boolean
);
port(
clk_i: in std_logic;
rst_i: in std_logic;
cpu_rst_i: in std_logic;
wbm_cyc_o: out std_logic;
wbm_stb_o: out std_logic;
wbm_we_o: out std_logic;
wbm_sel_o: out std_logic_vector(3 downto 0);
wbm_ack_i: in std_logic;
wbm_adr_o: out std_logic_vector(27 downto 2);
wbm_dat_o: out std_logic_vector(31 downto 0);
wbm_dat_i: in std_logic_vector(31 downto 0);
wbs_cyc_i: in std_logic;
wbs_stb_i: in std_logic;
wbs_we_i: in std_logic;
wbs_sel_i: in std_logic_vector(3 downto 0);
wbs_ack_o: out std_logic;
wbs_adr_i: in std_logic_vector(31 downto 2);
wbs_dat_i: in std_logic_vector(31 downto 0);
wbs_dat_o: out std_logic_vector(31 downto 0);
gp_io: inout std_logic_vector(31 downto 0)
);
end entity;
 
architecture rtl of platform is
 
type wbm_type is record
cyc: std_logic;
stb: std_logic;
we: std_logic;
sel: std_logic_vector(3 downto 0);
ack: std_logic;
adr: std_logic_vector(31 downto 2);
wdata: std_logic_vector(31 downto 0);
rdata: std_logic_vector(31 downto 0);
end record;
 
type wbs_type is record
cyc: std_logic;
stb: std_logic;
we: std_logic;
sel: std_logic_vector(3 downto 0);
ack: std_logic;
adr: std_logic_vector(27 downto 2);
wdata: std_logic_vector(31 downto 0);
rdata: std_logic_vector(31 downto 0);
end record;
 
type ibus_type is record
cyc: std_logic;
stb: std_logic;
cti: std_logic_vector(2 downto 0);
bte: std_logic_vector(1 downto 0);
ack: std_logic;
adr: std_logic_vector(29 downto 0);
dat: std_logic_vector(31 downto 0);
end record;
 
signal cpu_rst: std_logic;
signal cpu_irq: std_logic_vector(7 downto 0);
signal cpu_dbus: wbm_type;
signal cpu_ibus: ibus_type;
 
signal lli_re: std_logic;
signal lli_adr: std_logic_vector(29 downto 0);
signal lli_dat: std_logic_vector(31 downto 0);
signal lli_busy: std_logic;
 
signal monitor_dbus: wbm_type;
 
signal ram_wb: wbs_type;
 
signal timer_wb: wbs_type;
signal timer_elapsed: std_logic;
 
signal coprocessor_wb: wbs_type;
signal coprocessor_irq: std_logic;
 
begin
 
-- Interconnect
 
intercon_inst: entity work.intercon(rtl)
port map(
clk_i=>clk_i,
rst_i=>rst_i,
 
s0_cyc_i=>wbs_cyc_i,
s0_stb_i=>wbs_stb_i,
s0_we_i=>wbs_we_i,
s0_sel_i=>wbs_sel_i,
s0_ack_o=>wbs_ack_o,
s0_adr_i=>wbs_adr_i,
s0_dat_i=>wbs_dat_i,
s0_dat_o=>wbs_dat_o,
 
s1_cyc_i=>monitor_dbus.cyc,
s1_stb_i=>monitor_dbus.stb,
s1_we_i=>monitor_dbus.we,
s1_sel_i=>monitor_dbus.sel,
s1_ack_o=>monitor_dbus.ack,
s1_adr_i=>monitor_dbus.adr,
s1_dat_i=>monitor_dbus.wdata,
s1_dat_o=>monitor_dbus.rdata,
 
m0_cyc_o=>ram_wb.cyc,
m0_stb_o=>ram_wb.stb,
m0_we_o=>ram_wb.we,
m0_sel_o=>ram_wb.sel,
m0_ack_i=>ram_wb.ack,
m0_adr_o=>ram_wb.adr,
m0_dat_o=>ram_wb.wdata,
m0_dat_i=>ram_wb.rdata,
 
m1_cyc_o=>wbm_cyc_o,
m1_stb_o=>wbm_stb_o,
m1_we_o=>wbm_we_o,
m1_sel_o=>wbm_sel_o,
m1_ack_i=>wbm_ack_i,
m1_adr_o=>wbm_adr_o,
m1_dat_o=>wbm_dat_o,
m1_dat_i=>wbm_dat_i,
m2_cyc_o=>timer_wb.cyc,
m2_stb_o=>timer_wb.stb,
m2_we_o=>timer_wb.we,
m2_sel_o=>timer_wb.sel,
m2_ack_i=>timer_wb.ack,
m2_adr_o=>timer_wb.adr,
m2_dat_o=>timer_wb.wdata,
m2_dat_i=>timer_wb.rdata,
m3_cyc_o=>coprocessor_wb.cyc,
m3_stb_o=>coprocessor_wb.stb,
m3_we_o=>coprocessor_wb.we,
m3_sel_o=>coprocessor_wb.sel,
m3_ack_i=>coprocessor_wb.ack,
m3_adr_o=>coprocessor_wb.adr,
m3_dat_o=>coprocessor_wb.wdata,
m3_dat_i=>coprocessor_wb.rdata
);
 
-- CPU
 
cpu_rst<=cpu_rst_i or rst_i;
 
-- Note: we connect the timer IRQ to 2 CPU channels to test
-- handling of simultaneously arriving interrupt requests.
 
cpu_irq<="00000"&coprocessor_irq&timer_elapsed&timer_elapsed;
 
gen_lxp32u: if not MODEL_LXP32C generate
lxp32u_top_inst: entity work.lxp32u_top(rtl)
generic map(
DBUS_RMW=>CPU_DBUS_RMW,
DIVIDER_EN=>true,
MUL_ARCH=>CPU_MUL_ARCH,
START_ADDR=>(others=>'0')
)
port map(
clk_i=>clk_i,
rst_i=>cpu_rst,
lli_re_o=>lli_re,
lli_adr_o=>lli_adr,
lli_dat_i=>lli_dat,
lli_busy_i=>lli_busy,
dbus_cyc_o=>cpu_dbus.cyc,
dbus_stb_o=>cpu_dbus.stb,
dbus_we_o=>cpu_dbus.we,
dbus_sel_o=>cpu_dbus.sel,
dbus_ack_i=>cpu_dbus.ack,
dbus_adr_o=>cpu_dbus.adr,
dbus_dat_o=>cpu_dbus.wdata,
dbus_dat_i=>cpu_dbus.rdata,
irq_i=>cpu_irq
);
end generate;
 
gen_lxp32c: if MODEL_LXP32C generate
lxp32c_top_inst: entity work.lxp32c_top(rtl)
generic map(
DBUS_RMW=>CPU_DBUS_RMW,
DIVIDER_EN=>true,
IBUS_BURST_SIZE=>16,
IBUS_PREFETCH_SIZE=>32,
MUL_ARCH=>CPU_MUL_ARCH,
START_ADDR=>(others=>'0')
)
port map(
clk_i=>clk_i,
rst_i=>cpu_rst,
ibus_cyc_o=>cpu_ibus.cyc,
ibus_stb_o=>cpu_ibus.stb,
ibus_cti_o=>cpu_ibus.cti,
ibus_bte_o=>cpu_ibus.bte,
ibus_ack_i=>cpu_ibus.ack,
ibus_adr_o=>cpu_ibus.adr,
ibus_dat_i=>cpu_ibus.dat,
dbus_cyc_o=>cpu_dbus.cyc,
dbus_stb_o=>cpu_dbus.stb,
dbus_we_o=>cpu_dbus.we,
dbus_sel_o=>cpu_dbus.sel,
dbus_ack_i=>cpu_dbus.ack,
dbus_adr_o=>cpu_dbus.adr,
dbus_dat_o=>cpu_dbus.wdata,
dbus_dat_i=>cpu_dbus.rdata,
irq_i=>cpu_irq
);
ibus_adapter_inst: entity work.ibus_adapter(rtl)
port map(
clk_i=>clk_i,
rst_i=>rst_i,
ibus_cyc_i=>cpu_ibus.cyc,
ibus_stb_i=>cpu_ibus.stb,
ibus_cti_i=>cpu_ibus.cti,
ibus_bte_i=>cpu_ibus.bte,
ibus_ack_o=>cpu_ibus.ack,
ibus_adr_i=>cpu_ibus.adr,
ibus_dat_o=>cpu_ibus.dat,
lli_re_o=>lli_re,
lli_adr_o=>lli_adr,
lli_dat_i=>lli_dat,
lli_busy_i=>lli_busy
);
end generate;
 
-- DBUS monitor
 
dbus_monitor_inst: entity work.dbus_monitor(rtl)
generic map(
THROTTLE=>THROTTLE_DBUS
)
port map(
clk_i=>clk_i,
rst_i=>rst_i,
wbs_cyc_i=>cpu_dbus.cyc,
wbs_stb_i=>cpu_dbus.stb,
wbs_we_i=>cpu_dbus.we,
wbs_sel_i=>cpu_dbus.sel,
wbs_ack_o=>cpu_dbus.ack,
wbs_adr_i=>cpu_dbus.adr,
wbs_dat_i=>cpu_dbus.wdata,
wbs_dat_o=>cpu_dbus.rdata,
wbm_cyc_o=>monitor_dbus.cyc,
wbm_stb_o=>monitor_dbus.stb,
wbm_we_o=>monitor_dbus.we,
wbm_sel_o=>monitor_dbus.sel,
wbm_ack_i=>monitor_dbus.ack,
wbm_adr_o=>monitor_dbus.adr,
wbm_dat_o=>monitor_dbus.wdata,
wbm_dat_i=>monitor_dbus.rdata
);
 
-- Program RAM
 
program_ram_inst: entity work.program_ram(rtl)
generic map(
THROTTLE=>THROTTLE_IBUS
)
port map(
clk_i=>clk_i,
rst_i=>rst_i,
wbs_cyc_i=>ram_wb.cyc,
wbs_stb_i=>ram_wb.stb,
wbs_we_i=>ram_wb.we,
wbs_sel_i=>ram_wb.sel,
wbs_ack_o=>ram_wb.ack,
wbs_adr_i=>ram_wb.adr,
wbs_dat_i=>ram_wb.wdata,
wbs_dat_o=>ram_wb.rdata,
lli_re_i=>lli_re,
lli_adr_i=>lli_adr,
lli_dat_o=>lli_dat,
lli_busy_o=>lli_busy
);
 
-- Timer
 
timer_inst: entity work.timer(rtl)
port map(
clk_i=>clk_i,
rst_i=>rst_i,
wbs_cyc_i=>timer_wb.cyc,
wbs_stb_i=>timer_wb.stb,
wbs_we_i=>timer_wb.we,
wbs_sel_i=>timer_wb.sel,
wbs_ack_o=>timer_wb.ack,
wbs_adr_i=>timer_wb.adr,
wbs_dat_i=>timer_wb.wdata,
wbs_dat_o=>timer_wb.rdata,
elapsed_o=>timer_elapsed
);
 
-- Coprocessor
 
coprocessor_inst: entity work.coprocessor(rtl)
port map(
clk_i=>clk_i,
rst_i=>rst_i,
wbs_cyc_i=>coprocessor_wb.cyc,
wbs_stb_i=>coprocessor_wb.stb,
wbs_we_i=>coprocessor_wb.we,
wbs_sel_i=>coprocessor_wb.sel,
wbs_ack_o=>coprocessor_wb.ack,
wbs_adr_i=>coprocessor_wb.adr,
wbs_dat_i=>coprocessor_wb.wdata,
wbs_dat_o=>coprocessor_wb.rdata,
irq_o=>coprocessor_irq
);
 
end architecture;
---------------------------------------------------------------------
-- LXP32 platform top-level design unit
--
-- Part of the LXP32 test platform
--
-- Copyright (c) 2016 by Alex I. Kuznetsov
--
-- A SoC-like simulation platform for the LXP32 CPU, containing
-- a few peripherals such as program RAM, timer and coprocessor.
--
-- Note: regardless of whether this description is synthesizable,
-- it was designed exclusively for simulation purposes.
---------------------------------------------------------------------
 
library ieee;
use ieee.std_logic_1164.all;
 
entity platform is
generic(
CPU_DBUS_RMW: boolean;
CPU_MUL_ARCH: string;
MODEL_LXP32C: boolean;
THROTTLE_DBUS: boolean;
THROTTLE_IBUS: boolean
);
port(
clk_i: in std_logic;
rst_i: in std_logic;
cpu_rst_i: in std_logic;
wbm_cyc_o: out std_logic;
wbm_stb_o: out std_logic;
wbm_we_o: out std_logic;
wbm_sel_o: out std_logic_vector(3 downto 0);
wbm_ack_i: in std_logic;
wbm_adr_o: out std_logic_vector(27 downto 2);
wbm_dat_o: out std_logic_vector(31 downto 0);
wbm_dat_i: in std_logic_vector(31 downto 0);
wbs_cyc_i: in std_logic;
wbs_stb_i: in std_logic;
wbs_we_i: in std_logic;
wbs_sel_i: in std_logic_vector(3 downto 0);
wbs_ack_o: out std_logic;
wbs_adr_i: in std_logic_vector(31 downto 2);
wbs_dat_i: in std_logic_vector(31 downto 0);
wbs_dat_o: out std_logic_vector(31 downto 0);
gp_io: inout std_logic_vector(31 downto 0)
);
end entity;
 
architecture rtl of platform is
 
type wbm_type is record
cyc: std_logic;
stb: std_logic;
we: std_logic;
sel: std_logic_vector(3 downto 0);
ack: std_logic;
adr: std_logic_vector(31 downto 2);
wdata: std_logic_vector(31 downto 0);
rdata: std_logic_vector(31 downto 0);
end record;
 
type wbs_type is record
cyc: std_logic;
stb: std_logic;
we: std_logic;
sel: std_logic_vector(3 downto 0);
ack: std_logic;
adr: std_logic_vector(27 downto 2);
wdata: std_logic_vector(31 downto 0);
rdata: std_logic_vector(31 downto 0);
end record;
 
type ibus_type is record
cyc: std_logic;
stb: std_logic;
cti: std_logic_vector(2 downto 0);
bte: std_logic_vector(1 downto 0);
ack: std_logic;
adr: std_logic_vector(29 downto 0);
dat: std_logic_vector(31 downto 0);
end record;
 
signal cpu_rst: std_logic;
signal cpu_irq: std_logic_vector(7 downto 0);
signal cpu_dbus: wbm_type;
signal cpu_ibus: ibus_type;
 
signal lli_re: std_logic;
signal lli_adr: std_logic_vector(29 downto 0);
signal lli_dat: std_logic_vector(31 downto 0);
signal lli_busy: std_logic;
 
signal monitor_dbus: wbm_type;
 
signal ram_wb: wbs_type;
 
signal timer_wb: wbs_type;
signal timer_elapsed: std_logic;
 
signal coprocessor_wb: wbs_type;
signal coprocessor_irq: std_logic;
 
begin
 
-- Interconnect
 
intercon_inst: entity work.intercon(rtl)
port map(
clk_i=>clk_i,
rst_i=>rst_i,
 
s0_cyc_i=>wbs_cyc_i,
s0_stb_i=>wbs_stb_i,
s0_we_i=>wbs_we_i,
s0_sel_i=>wbs_sel_i,
s0_ack_o=>wbs_ack_o,
s0_adr_i=>wbs_adr_i,
s0_dat_i=>wbs_dat_i,
s0_dat_o=>wbs_dat_o,
 
s1_cyc_i=>monitor_dbus.cyc,
s1_stb_i=>monitor_dbus.stb,
s1_we_i=>monitor_dbus.we,
s1_sel_i=>monitor_dbus.sel,
s1_ack_o=>monitor_dbus.ack,
s1_adr_i=>monitor_dbus.adr,
s1_dat_i=>monitor_dbus.wdata,
s1_dat_o=>monitor_dbus.rdata,
 
m0_cyc_o=>ram_wb.cyc,
m0_stb_o=>ram_wb.stb,
m0_we_o=>ram_wb.we,
m0_sel_o=>ram_wb.sel,
m0_ack_i=>ram_wb.ack,
m0_adr_o=>ram_wb.adr,
m0_dat_o=>ram_wb.wdata,
m0_dat_i=>ram_wb.rdata,
 
m1_cyc_o=>wbm_cyc_o,
m1_stb_o=>wbm_stb_o,
m1_we_o=>wbm_we_o,
m1_sel_o=>wbm_sel_o,
m1_ack_i=>wbm_ack_i,
m1_adr_o=>wbm_adr_o,
m1_dat_o=>wbm_dat_o,
m1_dat_i=>wbm_dat_i,
m2_cyc_o=>timer_wb.cyc,
m2_stb_o=>timer_wb.stb,
m2_we_o=>timer_wb.we,
m2_sel_o=>timer_wb.sel,
m2_ack_i=>timer_wb.ack,
m2_adr_o=>timer_wb.adr,
m2_dat_o=>timer_wb.wdata,
m2_dat_i=>timer_wb.rdata,
m3_cyc_o=>coprocessor_wb.cyc,
m3_stb_o=>coprocessor_wb.stb,
m3_we_o=>coprocessor_wb.we,
m3_sel_o=>coprocessor_wb.sel,
m3_ack_i=>coprocessor_wb.ack,
m3_adr_o=>coprocessor_wb.adr,
m3_dat_o=>coprocessor_wb.wdata,
m3_dat_i=>coprocessor_wb.rdata
);
 
-- CPU
 
cpu_rst<=cpu_rst_i or rst_i;
 
-- Note: we connect the timer IRQ to 2 CPU channels to test
-- handling of simultaneously arriving interrupt requests.
 
cpu_irq<="00000"&coprocessor_irq&timer_elapsed&timer_elapsed;
 
gen_lxp32u: if not MODEL_LXP32C generate
lxp32u_top_inst: entity work.lxp32u_top(rtl)
generic map(
DBUS_RMW=>CPU_DBUS_RMW,
DIVIDER_EN=>true,
MUL_ARCH=>CPU_MUL_ARCH,
START_ADDR=>(others=>'0')
)
port map(
clk_i=>clk_i,
rst_i=>cpu_rst,
lli_re_o=>lli_re,
lli_adr_o=>lli_adr,
lli_dat_i=>lli_dat,
lli_busy_i=>lli_busy,
dbus_cyc_o=>cpu_dbus.cyc,
dbus_stb_o=>cpu_dbus.stb,
dbus_we_o=>cpu_dbus.we,
dbus_sel_o=>cpu_dbus.sel,
dbus_ack_i=>cpu_dbus.ack,
dbus_adr_o=>cpu_dbus.adr,
dbus_dat_o=>cpu_dbus.wdata,
dbus_dat_i=>cpu_dbus.rdata,
irq_i=>cpu_irq
);
end generate;
 
gen_lxp32c: if MODEL_LXP32C generate
lxp32c_top_inst: entity work.lxp32c_top(rtl)
generic map(
DBUS_RMW=>CPU_DBUS_RMW,
DIVIDER_EN=>true,
IBUS_BURST_SIZE=>16,
IBUS_PREFETCH_SIZE=>32,
MUL_ARCH=>CPU_MUL_ARCH,
START_ADDR=>(others=>'0')
)
port map(
clk_i=>clk_i,
rst_i=>cpu_rst,
ibus_cyc_o=>cpu_ibus.cyc,
ibus_stb_o=>cpu_ibus.stb,
ibus_cti_o=>cpu_ibus.cti,
ibus_bte_o=>cpu_ibus.bte,
ibus_ack_i=>cpu_ibus.ack,
ibus_adr_o=>cpu_ibus.adr,
ibus_dat_i=>cpu_ibus.dat,
dbus_cyc_o=>cpu_dbus.cyc,
dbus_stb_o=>cpu_dbus.stb,
dbus_we_o=>cpu_dbus.we,
dbus_sel_o=>cpu_dbus.sel,
dbus_ack_i=>cpu_dbus.ack,
dbus_adr_o=>cpu_dbus.adr,
dbus_dat_o=>cpu_dbus.wdata,
dbus_dat_i=>cpu_dbus.rdata,
irq_i=>cpu_irq
);
ibus_adapter_inst: entity work.ibus_adapter(rtl)
port map(
clk_i=>clk_i,
rst_i=>rst_i,
ibus_cyc_i=>cpu_ibus.cyc,
ibus_stb_i=>cpu_ibus.stb,
ibus_cti_i=>cpu_ibus.cti,
ibus_bte_i=>cpu_ibus.bte,
ibus_ack_o=>cpu_ibus.ack,
ibus_adr_i=>cpu_ibus.adr,
ibus_dat_o=>cpu_ibus.dat,
lli_re_o=>lli_re,
lli_adr_o=>lli_adr,
lli_dat_i=>lli_dat,
lli_busy_i=>lli_busy
);
end generate;
 
-- DBUS monitor
 
dbus_monitor_inst: entity work.dbus_monitor(rtl)
generic map(
THROTTLE=>THROTTLE_DBUS
)
port map(
clk_i=>clk_i,
rst_i=>rst_i,
wbs_cyc_i=>cpu_dbus.cyc,
wbs_stb_i=>cpu_dbus.stb,
wbs_we_i=>cpu_dbus.we,
wbs_sel_i=>cpu_dbus.sel,
wbs_ack_o=>cpu_dbus.ack,
wbs_adr_i=>cpu_dbus.adr,
wbs_dat_i=>cpu_dbus.wdata,
wbs_dat_o=>cpu_dbus.rdata,
wbm_cyc_o=>monitor_dbus.cyc,
wbm_stb_o=>monitor_dbus.stb,
wbm_we_o=>monitor_dbus.we,
wbm_sel_o=>monitor_dbus.sel,
wbm_ack_i=>monitor_dbus.ack,
wbm_adr_o=>monitor_dbus.adr,
wbm_dat_o=>monitor_dbus.wdata,
wbm_dat_i=>monitor_dbus.rdata
);
 
-- Program RAM
 
program_ram_inst: entity work.program_ram(rtl)
generic map(
THROTTLE=>THROTTLE_IBUS
)
port map(
clk_i=>clk_i,
rst_i=>rst_i,
wbs_cyc_i=>ram_wb.cyc,
wbs_stb_i=>ram_wb.stb,
wbs_we_i=>ram_wb.we,
wbs_sel_i=>ram_wb.sel,
wbs_ack_o=>ram_wb.ack,
wbs_adr_i=>ram_wb.adr,
wbs_dat_i=>ram_wb.wdata,
wbs_dat_o=>ram_wb.rdata,
lli_re_i=>lli_re,
lli_adr_i=>lli_adr,
lli_dat_o=>lli_dat,
lli_busy_o=>lli_busy
);
 
-- Timer
 
timer_inst: entity work.timer(rtl)
port map(
clk_i=>clk_i,
rst_i=>rst_i,
wbs_cyc_i=>timer_wb.cyc,
wbs_stb_i=>timer_wb.stb,
wbs_we_i=>timer_wb.we,
wbs_sel_i=>timer_wb.sel,
wbs_ack_o=>timer_wb.ack,
wbs_adr_i=>timer_wb.adr,
wbs_dat_i=>timer_wb.wdata,
wbs_dat_o=>timer_wb.rdata,
elapsed_o=>timer_elapsed
);
 
-- Coprocessor
 
coprocessor_inst: entity work.coprocessor(rtl)
port map(
clk_i=>clk_i,
rst_i=>rst_i,
wbs_cyc_i=>coprocessor_wb.cyc,
wbs_stb_i=>coprocessor_wb.stb,
wbs_we_i=>coprocessor_wb.we,
wbs_sel_i=>coprocessor_wb.sel,
wbs_ack_o=>coprocessor_wb.ack,
wbs_adr_i=>coprocessor_wb.adr,
wbs_dat_i=>coprocessor_wb.wdata,
wbs_dat_o=>coprocessor_wb.rdata,
irq_o=>coprocessor_irq
);
 
end architecture;
/program_ram.vhd
1,145 → 1,145
---------------------------------------------------------------------
-- Program RAM
--
-- Part of the LXP32 test platform
--
-- Copyright (c) 2016 by Alex I. Kuznetsov
--
-- Program RAM for the LXP32 test platform. Has two interfaces:
-- WISHBONE (for data access) and LLI (for LXP32 instruction bus).
-- Optionally performs throttling.
--
-- Note: regardless of whether this description is synthesizable,
-- it was designed exclusively for simulation purposes.
---------------------------------------------------------------------
 
library ieee;
use ieee.std_logic_1164.all;
 
use work.common_pkg.all;
 
entity program_ram is
generic(
THROTTLE: boolean
);
port(
clk_i: in std_logic;
rst_i: in std_logic;
wbs_cyc_i: in std_logic;
wbs_stb_i: in std_logic;
wbs_we_i: in std_logic;
wbs_sel_i: in std_logic_vector(3 downto 0);
wbs_ack_o: out std_logic;
wbs_adr_i: in std_logic_vector(27 downto 2);
wbs_dat_i: in std_logic_vector(31 downto 0);
wbs_dat_o: out std_logic_vector(31 downto 0);
lli_re_i: in std_logic;
lli_adr_i: in std_logic_vector(29 downto 0);
lli_dat_o: out std_logic_vector(31 downto 0);
lli_busy_o: out std_logic
);
end entity;
 
architecture rtl of program_ram is
 
signal ram_a_we: std_logic_vector(3 downto 0);
signal ram_a_rdata: std_logic_vector(31 downto 0);
 
signal ram_b_re: std_logic;
signal ram_b_rdata: std_logic_vector(31 downto 0);
 
signal ack_write: std_logic;
signal ack_read: std_logic;
 
signal prbs: std_logic;
signal lli_busy: std_logic:='0';
 
begin
 
-- The total memory size is 16384 words, i.e. 64K bytes
 
gen_dprams: for i in 3 downto 0 generate
generic_dpram_inst: entity work.generic_dpram(rtl)
generic map(
DATA_WIDTH=>8,
ADDR_WIDTH=>14,
SIZE=>16384,
MODE=>"DONTCARE"
)
port map(
clka_i=>clk_i,
cea_i=>'1',
wea_i=>ram_a_we(i),
addra_i=>wbs_adr_i(15 downto 2),
da_i=>wbs_dat_i(i*8+7 downto i*8),
da_o=>ram_a_rdata(i*8+7 downto i*8),
clkb_i=>clk_i,
ceb_i=>ram_b_re,
addrb_i=>lli_adr_i(13 downto 0),
db_o=>ram_b_rdata(i*8+7 downto i*8)
);
end generate;
 
-- WISHBONE interface
 
gen_ram_a_we: for i in 3 downto 0 generate
ram_a_we(i)<='1' when wbs_cyc_i='1' and wbs_stb_i='1' and wbs_we_i='1'
and wbs_sel_i(i)='1' and wbs_adr_i(27 downto 16)="000000000000" else '0';
end generate;
 
process (clk_i) is
begin
if rising_edge(clk_i) then
ack_read<=wbs_cyc_i and wbs_stb_i and not wbs_we_i and not ack_read;
end if;
end process;
 
ack_write<=wbs_cyc_i and wbs_stb_i and wbs_we_i;
 
wbs_ack_o<=ack_read or ack_write;
wbs_dat_o<=ram_a_rdata;
 
-- Low Latency Interface (with optional pseudo-random throttling)
 
process (clk_i) is
begin
if rising_edge(clk_i) then
assert lli_re_i='0' or lli_adr_i(lli_adr_i'high downto 14)=X"0000"
report "Attempted to fetch instruction from a non-existent address 0x"&
hex_string(lli_adr_i&"00")
severity failure;
end if;
end process;
 
gen_throttling: if THROTTLE generate
throttle_inst: entity work.scrambler(rtl)
generic map(TAP1=>9,TAP2=>11)
port map(clk_i=>clk_i,rst_i=>rst_i,ce_i=>'1',d_o=>prbs);
end generate;
 
gen_no_throttling: if not THROTTLE generate
prbs<='0';
end generate;
 
process (clk_i) is
begin
if rising_edge(clk_i) then
if rst_i='1' then
lli_busy<='0';
elsif prbs='1' and lli_re_i='1' then
lli_busy<='1';
elsif prbs='0' then
lli_busy<='0';
end if;
end if;
end process;
 
ram_b_re<=lli_re_i and not lli_busy;
 
lli_busy_o<=lli_busy;
lli_dat_o<=ram_b_rdata when lli_busy='0' else (others=>'-');
 
end architecture;
---------------------------------------------------------------------
-- Program RAM
--
-- Part of the LXP32 test platform
--
-- Copyright (c) 2016 by Alex I. Kuznetsov
--
-- Program RAM for the LXP32 test platform. Has two interfaces:
-- WISHBONE (for data access) and LLI (for LXP32 instruction bus).
-- Optionally performs throttling.
--
-- Note: regardless of whether this description is synthesizable,
-- it was designed exclusively for simulation purposes.
---------------------------------------------------------------------
 
library ieee;
use ieee.std_logic_1164.all;
 
use work.common_pkg.all;
 
entity program_ram is
generic(
THROTTLE: boolean
);
port(
clk_i: in std_logic;
rst_i: in std_logic;
wbs_cyc_i: in std_logic;
wbs_stb_i: in std_logic;
wbs_we_i: in std_logic;
wbs_sel_i: in std_logic_vector(3 downto 0);
wbs_ack_o: out std_logic;
wbs_adr_i: in std_logic_vector(27 downto 2);
wbs_dat_i: in std_logic_vector(31 downto 0);
wbs_dat_o: out std_logic_vector(31 downto 0);
lli_re_i: in std_logic;
lli_adr_i: in std_logic_vector(29 downto 0);
lli_dat_o: out std_logic_vector(31 downto 0);
lli_busy_o: out std_logic
);
end entity;
 
architecture rtl of program_ram is
 
signal ram_a_we: std_logic_vector(3 downto 0);
signal ram_a_rdata: std_logic_vector(31 downto 0);
 
signal ram_b_re: std_logic;
signal ram_b_rdata: std_logic_vector(31 downto 0);
 
signal ack_write: std_logic;
signal ack_read: std_logic;
 
signal prbs: std_logic;
signal lli_busy: std_logic:='0';
 
begin
 
-- The total memory size is 16384 words, i.e. 64K bytes
 
gen_dprams: for i in 3 downto 0 generate
generic_dpram_inst: entity work.generic_dpram(rtl)
generic map(
DATA_WIDTH=>8,
ADDR_WIDTH=>14,
SIZE=>16384,
MODE=>"DONTCARE"
)
port map(
clka_i=>clk_i,
cea_i=>'1',
wea_i=>ram_a_we(i),
addra_i=>wbs_adr_i(15 downto 2),
da_i=>wbs_dat_i(i*8+7 downto i*8),
da_o=>ram_a_rdata(i*8+7 downto i*8),
clkb_i=>clk_i,
ceb_i=>ram_b_re,
addrb_i=>lli_adr_i(13 downto 0),
db_o=>ram_b_rdata(i*8+7 downto i*8)
);
end generate;
 
-- WISHBONE interface
 
gen_ram_a_we: for i in 3 downto 0 generate
ram_a_we(i)<='1' when wbs_cyc_i='1' and wbs_stb_i='1' and wbs_we_i='1'
and wbs_sel_i(i)='1' and wbs_adr_i(27 downto 16)="000000000000" else '0';
end generate;
 
process (clk_i) is
begin
if rising_edge(clk_i) then
ack_read<=wbs_cyc_i and wbs_stb_i and not wbs_we_i and not ack_read;
end if;
end process;
 
ack_write<=wbs_cyc_i and wbs_stb_i and wbs_we_i;
 
wbs_ack_o<=ack_read or ack_write;
wbs_dat_o<=ram_a_rdata;
 
-- Low Latency Interface (with optional pseudo-random throttling)
 
process (clk_i) is
begin
if rising_edge(clk_i) then
assert lli_re_i='0' or lli_adr_i(lli_adr_i'high downto 14)=X"0000"
report "Attempted to fetch instruction from a non-existent address 0x"&
hex_string(lli_adr_i&"00")
severity failure;
end if;
end process;
 
gen_throttling: if THROTTLE generate
throttle_inst: entity work.scrambler(rtl)
generic map(TAP1=>9,TAP2=>11)
port map(clk_i=>clk_i,rst_i=>rst_i,ce_i=>'1',d_o=>prbs);
end generate;
 
gen_no_throttling: if not THROTTLE generate
prbs<='0';
end generate;
 
process (clk_i) is
begin
if rising_edge(clk_i) then
if rst_i='1' then
lli_busy<='0';
elsif prbs='1' and lli_re_i='1' then
lli_busy<='1';
elsif prbs='0' then
lli_busy<='0';
end if;
end if;
end process;
 
ram_b_re<=lli_re_i and not lli_busy;
 
lli_busy_o<=lli_busy;
lli_dat_o<=ram_b_rdata when lli_busy='0' else (others=>'-');
 
end architecture;
/timer.vhd
1,98 → 1,98
---------------------------------------------------------------------
-- Timer
--
-- Part of the LXP32 test platform
--
-- Copyright (c) 2016 by Alex I. Kuznetsov
--
-- A simple programmable interval timer.
--
-- Note: regardless of whether this description is synthesizable,
-- it was designed exclusively for simulation purposes.
---------------------------------------------------------------------
 
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
 
entity timer is
port(
clk_i: in std_logic;
rst_i: in std_logic;
wbs_cyc_i: in std_logic;
wbs_stb_i: in std_logic;
wbs_we_i: in std_logic;
wbs_sel_i: in std_logic_vector(3 downto 0);
wbs_ack_o: out std_logic;
wbs_adr_i: in std_logic_vector(27 downto 2);
wbs_dat_i: in std_logic_vector(31 downto 0);
wbs_dat_o: out std_logic_vector(31 downto 0);
elapsed_o: out std_logic
);
end entity;
 
architecture rtl of timer is
 
signal pulses: unsigned(31 downto 0):=(others=>'0');
signal interval: unsigned(31 downto 0):=(others=>'0');
signal cnt: unsigned(31 downto 0):=(others=>'0');
signal elapsed: std_logic:='0';
 
begin
 
process (clk_i) is
begin
if rising_edge(clk_i) then
if rst_i='1' then
pulses<=(others=>'0');
interval<=(others=>'0');
cnt<=(others=>'0');
elapsed<='0';
else
elapsed<='0';
if pulses/=X"00000000" or cnt/=X"00000000" then
if cnt=X"00000000" then
if pulses/=X"FFFFFFFF" then
pulses<=pulses-1;
end if;
if pulses/=X"00000000" then
cnt<=interval;
end if;
else
cnt<=cnt-1;
end if;
if cnt=X"00000001" then
elapsed<='1';
end if;
end if;
if wbs_cyc_i='1' and wbs_stb_i='1' and wbs_we_i='1' then
for i in wbs_sel_i'range loop
if wbs_sel_i(i)='1' then
if wbs_adr_i="00"&X"000000" then
pulses(i*8+7 downto i*8)<=
unsigned(wbs_dat_i(i*8+7 downto i*8));
cnt<=(others=>'0');
end if;
if wbs_adr_i="00"&X"000001" then
interval(i*8+7 downto i*8)<=
unsigned(wbs_dat_i(i*8+7 downto i*8));
cnt<=(others=>'0');
end if;
end if;
end loop;
end if;
end if;
end if;
end process;
 
wbs_ack_o<=wbs_cyc_i and wbs_stb_i;
wbs_dat_o<=std_logic_vector(pulses) when wbs_adr_i="00"&X"000000" else
std_logic_vector(interval) when wbs_adr_i="00"&X"000001" else
(others=>'-');
 
elapsed_o<=elapsed;
 
end architecture;
---------------------------------------------------------------------
-- Timer
--
-- Part of the LXP32 test platform
--
-- Copyright (c) 2016 by Alex I. Kuznetsov
--
-- A simple programmable interval timer.
--
-- Note: regardless of whether this description is synthesizable,
-- it was designed exclusively for simulation purposes.
---------------------------------------------------------------------
 
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
 
entity timer is
port(
clk_i: in std_logic;
rst_i: in std_logic;
wbs_cyc_i: in std_logic;
wbs_stb_i: in std_logic;
wbs_we_i: in std_logic;
wbs_sel_i: in std_logic_vector(3 downto 0);
wbs_ack_o: out std_logic;
wbs_adr_i: in std_logic_vector(27 downto 2);
wbs_dat_i: in std_logic_vector(31 downto 0);
wbs_dat_o: out std_logic_vector(31 downto 0);
elapsed_o: out std_logic
);
end entity;
 
architecture rtl of timer is
 
signal pulses: unsigned(31 downto 0):=(others=>'0');
signal interval: unsigned(31 downto 0):=(others=>'0');
signal cnt: unsigned(31 downto 0):=(others=>'0');
signal elapsed: std_logic:='0';
 
begin
 
process (clk_i) is
begin
if rising_edge(clk_i) then
if rst_i='1' then
pulses<=(others=>'0');
interval<=(others=>'0');
cnt<=(others=>'0');
elapsed<='0';
else
elapsed<='0';
if pulses/=X"00000000" or cnt/=X"00000000" then
if cnt=X"00000000" then
if pulses/=X"FFFFFFFF" then
pulses<=pulses-1;
end if;
if pulses/=X"00000000" then
cnt<=interval;
end if;
else
cnt<=cnt-1;
end if;
if cnt=X"00000001" then
elapsed<='1';
end if;
end if;
if wbs_cyc_i='1' and wbs_stb_i='1' and wbs_we_i='1' then
for i in wbs_sel_i'range loop
if wbs_sel_i(i)='1' then
if wbs_adr_i="00"&X"000000" then
pulses(i*8+7 downto i*8)<=
unsigned(wbs_dat_i(i*8+7 downto i*8));
cnt<=(others=>'0');
end if;
if wbs_adr_i="00"&X"000001" then
interval(i*8+7 downto i*8)<=
unsigned(wbs_dat_i(i*8+7 downto i*8));
cnt<=(others=>'0');
end if;
end if;
end loop;
end if;
end if;
end if;
end process;
 
wbs_ack_o<=wbs_cyc_i and wbs_stb_i;
wbs_dat_o<=std_logic_vector(pulses) when wbs_adr_i="00"&X"000000" else
std_logic_vector(interval) when wbs_adr_i="00"&X"000001" else
(others=>'-');
 
elapsed_o<=elapsed;
 
end architecture;
/coprocessor.vhd
1,97 → 1,97
---------------------------------------------------------------------
-- Coprocessor
--
-- Part of the LXP32 test platform
--
-- Copyright (c) 2016 by Alex I. Kuznetsov
--
-- Performs a simple arithmetic operation, uses interrupt to wake
-- up the CPU.
--
-- Note: regardless of whether this description is synthesizable,
-- it was designed exclusively for simulation purposes.
---------------------------------------------------------------------
 
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
 
entity coprocessor is
port(
clk_i: in std_logic;
rst_i: in std_logic;
wbs_cyc_i: in std_logic;
wbs_stb_i: in std_logic;
wbs_we_i: in std_logic;
wbs_sel_i: in std_logic_vector(3 downto 0);
wbs_ack_o: out std_logic;
wbs_adr_i: in std_logic_vector(27 downto 2);
wbs_dat_i: in std_logic_vector(31 downto 0);
wbs_dat_o: out std_logic_vector(31 downto 0);
irq_o: out std_logic
);
end entity;
 
architecture rtl of coprocessor is
 
signal value: unsigned(31 downto 0):=(others=>'0');
signal result: unsigned(31 downto 0):=(others=>'0');
signal cnt: integer range 0 to 5:=0;
signal irq: std_logic:='0';
 
begin
 
process (clk_i) is
begin
if rising_edge(clk_i) then
if rst_i='1' then
value<=(others=>'0');
cnt<=0;
irq<='0';
else
if cnt>0 then
cnt<=cnt-1;
end if;
if cnt=1 then
irq<='1';
else
irq<='0';
end if;
if wbs_cyc_i='1' and wbs_stb_i='1' and wbs_we_i='1' then
for i in wbs_sel_i'range loop
if wbs_sel_i(i)='1' then
if wbs_adr_i="00"&X"000000" then
value(i*8+7 downto i*8)<=
unsigned(wbs_dat_i(i*8+7 downto i*8));
cnt<=5;
end if;
end if;
end loop;
end if;
end if;
end if;
end process;
 
process (clk_i) is
begin
if rising_edge(clk_i) then
if rst_i='1' then
result<=(others=>'0');
else
result<=shift_left(value,1)+value;
end if;
end if;
end process;
 
wbs_ack_o<=wbs_cyc_i and wbs_stb_i;
wbs_dat_o<=std_logic_vector(value) when wbs_adr_i="00"&X"000000" else
std_logic_vector(result) when wbs_adr_i="00"&X"000001" else
(others=>'-');
 
irq_o<=irq;
 
end architecture;
---------------------------------------------------------------------
-- Coprocessor
--
-- Part of the LXP32 test platform
--
-- Copyright (c) 2016 by Alex I. Kuznetsov
--
-- Performs a simple arithmetic operation, uses interrupt to wake
-- up the CPU.
--
-- Note: regardless of whether this description is synthesizable,
-- it was designed exclusively for simulation purposes.
---------------------------------------------------------------------
 
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
 
entity coprocessor is
port(
clk_i: in std_logic;
rst_i: in std_logic;
wbs_cyc_i: in std_logic;
wbs_stb_i: in std_logic;
wbs_we_i: in std_logic;
wbs_sel_i: in std_logic_vector(3 downto 0);
wbs_ack_o: out std_logic;
wbs_adr_i: in std_logic_vector(27 downto 2);
wbs_dat_i: in std_logic_vector(31 downto 0);
wbs_dat_o: out std_logic_vector(31 downto 0);
irq_o: out std_logic
);
end entity;
 
architecture rtl of coprocessor is
 
signal value: unsigned(31 downto 0):=(others=>'0');
signal result: unsigned(31 downto 0):=(others=>'0');
signal cnt: integer range 0 to 5:=0;
signal irq: std_logic:='0';
 
begin
 
process (clk_i) is
begin
if rising_edge(clk_i) then
if rst_i='1' then
value<=(others=>'0');
cnt<=0;
irq<='0';
else
if cnt>0 then
cnt<=cnt-1;
end if;
if cnt=1 then
irq<='1';
else
irq<='0';
end if;
if wbs_cyc_i='1' and wbs_stb_i='1' and wbs_we_i='1' then
for i in wbs_sel_i'range loop
if wbs_sel_i(i)='1' then
if wbs_adr_i="00"&X"000000" then
value(i*8+7 downto i*8)<=
unsigned(wbs_dat_i(i*8+7 downto i*8));
cnt<=5;
end if;
end if;
end loop;
end if;
end if;
end if;
end process;
 
process (clk_i) is
begin
if rising_edge(clk_i) then
if rst_i='1' then
result<=(others=>'0');
else
result<=shift_left(value,1)+value;
end if;
end if;
end process;
 
wbs_ack_o<=wbs_cyc_i and wbs_stb_i;
wbs_dat_o<=std_logic_vector(value) when wbs_adr_i="00"&X"000000" else
std_logic_vector(result) when wbs_adr_i="00"&X"000001" else
(others=>'-');
 
irq_o<=irq;
 
end architecture;
/intercon.vhd
1,215 → 1,215
---------------------------------------------------------------------
-- Simple WISHBONE interconnect
--
-- Generated by wigen at 02/16/16 06:15:08
--
-- Configuration:
-- Number of masters: 2
-- Number of slaves: 4
-- Master address width: 32
-- Slave address width: 28
-- Port size: 32
-- Port granularity: 8
-- Entity name: intercon
-- Pipelined arbiter: no
-- Registered feedback: no
-- Unsafe slave decoder: no
--
-- Command line:
-- wigen -e intercon 2 4 32 28 32 8
---------------------------------------------------------------------
 
library ieee;
use ieee.std_logic_1164.all;
 
entity intercon is
port(
clk_i: in std_logic;
rst_i: in std_logic;
 
s0_cyc_i: in std_logic;
s0_stb_i: in std_logic;
s0_we_i: in std_logic;
s0_sel_i: in std_logic_vector(3 downto 0);
s0_ack_o: out std_logic;
s0_adr_i: in std_logic_vector(31 downto 2);
s0_dat_i: in std_logic_vector(31 downto 0);
s0_dat_o: out std_logic_vector(31 downto 0);
 
s1_cyc_i: in std_logic;
s1_stb_i: in std_logic;
s1_we_i: in std_logic;
s1_sel_i: in std_logic_vector(3 downto 0);
s1_ack_o: out std_logic;
s1_adr_i: in std_logic_vector(31 downto 2);
s1_dat_i: in std_logic_vector(31 downto 0);
s1_dat_o: out std_logic_vector(31 downto 0);
 
m0_cyc_o: out std_logic;
m0_stb_o: out std_logic;
m0_we_o: out std_logic;
m0_sel_o: out std_logic_vector(3 downto 0);
m0_ack_i: in std_logic;
m0_adr_o: out std_logic_vector(27 downto 2);
m0_dat_o: out std_logic_vector(31 downto 0);
m0_dat_i: in std_logic_vector(31 downto 0);
 
m1_cyc_o: out std_logic;
m1_stb_o: out std_logic;
m1_we_o: out std_logic;
m1_sel_o: out std_logic_vector(3 downto 0);
m1_ack_i: in std_logic;
m1_adr_o: out std_logic_vector(27 downto 2);
m1_dat_o: out std_logic_vector(31 downto 0);
m1_dat_i: in std_logic_vector(31 downto 0);
 
m2_cyc_o: out std_logic;
m2_stb_o: out std_logic;
m2_we_o: out std_logic;
m2_sel_o: out std_logic_vector(3 downto 0);
m2_ack_i: in std_logic;
m2_adr_o: out std_logic_vector(27 downto 2);
m2_dat_o: out std_logic_vector(31 downto 0);
m2_dat_i: in std_logic_vector(31 downto 0);
 
m3_cyc_o: out std_logic;
m3_stb_o: out std_logic;
m3_we_o: out std_logic;
m3_sel_o: out std_logic_vector(3 downto 0);
m3_ack_i: in std_logic;
m3_adr_o: out std_logic_vector(27 downto 2);
m3_dat_o: out std_logic_vector(31 downto 0);
m3_dat_i: in std_logic_vector(31 downto 0)
);
end entity;
 
architecture rtl of intercon is
 
signal request: std_logic_vector(1 downto 0);
signal grant_next: std_logic_vector(1 downto 0);
signal grant: std_logic_vector(1 downto 0);
signal grant_reg: std_logic_vector(1 downto 0):=(others=>'0');
 
signal select_slave: std_logic_vector(4 downto 0);
 
signal cyc_mux: std_logic;
signal stb_mux: std_logic;
signal we_mux: std_logic;
signal sel_mux: std_logic_vector(3 downto 0);
signal adr_mux: std_logic_vector(31 downto 2);
signal wdata_mux: std_logic_vector(31 downto 0);
 
signal ack_mux: std_logic;
signal rdata_mux: std_logic_vector(31 downto 0);
 
begin
 
-- ARBITER
-- Selects the active master. Masters with lower port numbers
-- have higher priority. Ongoing cycles are not interrupted.
 
request<=s1_cyc_i&s0_cyc_i;
 
grant_next<="01" when request(0)='1' else
"10" when request(1)='1' else
(others=>'0');
 
grant<=grant_reg when (request and grant_reg)/="00" else grant_next;
 
process (clk_i) is
begin
if rising_edge(clk_i) then
if rst_i='1' then
grant_reg<=(others=>'0');
else
grant_reg<=grant;
end if;
end if;
end process;
 
-- MASTER->SLAVE MUX
 
cyc_mux<=(s0_cyc_i and grant(0)) or
(s1_cyc_i and grant(1));
 
stb_mux<=(s0_stb_i and grant(0)) or
(s1_stb_i and grant(1));
 
we_mux<=(s0_we_i and grant(0)) or
(s1_we_i and grant(1));
 
sel_mux_gen: for i in sel_mux'range generate
sel_mux(i)<=(s0_sel_i(i) and grant(0)) or
(s1_sel_i(i) and grant(1));
end generate;
 
adr_mux_gen: for i in adr_mux'range generate
adr_mux(i)<=(s0_adr_i(i) and grant(0)) or
(s1_adr_i(i) and grant(1));
end generate;
 
wdata_mux_gen: for i in wdata_mux'range generate
wdata_mux(i)<=(s0_dat_i(i) and grant(0)) or
(s1_dat_i(i) and grant(1));
end generate;
 
-- MASTER->SLAVE DEMUX
 
select_slave<="00001" when adr_mux(31 downto 28)="0000" else
"00010" when adr_mux(31 downto 28)="0001" else
"00100" when adr_mux(31 downto 28)="0010" else
"01000" when adr_mux(31 downto 28)="0011" else
"10000"; -- fallback slave
 
m0_cyc_o<=cyc_mux and select_slave(0);
m0_stb_o<=stb_mux and select_slave(0);
m0_we_o<=we_mux;
m0_sel_o<=sel_mux;
m0_adr_o<=adr_mux(m0_adr_o'range);
m0_dat_o<=wdata_mux;
 
m1_cyc_o<=cyc_mux and select_slave(1);
m1_stb_o<=stb_mux and select_slave(1);
m1_we_o<=we_mux;
m1_sel_o<=sel_mux;
m1_adr_o<=adr_mux(m1_adr_o'range);
m1_dat_o<=wdata_mux;
 
m2_cyc_o<=cyc_mux and select_slave(2);
m2_stb_o<=stb_mux and select_slave(2);
m2_we_o<=we_mux;
m2_sel_o<=sel_mux;
m2_adr_o<=adr_mux(m2_adr_o'range);
m2_dat_o<=wdata_mux;
 
m3_cyc_o<=cyc_mux and select_slave(3);
m3_stb_o<=stb_mux and select_slave(3);
m3_we_o<=we_mux;
m3_sel_o<=sel_mux;
m3_adr_o<=adr_mux(m3_adr_o'range);
m3_dat_o<=wdata_mux;
 
-- SLAVE->MASTER MUX
 
ack_mux<=(m0_ack_i and select_slave(0)) or
(m1_ack_i and select_slave(1)) or
(m2_ack_i and select_slave(2)) or
(m3_ack_i and select_slave(3)) or
(cyc_mux and stb_mux and select_slave(4)); -- fallback slave
 
rdata_mux_gen: for i in rdata_mux'range generate
rdata_mux(i)<=(m0_dat_i(i) and select_slave(0)) or
(m1_dat_i(i) and select_slave(1)) or
(m2_dat_i(i) and select_slave(2)) or
(m3_dat_i(i) and select_slave(3));
end generate;
 
-- SLAVE->MASTER DEMUX
 
s0_ack_o<=ack_mux and grant(0);
s0_dat_o<=rdata_mux;
 
s1_ack_o<=ack_mux and grant(1);
s1_dat_o<=rdata_mux;
 
end architecture;
---------------------------------------------------------------------
-- Simple WISHBONE interconnect
--
-- Generated by wigen at 02/16/16 06:15:08
--
-- Configuration:
-- Number of masters: 2
-- Number of slaves: 4
-- Master address width: 32
-- Slave address width: 28
-- Port size: 32
-- Port granularity: 8
-- Entity name: intercon
-- Pipelined arbiter: no
-- Registered feedback: no
-- Unsafe slave decoder: no
--
-- Command line:
-- wigen -e intercon 2 4 32 28 32 8
---------------------------------------------------------------------
 
library ieee;
use ieee.std_logic_1164.all;
 
entity intercon is
port(
clk_i: in std_logic;
rst_i: in std_logic;
 
s0_cyc_i: in std_logic;
s0_stb_i: in std_logic;
s0_we_i: in std_logic;
s0_sel_i: in std_logic_vector(3 downto 0);
s0_ack_o: out std_logic;
s0_adr_i: in std_logic_vector(31 downto 2);
s0_dat_i: in std_logic_vector(31 downto 0);
s0_dat_o: out std_logic_vector(31 downto 0);
 
s1_cyc_i: in std_logic;
s1_stb_i: in std_logic;
s1_we_i: in std_logic;
s1_sel_i: in std_logic_vector(3 downto 0);
s1_ack_o: out std_logic;
s1_adr_i: in std_logic_vector(31 downto 2);
s1_dat_i: in std_logic_vector(31 downto 0);
s1_dat_o: out std_logic_vector(31 downto 0);
 
m0_cyc_o: out std_logic;
m0_stb_o: out std_logic;
m0_we_o: out std_logic;
m0_sel_o: out std_logic_vector(3 downto 0);
m0_ack_i: in std_logic;
m0_adr_o: out std_logic_vector(27 downto 2);
m0_dat_o: out std_logic_vector(31 downto 0);
m0_dat_i: in std_logic_vector(31 downto 0);
 
m1_cyc_o: out std_logic;
m1_stb_o: out std_logic;
m1_we_o: out std_logic;
m1_sel_o: out std_logic_vector(3 downto 0);
m1_ack_i: in std_logic;
m1_adr_o: out std_logic_vector(27 downto 2);
m1_dat_o: out std_logic_vector(31 downto 0);
m1_dat_i: in std_logic_vector(31 downto 0);
 
m2_cyc_o: out std_logic;
m2_stb_o: out std_logic;
m2_we_o: out std_logic;
m2_sel_o: out std_logic_vector(3 downto 0);
m2_ack_i: in std_logic;
m2_adr_o: out std_logic_vector(27 downto 2);
m2_dat_o: out std_logic_vector(31 downto 0);
m2_dat_i: in std_logic_vector(31 downto 0);
 
m3_cyc_o: out std_logic;
m3_stb_o: out std_logic;
m3_we_o: out std_logic;
m3_sel_o: out std_logic_vector(3 downto 0);
m3_ack_i: in std_logic;
m3_adr_o: out std_logic_vector(27 downto 2);
m3_dat_o: out std_logic_vector(31 downto 0);
m3_dat_i: in std_logic_vector(31 downto 0)
);
end entity;
 
architecture rtl of intercon is
 
signal request: std_logic_vector(1 downto 0);
signal grant_next: std_logic_vector(1 downto 0);
signal grant: std_logic_vector(1 downto 0);
signal grant_reg: std_logic_vector(1 downto 0):=(others=>'0');
 
signal select_slave: std_logic_vector(4 downto 0);
 
signal cyc_mux: std_logic;
signal stb_mux: std_logic;
signal we_mux: std_logic;
signal sel_mux: std_logic_vector(3 downto 0);
signal adr_mux: std_logic_vector(31 downto 2);
signal wdata_mux: std_logic_vector(31 downto 0);
 
signal ack_mux: std_logic;
signal rdata_mux: std_logic_vector(31 downto 0);
 
begin
 
-- ARBITER
-- Selects the active master. Masters with lower port numbers
-- have higher priority. Ongoing cycles are not interrupted.
 
request<=s1_cyc_i&s0_cyc_i;
 
grant_next<="01" when request(0)='1' else
"10" when request(1)='1' else
(others=>'0');
 
grant<=grant_reg when (request and grant_reg)/="00" else grant_next;
 
process (clk_i) is
begin
if rising_edge(clk_i) then
if rst_i='1' then
grant_reg<=(others=>'0');
else
grant_reg<=grant;
end if;
end if;
end process;
 
-- MASTER->SLAVE MUX
 
cyc_mux<=(s0_cyc_i and grant(0)) or
(s1_cyc_i and grant(1));
 
stb_mux<=(s0_stb_i and grant(0)) or
(s1_stb_i and grant(1));
 
we_mux<=(s0_we_i and grant(0)) or
(s1_we_i and grant(1));
 
sel_mux_gen: for i in sel_mux'range generate
sel_mux(i)<=(s0_sel_i(i) and grant(0)) or
(s1_sel_i(i) and grant(1));
end generate;
 
adr_mux_gen: for i in adr_mux'range generate
adr_mux(i)<=(s0_adr_i(i) and grant(0)) or
(s1_adr_i(i) and grant(1));
end generate;
 
wdata_mux_gen: for i in wdata_mux'range generate
wdata_mux(i)<=(s0_dat_i(i) and grant(0)) or
(s1_dat_i(i) and grant(1));
end generate;
 
-- MASTER->SLAVE DEMUX
 
select_slave<="00001" when adr_mux(31 downto 28)="0000" else
"00010" when adr_mux(31 downto 28)="0001" else
"00100" when adr_mux(31 downto 28)="0010" else
"01000" when adr_mux(31 downto 28)="0011" else
"10000"; -- fallback slave
 
m0_cyc_o<=cyc_mux and select_slave(0);
m0_stb_o<=stb_mux and select_slave(0);
m0_we_o<=we_mux;
m0_sel_o<=sel_mux;
m0_adr_o<=adr_mux(m0_adr_o'range);
m0_dat_o<=wdata_mux;
 
m1_cyc_o<=cyc_mux and select_slave(1);
m1_stb_o<=stb_mux and select_slave(1);
m1_we_o<=we_mux;
m1_sel_o<=sel_mux;
m1_adr_o<=adr_mux(m1_adr_o'range);
m1_dat_o<=wdata_mux;
 
m2_cyc_o<=cyc_mux and select_slave(2);
m2_stb_o<=stb_mux and select_slave(2);
m2_we_o<=we_mux;
m2_sel_o<=sel_mux;
m2_adr_o<=adr_mux(m2_adr_o'range);
m2_dat_o<=wdata_mux;
 
m3_cyc_o<=cyc_mux and select_slave(3);
m3_stb_o<=stb_mux and select_slave(3);
m3_we_o<=we_mux;
m3_sel_o<=sel_mux;
m3_adr_o<=adr_mux(m3_adr_o'range);
m3_dat_o<=wdata_mux;
 
-- SLAVE->MASTER MUX
 
ack_mux<=(m0_ack_i and select_slave(0)) or
(m1_ack_i and select_slave(1)) or
(m2_ack_i and select_slave(2)) or
(m3_ack_i and select_slave(3)) or
(cyc_mux and stb_mux and select_slave(4)); -- fallback slave
 
rdata_mux_gen: for i in rdata_mux'range generate
rdata_mux(i)<=(m0_dat_i(i) and select_slave(0)) or
(m1_dat_i(i) and select_slave(1)) or
(m2_dat_i(i) and select_slave(2)) or
(m3_dat_i(i) and select_slave(3));
end generate;
 
-- SLAVE->MASTER DEMUX
 
s0_ack_o<=ack_mux and grant(0);
s0_dat_o<=rdata_mux;
 
s1_ack_o<=ack_mux and grant(1);
s1_dat_o<=rdata_mux;
 
end architecture;
/ibus_adapter.vhd
1,101 → 1,101
---------------------------------------------------------------------
-- IBUS adapter
--
-- Part of the LXP32 test platform
--
-- Copyright (c) 2016 by Alex I. Kuznetsov
--
-- Converts the Low Latency Interface to WISHBONE registered
-- feedback protocol.
--
-- Note: regardless of whether this description is synthesizable,
-- it was designed exclusively for simulation purposes.
---------------------------------------------------------------------
 
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
 
entity ibus_adapter is
port(
clk_i: in std_logic;
rst_i: in std_logic;
ibus_cyc_i: in std_logic;
ibus_stb_i: in std_logic;
ibus_cti_i: in std_logic_vector(2 downto 0);
ibus_bte_i: in std_logic_vector(1 downto 0);
ibus_ack_o: out std_logic;
ibus_adr_i: in std_logic_vector(29 downto 0);
ibus_dat_o: out std_logic_vector(31 downto 0);
lli_re_o: out std_logic;
lli_adr_o: out std_logic_vector(29 downto 0);
lli_dat_i: in std_logic_vector(31 downto 0);
lli_busy_i: in std_logic
);
end entity;
 
architecture rtl of ibus_adapter is
 
constant burst_delay: integer:=5;
signal burst_delay_cnt: integer:=0;
signal delay_burst: std_logic;
 
signal re: std_logic;
signal requested: std_logic:='0';
signal adr: unsigned(29 downto 0);
signal ack: std_logic;
 
begin
 
-- Insert burst delay
 
process (clk_i) is
begin
if rising_edge(clk_i) then
if rst_i='1' then
burst_delay_cnt<=0;
elsif ibus_cyc_i='0' then
burst_delay_cnt<=burst_delay;
elsif burst_delay_cnt/=0 then
burst_delay_cnt<=burst_delay_cnt-1;
end if;
end if;
end process;
 
delay_burst<='1' when burst_delay_cnt/=0 else '0';
 
-- Generate ACK signal
 
process (clk_i) is
begin
if rising_edge(clk_i) then
if rst_i='1' then
requested<='0';
elsif lli_busy_i='0' then
requested<=re;
end if;
end if;
end process;
 
ack<=requested and not lli_busy_i;
 
-- Generate LLI signals
 
re<=(ibus_cyc_i and ibus_stb_i and not delay_burst) when ack='0' or
(ibus_cti_i="010" and ibus_bte_i="00") else '0';
 
adr<=unsigned(ibus_adr_i) when re='1' and ack='0' else
unsigned(ibus_adr_i)+1 when re='1' and ack='1' else
(others=>'-');
 
lli_re_o<=re;
lli_adr_o<=std_logic_vector(adr);
 
-- Generate IBUS signals
 
ibus_ack_o<=ack;
ibus_dat_o<=lli_dat_i when ack='1' else (others=>'-');
 
end architecture;
---------------------------------------------------------------------
-- IBUS adapter
--
-- Part of the LXP32 test platform
--
-- Copyright (c) 2016 by Alex I. Kuznetsov
--
-- Converts the Low Latency Interface to WISHBONE registered
-- feedback protocol.
--
-- Note: regardless of whether this description is synthesizable,
-- it was designed exclusively for simulation purposes.
---------------------------------------------------------------------
 
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
 
entity ibus_adapter is
port(
clk_i: in std_logic;
rst_i: in std_logic;
ibus_cyc_i: in std_logic;
ibus_stb_i: in std_logic;
ibus_cti_i: in std_logic_vector(2 downto 0);
ibus_bte_i: in std_logic_vector(1 downto 0);
ibus_ack_o: out std_logic;
ibus_adr_i: in std_logic_vector(29 downto 0);
ibus_dat_o: out std_logic_vector(31 downto 0);
lli_re_o: out std_logic;
lli_adr_o: out std_logic_vector(29 downto 0);
lli_dat_i: in std_logic_vector(31 downto 0);
lli_busy_i: in std_logic
);
end entity;
 
architecture rtl of ibus_adapter is
 
constant burst_delay: integer:=5;
signal burst_delay_cnt: integer:=0;
signal delay_burst: std_logic;
 
signal re: std_logic;
signal requested: std_logic:='0';
signal adr: unsigned(29 downto 0);
signal ack: std_logic;
 
begin
 
-- Insert burst delay
 
process (clk_i) is
begin
if rising_edge(clk_i) then
if rst_i='1' then
burst_delay_cnt<=0;
elsif ibus_cyc_i='0' then
burst_delay_cnt<=burst_delay;
elsif burst_delay_cnt/=0 then
burst_delay_cnt<=burst_delay_cnt-1;
end if;
end if;
end process;
 
delay_burst<='1' when burst_delay_cnt/=0 else '0';
 
-- Generate ACK signal
 
process (clk_i) is
begin
if rising_edge(clk_i) then
if rst_i='1' then
requested<='0';
elsif lli_busy_i='0' then
requested<=re;
end if;
end if;
end process;
 
ack<=requested and not lli_busy_i;
 
-- Generate LLI signals
 
re<=(ibus_cyc_i and ibus_stb_i and not delay_burst) when ack='0' or
(ibus_cti_i="010" and ibus_bte_i="00") else '0';
 
adr<=unsigned(ibus_adr_i) when re='1' and ack='0' else
unsigned(ibus_adr_i)+1 when re='1' and ack='1' else
(others=>'-');
 
lli_re_o<=re;
lli_adr_o<=std_logic_vector(adr);
 
-- Generate IBUS signals
 
ibus_ack_o<=ack;
ibus_dat_o<=lli_dat_i when ack='1' else (others=>'-');
 
end architecture;
/scrambler.vhd
1,54 → 1,54
---------------------------------------------------------------------
-- Scrambler
--
-- Part of the LXP32 test platform
--
-- Copyright (c) 2016 by Alex I. Kuznetsov
--
-- Generates a pseudo-random binary sequence using a Linear-Feedback
-- Shift Register (LFSR).
--
-- In order to generate a maximum-length sequence, 1+x^TAP1+x^TAP2
-- must be a primitive polynomial. Typical polynomials include:
-- (6,7), (9,11), (14,15).
--
-- Note: regardless of whether this description is synthesizable,
-- it was designed exclusively for simulation purposes.
---------------------------------------------------------------------
 
library ieee;
use ieee.std_logic_1164.all;
 
entity scrambler is
generic(
TAP1: integer;
TAP2: integer
);
port(
clk_i: in std_logic;
rst_i: in std_logic;
ce_i: in std_logic;
d_o: out std_logic
);
end entity;
 
architecture rtl of scrambler is
 
signal reg: std_logic_vector(TAP2 downto 1):=(others=>'1');
 
begin
 
process (clk_i) is
begin
if rising_edge(clk_i) then
if rst_i='1' then
reg<=(others=>'1');
elsif ce_i='1' then
reg<=reg(TAP2-1 downto 1)&(reg(TAP2) xor reg(TAP1));
end if;
end if;
end process;
 
d_o<=reg(1);
 
end architecture;
---------------------------------------------------------------------
-- Scrambler
--
-- Part of the LXP32 test platform
--
-- Copyright (c) 2016 by Alex I. Kuznetsov
--
-- Generates a pseudo-random binary sequence using a Linear-Feedback
-- Shift Register (LFSR).
--
-- In order to generate a maximum-length sequence, 1+x^TAP1+x^TAP2
-- must be a primitive polynomial. Typical polynomials include:
-- (6,7), (9,11), (14,15).
--
-- Note: regardless of whether this description is synthesizable,
-- it was designed exclusively for simulation purposes.
---------------------------------------------------------------------
 
library ieee;
use ieee.std_logic_1164.all;
 
entity scrambler is
generic(
TAP1: integer;
TAP2: integer
);
port(
clk_i: in std_logic;
rst_i: in std_logic;
ce_i: in std_logic;
d_o: out std_logic
);
end entity;
 
architecture rtl of scrambler is
 
signal reg: std_logic_vector(TAP2 downto 1):=(others=>'1');
 
begin
 
process (clk_i) is
begin
if rising_edge(clk_i) then
if rst_i='1' then
reg<=(others=>'1');
elsif ce_i='1' then
reg<=reg(TAP2-1 downto 1)&(reg(TAP2) xor reg(TAP1));
end if;
end if;
end process;
 
d_o<=reg(1);
 
end architecture;

powered by: WebSVN 2.1.0

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