[submodule "submodule/ulan-drv"]
path = submodule/ulan-drv
url = git://git.code.sf.net/p/ulan/ulan-drv
+[submodule "submodule/tumbl"]
+ path = submodule/tumbl
+ url = ssh://git@rtime.felk.cvut.cz/fpga/lx-cpu1/tumbl.git
# - gen : Transfer placed and routed NCD file into the bin file, which can
# be then used to configure particular FPGA (this is further packaged
# for SelectMap interface via the ARM CPU)
+# - firmware : Builds the firmware for Tumbl core
# Dependicies are handled, so in most cases only 'download' target is called.
REQ_PKG := $(REQB).pkg
REQ_SRC := .
+REQ_FIRMWARE := $(OUT)/imem.bin $(OUT)/imem.asm $(OUT)/dmem.bin $(OUT)/firmware.lst
+
+#===============================================================================
+
+MB_CROSS_COMPILE ?= mb-
+TARGET_CC := $(MB_CROSS_COMPILE)gcc
+TARGET_LD := $(MB_CROSS_COMPILE)ld
+TARGET_OBJCOPY := $(MB_CROSS_COMPILE)objcopy
+TARGET_OBJDUMP := $(MB_CROSS_COMPILE)objdump
+
+C_OBJS := $(OUT)/firmware.o
+A_OBJS :=
+CFLAGS := -mxl-soft-div -msoft-float -mno-xl-soft-mul -mxl-barrel-shift -Wno-main -Wl,-no-check-sections -fno-zero-initialized-in-bss -g -O2 -Wall
+AFLAGS := -D__ASSEMBLY__ $(CFLAGS)
+LDFLAGS := -static -nostdlib -defsym _STACK_SIZE=0x0200
+
+OBJS := $(OUT)/start.o $(C_OBJS) $(A_OBJS)
+
+FIRMWARE_DIR := ./lx-rocon_firmware
+
#===============================================================================
# Attempt to create a output directory.
#===============================================================================
.PHONY: all
-all: pkg
+all: pkg firmware
.PHONY: re-synthesize
re-synthesize $(REQ_NGC): $(addprefix $(REQ_SRC)/,$(PRJ))
cd $(OUT); \
./packager le $(BIN) $(PKG)
+$(OUT)/%.o: $(FIRMWARE_DIR)/%.c
+ $(TARGET_CC) $(CFLAGS) -c $< -o $@
+
+$(OUT)/%.o: $(FIRMWARE_DIR)/%.S
+ $(TARGET_CC) $(AFLAGS) -c $< -o $@
+
+$(OUT)/firmware.elf: $(OBJS)
+ $(TARGET_LD) $(LDFLAGS) -T $(FIRMWARE_DIR)/utils/tumbl.ld-script -o $@ $(OBJS)
+
+$(OUT)/mb-dasm: $(FIRMWARE_DIR)/utils/mb-dasm.cpp
+ g++ $< -o $@
+
+$(OUT)/bin2mem: $(FIRMWARE_DIR)/utils/bin2mem.c
+ gcc $< -o $@
+
+.PHONY: re-firmware
+re-firmware $(REQ_FIRMWARE): $(REQ_PKG) $(OUT)/mb-dasm $(OUT)/bin2mem $(OUT)/firmware.elf
+ $(TARGET_OBJCOPY) -O binary $(OUT)/firmware.elf -j .text -S $(OUT)/imem.bin
+ $(TARGET_OBJCOPY) -O binary $(OUT)/firmware.elf -j .data -S $(OUT)/dmem.bin
+ $(TARGET_OBJDUMP) -DSCz $(OUT)/firmware.elf > $@
+ cd $(OUT); \
+ ./mb-dasm imem.bin > imem.asm
+
#===============================================================================
.PHONY: clean
.PHONY: pkg
pkg: $(OUT)/packager $(REQ_PKG)
+
+.PHONY: firmware
+firmware: $(OUT)/mb-dasm $(OUT)/bin2mem $(REQ_FIRMWARE)
+++ /dev/null
-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;
-
--- Bcd for clock debugging purposes
-
-entity bcd is
- generic
- (
- width : integer := 32
- );
- port
- (
- -- Reset
- reset : in std_logic;
-
- -- Enabled
- en : in std_logic;
-
- -- Clock
- clk : in std_logic;
-
- -- Value
- value : out std_logic_vector((width-1) downto 0)
- );
-end bcd;
-
-architecture Behavioral of bcd is
- signal counter : std_logic_vector((width-1) downto 0);
-begin
-
- value <= counter;
-
- update: process (clk, reset)
- begin
-
- if reset = '1' then
- counter <= (others => '0');
- elsif clk = '1' and clk'event then
- if en = '1' then
- counter <= counter + 1;
- end if;
- end if;
-
- end process;
-
-end Behavioral;
-
+++ /dev/null
-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;
-
--- BCD interconnection
-
-entity bus_bcd is
- port
- (
- -- Reset
- reset : in std_logic;
-
- -- Enable
- en : in std_logic;
-
- -- Clock
- clk : in std_logic;
-
- -- Chip enable
- ce : in std_logic;
-
- -- Data bus (read only)
- data_out : out std_logic_vector(31 downto 0);
-
- -- Bus signals
- rd : in std_logic;
- ta : out std_logic
- );
-end bus_bcd;
-
-architecture Behavioral of bus_bcd is
-
- signal value : std_logic_vector(31 downto 0);
-
- component bcd
- generic
- (
- width : integer
- );
- port
- (
- reset : in std_logic;
- en : in std_logic;
- clk : in std_logic;
- value : out std_logic_vector((width-1) downto 0)
- );
- end component;
-
-begin
-
- my_bcd: bcd
- generic map
- (
- width => 32
- )
- port map
- (
- reset => reset,
- en => en,
- clk => clk,
- value => value
- );
-
- memory_bus: process(ce, rd, value)
- begin
-
- -- Init defaults
- ta <= '1';
- data_out <= (others => 'X');
-
- if ce = '0' and rd = '0' then
- ta <= '0';
- -- ID in big endian
- data_out <= value;
- end if;
-
- end process;
-
-
-end Behavioral;
-
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;
use ieee.numeric_std.all;
+use work.lx_rocon_pkg.all;
-- Memory bus calibration
-- Holds the signal for one clock to simulate longest route
-- Wiring
signal read1_out : std_logic_vector(31 downto 0);
signal read1_ta : std_logic;
- signal read1_ce : std_logic;
signal read2_out : std_logic_vector(31 downto 0);
signal read2_ta : std_logic;
- signal read2_ce : std_logic;
signal write1_out : std_logic_vector(31 downto 0);
signal write1_ta : std_logic;
signal write2_ta : std_logic;
signal write2_ce : std_logic;
- component calibration_read_register
- generic
- (
- id : std_logic_vector(31 downto 0)
- );
- port
- (
- ce : in std_logic;
- data_out : out std_logic_vector(31 downto 0);
- rd : in std_logic;
- ta : out std_logic
- );
- end component;
-
- component calibration_write_register
- port
- (
- clk : in std_logic;
- reset : in std_logic;
- ce : in std_logic;
- data_in : in std_logic_vector(31 downto 0);
- data_out : out std_logic_vector(31 downto 0);
- rd : in std_logic;
- bls : in std_logic_vector(3 downto 0);
- ta : out std_logic
- );
- end component;
-
begin
-- First read calibration register (0xAAAAAAAA)
)
port map
(
- ce => read1_ce,
rd => rd,
ta => read1_ta,
data_out => read1_out
)
port map
(
- ce => read2_ce,
rd => rd,
ta => read2_ta,
data_out => read2_out
if clk = '1' and clk'event then
-- Defaults
- read1_ce <= '1';
- read2_ce <= '1';
write1_ce <= '1';
write2_ce <= '1';
if ce = '0' then
case address is
when "00" => -- Read1
- read1_ce <= '0';
ta <= read1_ta;
data_out <= read1_out;
when "01" => -- Read2
- read2_ce <= '0';
ta <= read2_ta;
data_out <= read2_out;
when "10" => -- Write1
+++ /dev/null
-
-library IEEE;
-use IEEE.STD_LOGIC_1164.ALL;
-
--- Wrapper for the memory bus for CPU and the BRAM
-
-entity bus_control_bram is
- port
- (
- -- Clock
- clk : in std_logic;
-
- -- This is wired to CPU memory bus
- ena : in std_logic;
- wea : in std_logic_vector(3 downto 0);
- addra : in std_logic_vector(8 downto 0);
- dina : in std_logic_vector(31 downto 0);
- douta : out std_logic_vector(31 downto 0);
- taa : out std_logic;
-
- -- This is wired to control unit bus
- enb : in std_logic;
- web : in std_logic_vector(3 downto 0);
- addrb : in std_logic_vector(8 downto 0);
- dinb : in std_logic_vector(31 downto 0);
- doutb : out std_logic_vector(31 downto 0)
- );
-end bus_control_bram;
-
-architecture Behavioral of bus_control_bram is
-
- signal neg_ena : std_logic;
- signal neg_wea : std_logic_vector(3 downto 0);
-
- component control_bram
- port
- (
- clka : in std_logic;
- ena : in std_logic;
- wea : in std_logic_vector(3 downto 0);
- addra : in std_logic_vector(8 downto 0);
- dina : in std_logic_vector(31 downto 0);
- douta : out std_logic_vector(31 downto 0);
-
- clkb : in std_logic;
- enb : in std_logic;
- web : in std_logic_vector(3 downto 0);
- addrb : in std_logic_vector(8 downto 0);
- dinb : in std_logic_vector(31 downto 0);
- doutb : out std_logic_vector(31 downto 0)
- );
- end component;
-
-begin
-
- -- Wire it to the actual BRAM
- my_bram: control_bram
- port map
- (
- clka => clk,
- ena => neg_ena,
- wea => neg_wea,
- addra => addra,
- dina => dina,
- douta => douta,
-
- clkb => clk,
- enb => enb,
- web => web,
- addrb => addrb,
- dinb => dinb,
- doutb => doutb
- );
-
- -- Transaction acknowledge
- my_bram_ta: process(clk)
- begin
-
- -- It puts there data synchronously with clock, so make the same for ack
- if clk = '1' and clk'event then
- taa <= ena;
- end if;
-
- end process;
-
- -- Wire negated inputs
- my_bream_neg: process(ena, wea)
- begin
-
- neg_ena <= not ena;
- neg_wea <= not wea;
-
- end process;
-
-end Behavioral;
-
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;
use ieee.numeric_std.all;
+use work.lx_rocon_pkg.all;
-- IRC bus interconnect: memory region for IRC
signal irc4_ta : std_logic;
signal irc4_ce : std_logic_vector(1 downto 0);
- -- IRC register
- component irc_register
- port
- (
- clk : in std_logic;
- reset : in std_logic;
- a0, b0 : in std_logic;
- index0 : in std_logic;
- mark0 : in std_logic;
- data_in : in std_logic;
- data_out : out std_logic_vector(31 downto 0);
- ce : in std_logic_vector(1 downto 0);
- rd : in std_logic;
- ta : out std_logic;
- wr : in std_logic
- );
- end component;
-
begin
-- IRC for first axis
data_out <= irc4_out;
ta <= irc4_ta;
- when others =>
- data_out <= (others => 'X');
+ when others => NULL;
end case;
--- /dev/null
+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;
+use work.mbl_Pkg.all;
+use work.lx_rocon_pkg.all;
+
+-- Connects tumbl to the Master CPU
+
+entity bus_tumbl is
+ port
+ (
+ -- Clock
+ clk_100m : in std_logic;
+ clk_50m : in std_logic;
+
+ -- Chip enable
+ ce : in std_logic;
+
+ -- Global Reset
+ reset : in std_logic;
+
+ -- Master CPU bus for the memory
+ rd : in std_logic;
+ bls : in std_logic_vector(3 downto 0);
+ address : in std_logic_vector(11 downto 0);
+ data_in : in std_logic_vector(31 downto 0);
+ data_out : out std_logic_vector(31 downto 0);
+ ta : out std_logic;
+
+ -- Tumbl extrenal memory bus
+ XMEMB_sel_o : out std_logic;
+ XMEMB_i : in DMEMB2CORE_Type;
+ XMEMB_o : out CORE2DMEMB_Type
+ );
+end bus_tumbl;
+
+architecture Behavioral of bus_tumbl is
+
+ -- Internal state
+ signal tumbl_reset : std_logic;
+ signal tumbl_halt : std_logic;
+ signal tumbl_int : std_logic;
+ signal tumbl_trace : std_logic;
+ signal tumbl_trace_kick : std_logic; -- driven by 50M clock
+ signal tumbl_trace_kick_ack : std_logic; -- driven by 50M clock
+ signal tumbl_trace_kick_req : std_logic; -- driven by 100M clock
+ signal tumbl_done : std_logic; -- driven by 50M clock
+ signal tumbl_bad_op : std_logic; -- driven by 50M clock
+
+ -- Tumbl PC (copy it with cpu clock and then wire further)
+ signal tumbl_pc : std_logic_vector(31 downto 0); -- driven by 50M clock
+
+ -- Internal memory signals
+ signal imem_en : std_logic;
+ signal dmem_en : std_logic;
+
+ signal imem_we : std_logic_vector(3 downto 0);
+ signal dmem_we : std_logic_vector(3 downto 0);
+
+ signal imem_dout : std_logic_vector(31 downto 0);
+ signal dmem_dout : std_logic_vector(31 downto 0);
+
+ -- Internal bus structure
+ -- 12 address bits: 2 bits for selection, 10 bits for address
+ --
+ -- Selection:
+ -- 00 - imem
+ -- 01 - dmem
+ -- 10 - reserved
+ -- 11 - registers
+
+ -- Registers
+ -- 0x000
+ --
+ -- Bit 0: R/W - Reset
+ -- Bit 1: R/W - Interrupt
+ -- Bit 2: R/W - Halt
+ -- Bit 3: R/W - Trace
+ -- Bit 3: R - Done
+ -- Bit 4: R - Bad Op (halts the core until reset)
+
+ -- 0x001
+ -- Bit 0: W - Write 1 for trace kick, R - Read internal signals
+
+ -- 0x002
+ -- Tumbl program counter (R)
+
+begin
+
+ -- Wire it to the tumbl
+ I_TUMBL: lx_rocon_tumbl
+ generic map
+ (
+ IMEM_ABITS_g => 11,
+ DMEM_ABITS_g => 12,
+ --
+ USE_HW_MUL_g => true,
+ USE_BARREL_g => true
+ )
+ port map
+ (
+ clk_i => clk_50m,
+ rst_i => tumbl_reset,
+ halt_i => tumbl_halt,
+ int_i => tumbl_int,
+ trace_i => tumbl_trace,
+ trace_kick_i => tumbl_trace_kick,
+
+ pc_o => tumbl_pc,
+
+ -- Internal memory (instruction)
+ imem_clk => clk_100m,
+ imem_en => imem_en,
+ imem_we => imem_we,
+ imem_addr => address(8 downto 0),
+ imem_din => data_in,
+ imem_dout => imem_dout,
+
+ -- Internal memory (data)
+ dmem_clk => clk_100m,
+ dmem_en => dmem_en,
+ dmem_we => dmem_we,
+ dmem_addr => address(9 downto 0),
+ dmem_din => data_in,
+ dmem_dout => dmem_dout,
+
+ -- External memory bus
+ XMEMB_sel_o => XMEMB_sel_o,
+ XMEMB_i => XMEMB_i,
+ XMEMB_o => XMEMB_o,
+ --
+ done_o => tumbl_done,
+ bad_op_o => tumbl_bad_op
+ );
+
+ -- Wiring
+ wiring: process(ce, rd, bls, address, imem_en, imem_dout, dmem_en, dmem_dout,
+ tumbl_reset, tumbl_int, tumbl_halt, tumbl_trace, tumbl_done, tumbl_bad_op, tumbl_pc)
+ begin
+
+ if ce = '0' and address(11 downto 10) = "00" then
+ imem_en <= '1';
+ else
+ imem_en <= '0';
+ end if;
+
+ if ce = '0' and address(11 downto 10) = "01" then
+ dmem_en <= '1';
+ else
+ dmem_en <= '0';
+ end if;
+
+ if imem_en = '1' and tumbl_reset = '1' then
+ imem_we <= not bls;
+ else
+ imem_we <= "0000";
+ end if;
+
+ if dmem_en = '1' and tumbl_reset = '1' then
+ dmem_we <= not bls;
+ else
+ dmem_we <= "0000";
+ end if;
+
+ if imem_en = '1' then
+ data_out <= imem_dout;
+ elsif dmem_en = '1' then
+ data_out <= dmem_dout;
+ elsif ce = '0' and rd = '0' and address(11 downto 10) = "11" then
+ if address(9 downto 0) = "0000000000" then
+ data_out(0) <= tumbl_reset;
+ data_out(1) <= tumbl_int;
+ data_out(2) <= tumbl_halt;
+ data_out(3) <= tumbl_trace;
+ data_out(4) <= tumbl_done;
+ data_out(5) <= tumbl_bad_op;
+ data_out(31 downto 5) <= (others => '0');
+ elsif address(9 downto 0) = "0000000010" then
+ data_out <= tumbl_pc;
+ else
+ data_out <= (others => 'X');
+ end if;
+ else
+ data_out <= (others => 'X');
+ end if;
+
+ end process;
+
+ -- Transaction acknowledge and writing to registers
+ -- The clock are synchronous!
+ update: process(clk_100m)
+ begin
+
+ -- Update on the 100 MHz clock
+ if clk_100m = '1' and clk_100m'event then
+ ta <= '1';
+
+ if imem_en = '1' or dmem_en = '1' then
+ ta <= '0';
+ end if;
+
+ if reset = '1' then
+ tumbl_reset <= '1';
+ tumbl_int <= '0';
+ tumbl_halt <= '0';
+ tumbl_trace <= '0';
+ tumbl_trace_kick_req <= '0';
+ else
+
+ if tumbl_trace_kick_ack = '1' then
+ tumbl_trace_kick_req <= '0';
+ end if;
+
+ if ce = '0' and address(11 downto 10) = "11" then
+ if bls(0) = '0' then
+ if address(9 downto 0) = "0000000000" then
+ tumbl_reset <= data_in(0);
+ tumbl_int <= data_in(1);
+ tumbl_halt <= data_in(2);
+ tumbl_trace <= data_in(3);
+ elsif address(9 downto 0) = "0000000001" then
+ if data_in(0) = '1' and tumbl_trace_kick = '0' then
+ tumbl_trace_kick_req <= '1';
+ end if;
+ end if;
+ end if;
+
+ if rd = '0' then
+ ta <= '0';
+ end if;
+ end if;
+ end if;
+
+ end if;
+ end process;
+
+ -- Update tracing
+ tumbl: process(clk_50m)
+ begin
+
+ -- Update on the 50 MHz clock
+ if clk_50m = '1' and clk_50m'event then
+
+ if reset = '1' then
+ tumbl_trace_kick <= '0';
+ tumbl_trace_kick_ack <= '0';
+ else
+ if tumbl_trace_kick = '0' and tumbl_trace_kick_req = '1' then
+ tumbl_trace_kick <= '1';
+ tumbl_trace_kick_ack <= '1';
+ else
+ tumbl_trace_kick <= '0';
+ end if;
+ end if;
+
+ if tumbl_trace_kick_req <= '0' then
+ tumbl_trace_kick_ack <= '0';
+ end if;
+
+ end if;
+
+ end process;
+
+end Behavioral;
+
);
port
(
- -- Chip enable
- ce : in std_logic;
-
-- Data bus (read only)
data_out : out std_logic_vector(31 downto 0);
architecture Behavioral of calibration_read_register is
begin
- memory_bus: process(ce, rd)
+ memory_bus: process(rd)
begin
- -- Init defaults
- ta <= '1';
- data_out <= (others => 'X');
-
- if ce = '0' and rd = '0' then
- ta <= '0';
- data_out <= id;
- end if;
+ ta <= rd;
+ data_out <= id;
end process;
begin
-- Read is immideate
- memory_bus_read: process(ce, rd, value)
+ memory_bus_read: process(rd, value)
begin
- -- Init defaults
- ta <= '1';
- data_out <= (others => 'X');
-
- if ce = '0' and rd = '0' then
- ta <= '0';
- data_out <= value;
- end if;
+ ta <= rd;
+ data_out <= value;
end process;
-- Write waits for clock
- memory_bus_write: process(clk, reset)
+ memory_bus_write: process(clk)
begin
- if reset = '1' then
- value <= (others => '0');
- end if;
-
if clk = '1' and clk'event then
+ if reset = '1' then
+ value <= (others => '0');
+ end if;
+
if ce = '0' then
if reset = '0' and bls /= "1111" then
--- /dev/null
+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;
+
+-- D circuit (filtered)
+
+entity dff2 is
+ port
+ (
+ clk : in std_logic;
+ reset : in std_logic;
+ d : in std_logic;
+ q : out std_logic
+ );
+end dff2;
+
+architecture behavioral of dff2 is
+ signal last_d : std_logic;
+ signal data: std_logic;
+begin
+ q <= data;
+
+ seq: process(clk)
+ begin
+ if clk = '1' and clk'event then
+ if reset = '1' then
+ last_d <= '0';
+ data <= '0';
+ else
+ if d = last_d then
+ data <= d;
+ end if;
+ end if;
+
+ last_d <= d;
+ end if;
+ end process;
+
+end behavioral;
+++ /dev/null
-XILINX-XDB 0.1 STUB 0.1 ASCII
-XILINX-XDM V1.6e
-$0a6\7f44<,[o}e~g`n;"2*73>(-80!<;40123416<89:;<=>?0123456789:;<=>?0123456789:;<=>?0123456789:;<=>?012345679h1:?7GAPTV9EABUI^XJHI\31383:4g<9:0BB][[:@FGVGTCIMNY0<<50?37?40=AGZ^X7JFAEK?50<768>0=;4FNQWW>AOEL@6:97>114922?IR\Y__6IANDN>21?699<1::7AZTQWW>AIELF6:97>11591>LHW]]0OE]OKIQ>2>586<281EC^ZT;FJTGBNX5;1<3?<;38JJUSS2^OJ[HB31;2=56=52@D[YY4XECUFQ97=87;>7?4@UURVP?BHXHND\1?50?36?7<H]]Z^X7J@PCFLT97=87;87><5IORVP?bnfh68=7>112906?OIX\^1hd`m<2394;723:81CXZ_UU8gkprf4:;1<3?:;209KPRW]]0ocxzm<2394;773=0BB][[:vgb86<768:087GAPTV9s`d;;3:5h68|ly;wub73<$8:>675IORVP?gcl{k747>1139:>LHW]]0jhi|m<983:`=FLMXJ[_OKDS>3:c=FLMXJ[_OKDS>24;`<IMNYMZ\NDEP?548692KOH_OXR@FGV975294m7LJKR@UQEABU4885i6OKDSCTVDBCZ5;5i6OKDSCTVDBCZ585i6OKDSCTVDBCZ595i6OKDSCTVDBCZ5>5i6OKDSCTVDBCZ5?5i6OKDSCTVDBCZ5<5i6OKDSCTVDBCZ5=5i6OKDSCTVDBCZ525i6OKDSCTVDBCZ535i6OKDS@Q@DBCZ5:5j6OKDS@Q@DBCZ5;;2k5NDEPAVAGCL[6:=3?>;@FGVGTCIMNY0<<50?d8EABUJ[NJHI\313<f?DBCZKXOMIJ]<0<f?DBCZKXOMIJ]<3<f?DBCZKXOMIJ]<2<f?DBCZKXOMIJ]<5<f?DBCZKXOMIJ]<4<f?DBCZKXOMIJ]<7<f?DBCZKXOMIJ]<6<f?DBCZKXOMIJ]<9<f?DBCZKXOMIJ]<8<0?DJK02H^_RGAFN08G@753JBNOFQCIBGMW@YSQYO?7NBD079@HN7?8?1H@F<8049@HN4_02IGG?V>8178GIM>8<1H@FO>7:AOOD7C:>1H@FO>D558GIMF9M227NBDAVP@HN3<KEAI=45LLJ@Q@FJL=2IGGN?:;BNH@43<KEAOZn5LLJFU[AOQAMO>7NBDFY:8GIMAP82;56M@MLKWP@B6<2ID^HQHEOGQEQOHFVCEJB94CSGBP@Bd3MK_MRYFDUJ\Ef=CI]KT[DJ[H^@;?AOFL@6;245KI@FJ846912NBMIG310<:?AOFL@6:>374DHCGM974601OELJF<06=f>BNIMC7=84?>89GMDBN48?546JFAEK?5;><L@KOE1<18:FJEAO;;720HDOKI=6=<>BNIMC79364DHCGM90902NBMIG37?:8@LGCA52546JFAEK?=;><L@HOE1>19:FJFAO;99427IGMDH>25;?<L@HOE1?=>89GMGBN489556JFBEK?518e3MCIHD2>5;2==>BNJMC7=807;EKA@L:6611OEOJF<3<;?AOEL@68255KICFJ818?3MCIHD2:>99GMGBN4?437IGMDH>4:==CAKNB0507;EKA@L:>6h1OE]OKIQ>3:f=CAYKOE]2>:1<b?AOWIMC[0<0n;EKSFAOW494h7IG_BEKS84<76h1OE]LKIQ>2:==CGHND0=06;EMB@J:68730HBOKO=32:<=CGHND0<<19:FLEAI;9:427IANDN>20;d<LFKOC1?::1<:?AIFLF6:9364DNCGK97902NDMIA32?:8@JGCG59546J@AEM?0;><LFKOC1;18:FLEAI;>720HBOKO=5=<>BHIME74364DNCGK9?9?2NDMR\JG99GKGBH49427IAMDN>24;?<LFHOC1?>>89GKGBH488556J@BEM?568>3MEIHB2>4?`8@JDCG5;>6=06;EMA@J:6=720HBLKO=3=<>BHJME7>364DN@GK95902NDNIA34?:8@JDCG5?546J@BEM?2;><LFHOC1918:FLFAI;0720HBLKO=;=3>BHJVXNKl5KOQCGKU:76j1OC]OKOQ>2>58f3ME[MIA_<0<b?AIWJME[0=0l;EMSFAIW480;2l5KOQ@GKU:66>1NBLY]EO58AKDULLDi7H@PRRVQEHYFj2OES_][R@O\F0=AIEYN=6I<;FLG<>OIA]ZT<=64IOKWTZ6602CEEY^P03:8MKOSXV:8;6GAIU]342=NF@^T<<94IOKW[5403@DBXR><7:KMMQY7<>1BBDZP0458MKOSW9<<7D@FT^243>OIA]U;4:5FNHV\4<1<AGC_S=O8;HLJPZ6E?2CEEYQ?C69JJLRX8M=0ECG[_1G4?LHN\V:M;6GAIU]242=NF@^T=<94IOKW[4403@DBXR?<7:KMMQY6<>1BBDZP1458MKOSW8<<7D@FT^343>OIA]U:4:5FNHV\5<1<AGC_S<O8;HLJPZ7E?2CEEYQ>C69JJLRX9M=0ECG[_0G4?LHN\V;M:6GAIU]B2>OIA]UI56GAIU]EMIC13EEJHHJ9;MM@O@B03EELENOCc:ObnjtQm{ybccm4MhllvScu{`ee>6@>7:LFPRIUC=1ECCK>7:MSPLKNRLU[^DCFTHTFWZH@K>1[";6k_M68TDTSi2ZBBRLZSHF[f>VNFVH^_COBE79SWAIIM01YM@L7BVGQ<>TFEVGDHH84RDE@ADd<ZLMHIO\JGBG7?WUSI>1Y_YL]SU58VVRSQYOn7_][_QPJKWOSQVKn7_][_QPJKWOSQVH:=6]GRDE\A]RUIJ^TBJMj;RJQABYJAGUXEWK>3:QJIZEHDECXEB@PCIG@O3=TG\XHI:5\RWCO[D1<[[\J@RL9;RVBPPU33ZSEO>5[DQ68P\VB?91^<"v|t^`ooZkbeVmnbh|ntnp,ckgsa\7foiaj aaukuaZdkcVgnaRijn.tbhlb)kz~y#\7foblnms_5[)zhg%~"}9_hljp+tfe&^YYHQKP/RQMH?)zhg<<6[?/yqw[gjlWdofSjkaescwkw)`fh~bzhlbg/lbplpbWkf`S`kb_fgm+sgkam$h\7fy| r`ookjv\9T$ym` }/r4\mkos&{kf#Y\ZE^FS*UTNE0$ym`9?;T2,|vrXjeaTahcPgdlfvdrhz&memygyecod*kgsa\7foTnaePmdo\c`h(~hfbh#m|ts-qehjhgyQ9Q#|nm/p,w3Ynf`~%~lc TSWF[AV)X[CF5#|nm628Q5)\7f{}Ui`fQbel]dakcui}ey#j`nthtffha)fh~bzhQmlj]nahY`mg%}magk.bqwv*tfeeed|V=R.scn*w)t>Vceey }al-WVPCXLY$[^DC6.scng>STM[U]E^GMLD;8RLCPW]S[I45XE@UFH969j2]NMZKC<083:<=PMH]N@1?19:UFFRCR494i7ZKMWDW?5?6912]NNZKZ<0<a?RTN\LUME_][c:UQMQCXEFNNSLm4WSKWAZKHLLUI=i5WIMKM\(^CJ):%=-][UC"3*4&F[JCB:6V\TMKA3>^T\VMEHo5W_BMQAZOINF<0TilPIed8\anXX{cfZh||inl24>^ceVGjfb|Yesqjkk773QnfS@gaosTfvvohf:1S\7fy=4Ydq;?dbczh6;255ndepb848?3hno~l2=>99b`atf4:437ljkr`>7:==flmxj0807;`fgvd:1611jhi|n<6<b?dbczh636=07;`fgvd:?611jhi|m<1<;?dbczk6:255ndepa878?3hno~o2<>99b`ate4=437ljkrc>6:==flmxi0;07;`fgvg:06h1jhi|m<983:==flmxi050>8:`ooZkbeVmnbRijndpjgZet|{;37obd_lgn[bciWyxbaRyfduj\54><jeaTahcPgdl\twojW~coxeQ=199ahnYjmdUlicQ\7frho\slbs`V9:46lck^ofiZabfVzye`Qxievk[1453kf`S`kb_fgm[utneV}ym}~jr^q5[lhn|V;9>6lck^ofiZabfVzye`Qxr`rsawYt>VceeyQ=239ahnYjmdUlicQ\7frho\swgwxlxT\7f;Qfnhv\774<jeaTahcPgdl\twojW~xj|}k}_r4\mkosW=l0naePmdo\c`hX|fz:<6lck^ofiZabfV|<S><l;cnh[hcjWnoeS{9P3-"[mioip)ID^H.Heogqeqiu(8>%:<:4bmi\i`kXoldTz:Q<_yqw56=edbUfi`Qfnqww[gjhkb;?7obd_lgn[jssx|~Tnaalk59`hng33jf`nn5loovqkiYezhg?j85loovqkiYezhg'naePmdo\c`hX~>U8 vmPaefqeZqnl}b65!mPaefqfZqnl}b65!mPamelvlroe4:'oRowi^kg[roc|a7? nQnxh]phdpbW}s{i0>#c^c{mZr~xl7: nQmyug\wl|b51&hSnabmnl\gim:8%iThhhnumv\`drf59&hSig|acnf[rgufVhczRm`lm?3(fYcazki`hQxasl\fmpXzhdli0>#c^goegiui}cdbRjfr<-kkhc({bxb`lv dqr,v`vh'er&~bm`n.jt)iidie%b|na}e^fjv*rjx&Uhk""l_dlbficX;;hbxRokdsgpw86+kVljadbv=rrbvqgi>%iTdl}Payk\ma;7$jUcm~Qjn`?2(fYoizUnbo3>,b]kevYnfcohxh|}=1.`[mgtWdofSb{{ptv\v`atWh7; nQgar]nahYh}}z~xR|jgr]a95*dWakxS`{w_nwwtprXzlmxSl3?,b]kevYj}qUdyy~zt^pfcvYe59&hSeo|_sgdg`g:8%iTdl}Prde`ag;7$jUcm~Q}suc>4)eX`hyT~~zm=1.`[mgtWzemxhml_hlsqqYumnyTm0>#c^jbwZuhn}ohoRaztqww[wc`{Vh6<!mPiokw[cokm4Hgmce\tskmc)eXagc\7fSkgce^lbi`;igVidiRhfld]okdbbl%iTecg{a^tbh86+kVceeylPv`n>4)eXag~n~kole^vzt`;7$jUgcljPiokw[cokm4:'oRcjm^vzt`;5$jUfyuQ\7fiqgomkcX{}kli~3?,b]svlkX|pzn1>"l_sgb`Zbbx}bTm0<78-a\v`gcWmo{xeQm=3:;(fYumhnT{dj{h^c>77*dW{ojhRyfduj\f855$jUy\7fyQ\7frhmqmq\7fXi4IN nQ}su]svliua}sTn0MJ,b]qwqYsqyo6_T@L,b]qwqtfeVk6<!mPrrvqehYe59&hS~gb_bmohlunggUhdhmd=@NO(fYr{lUi~lcPbmm`o86+kV\7fxiRlvtd]tad;6$jU~\7fhQmyug\s`d:9%iTy~kPdddbqirXlh~j1<"l_tqf[`ed59&hSx}j_rmep`ed59&hSzkn_vkgpm;3$jU|ioQxievk91*dW~xbxhQkeqvk[d;501&hSz|ftd]gauroWk7945"l_vpjp`YjgmoTm0Y]IUG\BLTT\%iT{\7fg{e^ol``Ye5^XBXHQIISQW(fYpz`~nSzgkti]b964+kV}yeykPwhfwlZd:;;&hSujjvhafbdkndp7x|l|{ao4~65=dgg~ycaQmr`o/fimXelgTkh`Pv6]0(~{03mcem1>18:fjjd:68720hd`n<03=<>bnfh6:>364dhlb845902nbbl2>4?:8`lhf48?546jfn`>22;><l`dj0<918:fjjd:60720hd`n<0;=3>bnfh6:255kioc?658?3mcem1<>>99gmkg;:;437igaa=00:==cagk7>907;ekme942611oeco327<;?aoii58<255kioc?6=8?3mcem1<6>69gmkg;:720hd`n<22=e>bnfh68=7>18:fjjd:497=0hd`n<2<4?aoii5>5;6jfn`>6:2=cagk7:394dhlb82803mcem1617:fjjd:>6>1oecl30?:8`lhe48:546jfnc>25;><l`di0<<18:fjjg:6;720hd`m<06=<>bnfk6:9364dhla840902nbbo2>7?:8`lhe482546jfnc>2=;1<l`di0<07;ekmf947611oecl320<;?aoij589255kio`?668?3mcen1<;>99gmkd;:<437igab=05:==cagh7>:07;ekmf94?611oecl328<4?aoij58546jfnc>04;g<l`di0>?50?:8`lhe4:;5;6jfnc>0:2=cagh78394dhla80803mcen1817:fjjg:06>1oecl38?58`lhe40437iazt`>3:<=cg|~j0<>19:flqqg;98427iazt`>26;?<lf\7f\7fm1?<>89gkprf48>556j`uuc?508>3me~xl2>6?;8`jssi5;<245kotvb84>912ndyyo318<;?air|h6:245kotvb876912ndyyo320<:?air|h69>374dnwwe944601ocxzn<36==>bh}}k7>806;emvpd:5>730hb{{a=04:<=cg|~j0?619:flqqg;:0437iazt`>1:<=cg|~j0>>1b:flqqg;;80;245kotvb867902ndyyo33?:8`jssi5>546j`uuc?1;><lf\7f\7fm1818:flqqg;?720hb{{a=:=<>bh}}k75364dnwwf96912ndyyl311<:?air|k6:=374dnwwf975601ocxzm<01==>bh}}h7=906;emvpg:6=730hb{{b=35:<=cg|~i0<919:flqqd;91427iaztc>2=;><lf\7f\7fn1?19:flqqd;:9427iaztc>15;?<lf\7f\7fn1<=>89gkpre4;9556j`uu`?618>3me~xo2=5?;8`jssj58=245kotva871912ndyyl329<:?air|k695364dnwwf94912ndyyl331<a?air|k68=7>19:flqqd;;8437iaztc>0:==cg|~i0907;emvpg:2611ocxzm<7<;?air|k6<255kotva8=8?3me~xo26>29fjd5<mgh37cilbtko`7=ig?1|il2?>79tad:66?1|il2=>99tad:4294=7zkn<2<5?rce494=7zkm<0<5?rce4;437zkm<283:3=pmk682pNOp2c6?EF\7f9::1J7:51zQ7a?7713nj6<=<2b2;>45>k=qe==951:l24=<13-;;97??1:\7fP0f<6800om7?<33a3<?741jk0_i?51c;94?74;;i;47?<9e08W1e=9k31<7?<33a3<?741m>0h<=?:182>4}T<l0:<44ka;3077e703;85n64vUga>5<62802jv];e;33=?bf2898>n>7:01:g==#n>0o?6X>0781\7fpb3281~h84?;|&gf?713k;8<7>59d86><`|@o<0(k?51228^60=0r;?6<9511821?7?28;1=?4>3;\7f'552=9;k0(>651208 1b=9:;0(h751:&f<?77i2c:nk4?:%fg>4db3gnh6=54i0`g>5<#lm0:nh5adb82?>o6jj0;6)jk:0`f?kbd2;10e<lm:18'`a<6jl1ehn4<;:k251<72-no6<?<;of`>5=<a8;96=4+de8256=ilj0:76g>1083>!bc28;87cjl:398m477290/hi4>129m`f<432c:<k4?:%fg>4743gnh6954i02f>5<#lm0:=>5adb86?>o68m0;6)jk:030?kbd2?10e<>l:18'`a<69:1ehn48;:k24g<72-no6<?<;of`>==<a8>h6=4+de820g=ilj0;76g>4`83>!bc28>i7cjl:098m42?290/hi4>4c9m`f<532c:8:4?:%fg>42e3gnh6>54i065>5<#lm0:8o5adb87?>o6<<0;6)jk:06a?kbd2<10e<:;:18'`a<6<k1ehn49;:k206<72-no6<:m;of`>2=<a8>96=4+de820g=ilj0376g>4083>!bc28>i7cjl:898m427290/hi4>4c9m`f<f32c:?k4?:%fg>42e3gnh6o54i01g>5<#lm0:8o5adb8`?>o6;j0;6)jk:06a?kbd2m10e<=m:18'`a<6<k1ehn4j;:k27d<72-no6<:m;of`>c=<a8926=4+de820g=ilj0:<65f12:94?"cl3;?n6`kc;32?>o6;>0;6)jk:06a?kbd28807d?<6;29 ab=9=h0bim51298m452290/hi4>4c9m`f<6<21b=>:50;&g`?73j2doo7?:;:k216<72-no6<:m;of`>40<3`;>>7>5$ef951d<fmi1=:54i072>5<#lm0:8o5adb82<>=n9<:1<7*kd;37f>hck3;276g>4g83>!bc28>i7cjl:0c8?l73m3:1(ij515`8jae=9k10e<:k:18'`a<6<k1ehn4>c:9j51?=83.oh7?;b:lgg?7c32c:?h4?:%fg>42e3gnh6<k4;h307?6=,mn1=9l4nea95c=<a8i?6=4+de82g6=ilj0;76g>c383>!bc28i87cjl:098m4e6290/hi4>c29m`f<532c:o=4?:%fg>4e43gnh6>54i03f>5<#lm0:=i5adb83?>o69j0;6)jk:03g?kbd2810e<?m:18'`a<69m1ehn4=;:k25d<72-no6<?k;of`>6=<a8;26=4+de825a=ilj0?76g>1983>!bc28;o7cjl:498m470290/hi4>1e9m`f<132c:=;4?:%fg>47c3gnh6:54i036>5<#lm0:=i5adb8;?>o6>m0;6)jk:04`?kbd2910e<8m:18'`a<6>j1ehn4>;:k22<<72-no6<8l;of`>7=<a8<36=4+de822f=ilj0876g>6683>!bc28<h7cjl:598m401290/hi4>6b9m`f<232c::84?:%fg>40d3gnh6;54i047>5<#lm0::n5adb84?>o6>:0;6)jk:04`?kbd2110e<8=:18'`a<6>j1ehn46;:k224<72-no6<8l;of`>d=<a8<;6=4+de822f=ilj0i76g>5d83>!bc28<h7cjl:b98m43c290/hi4>6b9m`f<c32c:9n4?:%fg>40d3gnh6h54i07a>5<#lm0::n5adb8e?>o6=h0;6)jk:04`?kbd28:07d?:9;29 ab=9?i0bim51098m43?290/hi4>6b9m`f<6:21b=8950;&g`?71k2doo7?<;:k213<72-no6<8l;of`>42<3`;>97>5$ef953e<fmi1=854i057>5<#lm0::n5adb822>=n9>91<7*kd;35g>hck3;<76g>7383>!bc28<h7cjl:0:8?l7093:1(ij517a8jae=9010e<9?:18'`a<6>j1ehn4>a:9j53`=83.oh7?9c:lgg?7e32c::h4?:%fg>40d3gnh6<m4;h35e?6=,mn1=;m4nea95a=<a8?m6=4+de822f=ilj0:i65f14694?"cl3;=o6`kc;3e?>o6:l0;66g>b683>>o6:o0;66g>b983>>i60l0;6)jk:0:g?kbd2910c<6l:18'`a<60m1ehn4>;:m2<d<72-no6<6k;of`>7=<g8226=4+de82<a=ilj0876a>8983>!bc282o7cjl:598k4>0290/hi4>8e9m`f<232e:4;4?:%fg>4>c3gnh6;54o0:6>5<#lm0:4i5adb84?>i60=0;6)jk:0:g?kbd2110c<6<:18'`a<60m1ehn46;:m2<7<72-no6<6k;of`>d=<g82:6=4+de82<a=ilj0i76a>7g83>!bc282o7cjl:b98k41b290/hi4>8e9m`f<c32e:;i4?:%fg>4>c3gnh6h54o05`>5<#lm0:4i5adb8e?>i6?k0;6)jk:0:g?kbd28:07b?8a;29 ab=91n0bim51098k41>290/hi4>8e9m`f<6:21d=:650;&g`?7?l2doo7?<;:m232<72-no6<6k;of`>42<3f;<:7>5$ef95=b<fmi1=854o0;6>5<#lm0:4i5adb822>=h90>1<7*kd;3;`>hck3;<76a>9283>!bc282o7cjl:0:8?j7>:3:1(ij519f8jae=9010c<7>:18'`a<60m1ehn4>a:9l5<6=83.oh7?7d:lgg?7e32e:4k4?:%fg>4>c3gnh6<m4;n3;f?6=,mn1=5j4nea95a=<g82;6=4+de82<a=ilj0:i65`16794?"cl3;3h6`kc;3e?>i6io0;6)jk:0cf?kbd2910c<ok:18'`a<6il1ehn4>;:m2eg<72-no6<oj;of`>7=<g8kj6=4+de82e`=ilj0876a>a883>!bc28kn7cjl:598k4g?290/hi4>ad9m`f<232e:m:4?:%fg>4gb3gnh6;54o0c5>5<#lm0:mh5adb84?>i6i<0;6)jk:0cf?kbd2110c<o;:18'`a<6il1ehn46;:m2e6<72-no6<oj;of`>d=<g8k96=4+de82e`=ilj0i76a>a183>!bc28kn7cjl:b98k4?a290/hi4>ad9m`f<c32e:5h4?:%fg>4gb3gnh6h54o0;g>5<#lm0:mh5adb8e?>i61j0;6)jk:0cf?kbd28:07b?6b;29 ab=9ho0bim51098k4?f290/hi4>ad9m`f<6:21d=4750;&g`?7fm2doo7?<;:m2==<72-no6<oj;of`>42<3f;2;7>5$ef95dc<fmi1=854o0`5>5<#lm0:mh5adb822>=h9k?1<7*kd;3ba>hck3;<76a>b583>!bc28kn7cjl:0:8?j7e;3:1(ij51`g8jae=9010c<l=:18'`a<6il1ehn4>a:9l5g7=83.oh7?ne:lgg?7e32e:n=4?:%fg>4gb3gnh6<m4;n3bg?6=,mn1=lk4nea95a=<g8k:6=4+de82e`=ilj0:i65`18494?"cl3;ji6`kc;3e?>d68:0;6<4?:1y'b4<f12B:<?5Gf79le=<722wij?4?:7g94?6|,o;1hk5G1108Lc0<R:<1ov:55;g9b?d=i3i1h7657;49=?{#l00:nl5a4g8:?k37201e4l4?;o;`>5=#i<0j;6*n6;c4?!gf2:1/mo4<;%c`>6=#im087)oj:29'ec<43-h;6>5+b080?!d52:1/n>4<;%`7>6=#j<087)l9:29'f2<43-h36>5+b880?!df2:1/no4<;%``>6=#jm087)lj:29'fc<43-i;6>5+c080?!e52:1/o>4<;%a7>6=#k<087)m9:29'g2<43-i36>5+c880?!ef2:1/oo4<;%a`>6=#km087)mj:39'gc<53-n;6i64$d29b5=#m<0nj6*j6;14?!c02:=0(ho5349'af<53-oo6?5+fg8ea>"6890mi6gj4;29?lg32900eh?50;9je6<722c??7>5;h66>5<<al81<75fe283>>oai3:1(ij5f89m`f<732cm47>5$ef9b<=ilj0:76a70;29 ab=?o1ehn4?;:m4a?6=,mn1;k5adb82?>i0l3:1(ij57g9m`f<532e<o7>5$ef93c=ilj0876a8b;29 ab=?o1ehn4;;:m4e?6=,mn1;k5adb86?>i?13:1(ij57g9m`f<132e347>5$ef93c=ilj0<76a77;29 ab=?o1ehn47;:m;2?6=,mn1;k5adb8:?>i?=3:1(ij57g9m`f<f32e387>5$ef93c=ilj0i76a73;29 ab=?o1ehn4l;:m;6?6=,mn1;k5adb8g?>i?93:1(ij57g9m`f<b32e<57>5$ef93c=ilj0m76a6f;29 ab=1l1ehn4?;:m:`?6=,mn15h5adb82?>if:3:1(ij5a09m`f<732ej<7>5$ef9e4=ilj0:76gid;29 ab=nj1ehn4?;:kef?6=,mn1jn5adb82?>o6l3:1(ij51b9m`f<732c:n7>5$ef95f=ilj0:76g>a;29 ab=9j1ehn4=;:k12?6=,mn1=n5adb80?>o5=3:1(ij51b9m`f<332c987>5$ef95f=ilj0>76g=3;29 ab=9j1ehn49;:k16?6=,mn1=n5adb84?>o593:1(ij51b9m`f<?32c9<7>5$ef95f=ilj0276g>f;29 ab=9j1ehn4n;:k2a?6=,mn1=n5adb8a?>o613:1(ij51b9m`f<d32c<47>5$ef932=ilj0;76g86;29 ab=?>1ehn4>;:k5=?6=,mn1:55adb83?>o1?3:1(ij5699m`f<632c=:7>5$ef92==ilj0976g95;29 ab=>11ehn4<;:k50?6=,mn1:55adb87?>o1;3:1(ij5699m`f<232c<>7>5$ef92==ilj0=76g81;29 ab=>11ehn48;:k44?6=,mn1:55adb8;?>o1n3:1(ij5699m`f<>32c=i7>5$ef92==ilj0j76g9d;29 ab=>11ehn4m;:k5g?6=,mn1:55adb8`?>o1j3:1(ij5699m`f<c32c=m7>5$ef92==ilj0n76g92;29 ab=>11ehn4i;:k6<?6=,mn19:5adb83?>o2>3:1(ij5569m`f<632c>97>5$ef912=ilj0976g:4;29 ab==>1ehn4<;:k67?6=,mn19:5adb87?>o2:3:1(ij5569m`f<232c==7>5$ef912=ilj0=76g90;29 ab==>1ehn48;:k6b?6=,mn19:5adb8;?>o2m3:1(ij5569m`f<>32c>h7>5$ef912=ilj0j76g:c;29 ab==>1ehn4m;:k6f?6=,mn19:5adb8`?>o2i3:1(ij5569m`f<c32c>57>5$ef912=ilj0n76g:1;29 ab==>1ehn4i;:k1f?6=,mn1>l5adb83?>o513:1(ij52`9m`f<632c947>5$ef96d=ilj0976g<4;29 ab=:h1ehn4<;:k07?6=,mn1>l5adb87?>o4:3:1(ij52`9m`f<232c8=7>5$ef96d=ilj0=76g<0;29 ab=:h1ehn48;:k1b?6=,mn1>l5adb8;?>o5m3:1(ij52`9m`f<>32c9h7>5$ef96d=ilj0j76g=c;29 ab=:h1ehn4m;:k13?6=,mn1>l5adb8`?>i>:3:1(ij5909m`f<732e2<7>5$ef9=4=ilj0:76a7f;29 ab=181ehn4=;:m;a?6=,mn15<5adb80?>i?l3:1(ij5909m`f<332e3o7>5$ef9=4=ilj0>76a6b;29 ab=181ehn49;:m:e?6=,mn15<5adb84?>i>13:1(ij5909m`f<?32e247>5$ef9=4=ilj0276a67;29 ab=181ehn4n;:m:2?6=,mn15<5adb8a?>i>=3:1(ij5909m`f<d32e287>5$ef9=4=ilj0o76a63;29 ab=181ehn4j;:m;f?6=,mn15<5adb8e?>o0=3:1(ij5759m`f<732c<?7>5$ef931=ilj0:76smf283>3c=83:p(k?5dg9K554<@o<0V>85cz691?c=n3h1m7m5d;:93?0=13w/h44>b`9m0c<>3g?;645a8`83?k?d291/m84n7:&b2?g03-kj6>5+ac80?!gd2:1/mi4<;%cf>6=#io087)l?:29'f4<43-h96>5+b280?!d32:1/n84<;%`5>6=#j>087)l7:29'f<<43-hj6>5+bc80?!dd2:1/ni4<;%`f>6=#jo087)m?:29'g4<43-i96>5+c280?!e32:1/o84<;%a5>6=#k>087)m7:29'g<<43-ij6>5+cc80?!ed2:1/oi4<;%af>7=#ko097)j?:e:8 `6=n91/i84jf:&f2?503-o<6>94$dc970=#mj097)kk:39'bc<am2.:<=4ie:kf0?6=3`k?6=44id394?=ni:0;66g;3;29?l222900eh<50;9ja6<722cmm7>5$ef9b<=ilj0;76gi8;29 ab=n01ehn4>;:m;4?6=,mn1;k5adb83?>i0m3:1(ij57g9m`f<632e<h7>5$ef93c=ilj0976a8c;29 ab=?o1ehn4<;:m4f?6=,mn1;k5adb87?>i0i3:1(ij57g9m`f<232e357>5$ef93c=ilj0=76a78;29 ab=?o1ehn48;:m;3?6=,mn1;k5adb8;?>i?>3:1(ij57g9m`f<>32e397>5$ef93c=ilj0j76a74;29 ab=?o1ehn4m;:m;7?6=,mn1;k5adb8`?>i?:3:1(ij57g9m`f<c32e3=7>5$ef93c=ilj0n76a89;29 ab=?o1ehn4i;:m:b?6=,mn15h5adb83?>i>l3:1(ij59d9m`f<632ej>7>5$ef9e4=ilj0;76an0;29 ab=i81ehn4>;:ke`?6=,mn1jn5adb83?>oaj3:1(ij5fb9m`f<632c:h7>5$ef95f=ilj0;76g>b;29 ab=9j1ehn4>;:k2e?6=,mn1=n5adb81?>o5>3:1(ij51b9m`f<432c997>5$ef95f=ilj0?76g=4;29 ab=9j1ehn4:;:k17?6=,mn1=n5adb85?>o5:3:1(ij51b9m`f<032c9=7>5$ef95f=ilj0376g=0;29 ab=9j1ehn46;:k2b?6=,mn1=n5adb8b?>o6m3:1(ij51b9m`f<e32c:57>5$ef95f=ilj0h76g88;29 ab=?>1ehn4?;:k42?6=,mn1;:5adb82?>o113:1(ij5699m`f<732c=;7>5$ef92==ilj0:76g96;29 ab=>11ehn4=;:k51?6=,mn1:55adb80?>o1<3:1(ij5699m`f<332c=?7>5$ef92==ilj0>76g82;29 ab=>11ehn49;:k45?6=,mn1:55adb84?>o083:1(ij5699m`f<?32c=j7>5$ef92==ilj0276g9e;29 ab=>11ehn4n;:k5`?6=,mn1:55adb8a?>o1k3:1(ij5699m`f<d32c=n7>5$ef92==ilj0o76g9a;29 ab=>11ehn4j;:k56?6=,mn1:55adb8e?>o203:1(ij5569m`f<732c>:7>5$ef912=ilj0:76g:5;29 ab==>1ehn4=;:k60?6=,mn19:5adb80?>o2;3:1(ij5569m`f<332c>>7>5$ef912=ilj0>76g91;29 ab==>1ehn49;:k54?6=,mn19:5adb84?>o2n3:1(ij5569m`f<?32c>i7>5$ef912=ilj0276g:d;29 ab==>1ehn4n;:k6g?6=,mn19:5adb8a?>o2j3:1(ij5569m`f<d32c>m7>5$ef912=ilj0o76g:9;29 ab==>1ehn4j;:k65?6=,mn19:5adb8e?>o5j3:1(ij52`9m`f<732c957>5$ef96d=ilj0:76g=8;29 ab=:h1ehn4=;:k00?6=,mn1>l5adb80?>o4;3:1(ij52`9m`f<332c8>7>5$ef96d=ilj0>76g<1;29 ab=:h1ehn49;:k04?6=,mn1>l5adb84?>o5n3:1(ij52`9m`f<?32c9i7>5$ef96d=ilj0276g=d;29 ab=:h1ehn4n;:k1g?6=,mn1>l5adb8a?>o5?3:1(ij52`9m`f<d32e2>7>5$ef9=4=ilj0;76a60;29 ab=181ehn4>;:m;b?6=,mn15<5adb81?>i?m3:1(ij5909m`f<432e3h7>5$ef9=4=ilj0?76a7c;29 ab=181ehn4:;:m:f?6=,mn15<5adb85?>i>i3:1(ij5909m`f<032e257>5$ef9=4=ilj0376a68;29 ab=181ehn46;:m:3?6=,mn15<5adb8b?>i>>3:1(ij5909m`f<e32e297>5$ef9=4=ilj0h76a64;29 ab=181ehn4k;:m:7?6=,mn15<5adb8f?>i?j3:1(ij5909m`f<a32c<97>5$ef931=ilj0;76g83;29 ab=?=1ehn4>;:\7fab1<72?o1<7>t$g39`c=O9980Dk84Z249g~2==3o1j7l5a;a9`?>=?3<157s+d882fd=i<o027c;?:89m<d<73g3h6=5+a48b3>"f>3k<7)on:29'eg<43-kh6>5+ae80?!gb2:1/mk4<;%`3>6=#j8087)l=:29'f6<43-h?6>5+b480?!d12:1/n:4<;%`;>6=#j0087)ln:29'fg<43-hh6>5+be80?!db2:1/nk4<;%a3>6=#k8087)m=:29'g6<43-i?6>5+c480?!e12:1/o:4<;%a;>6=#k0087)mn:29'gg<43-ih6>5+ce80?!eb2;1/ok4=;%f3>a><,l:1j=5+e48fb>"b>39<7)k8:258 `g=;<1/in4=;%gg>7=#no0mi6*>018ea>ob<3:17do;:188m`7=831bm>4?::k77?6=3`>>6=44id094?=nm:0;66gia;29 ab=n01ehn4?;:ke<?6=,mn1j45adb82?>i?83:1(ij57g9m`f<732e<i7>5$ef93c=ilj0:76a8d;29 ab=?o1ehn4=;:m4g?6=,mn1;k5adb80?>i0j3:1(ij57g9m`f<332e<m7>5$ef93c=ilj0>76a79;29 ab=?o1ehn49;:m;<?6=,mn1;k5adb84?>i??3:1(ij57g9m`f<?32e3:7>5$ef93c=ilj0276a75;29 ab=?o1ehn4n;:m;0?6=,mn1;k5adb8a?>i?;3:1(ij57g9m`f<d32e3>7>5$ef93c=ilj0o76a71;29 ab=?o1ehn4j;:m4=?6=,mn1;k5adb8e?>i>n3:1(ij59d9m`f<732e2h7>5$ef9=`=ilj0:76an2;29 ab=i81ehn4?;:mb4?6=,mn1m<5adb82?>oal3:1(ij5fb9m`f<732cmn7>5$ef9bf=ilj0:76g>d;29 ab=9j1ehn4?;:k2f?6=,mn1=n5adb82?>o6i3:1(ij51b9m`f<532c9:7>5$ef95f=ilj0876g=5;29 ab=9j1ehn4;;:k10?6=,mn1=n5adb86?>o5;3:1(ij51b9m`f<132c9>7>5$ef95f=ilj0<76g=1;29 ab=9j1ehn47;:k14?6=,mn1=n5adb8:?>o6n3:1(ij51b9m`f<f32c:i7>5$ef95f=ilj0i76g>9;29 ab=9j1ehn4l;:k4<?6=,mn1;:5adb83?>o0>3:1(ij5769m`f<632c=57>5$ef92==ilj0;76g97;29 ab=>11ehn4>;:k52?6=,mn1:55adb81?>o1=3:1(ij5699m`f<432c=87>5$ef92==ilj0?76g93;29 ab=>11ehn4:;:k46?6=,mn1:55adb85?>o093:1(ij5699m`f<032c<<7>5$ef92==ilj0376g9f;29 ab=>11ehn46;:k5a?6=,mn1:55adb8b?>o1l3:1(ij5699m`f<e32c=o7>5$ef92==ilj0h76g9b;29 ab=>11ehn4k;:k5e?6=,mn1:55adb8f?>o1:3:1(ij5699m`f<a32c>47>5$ef912=ilj0;76g:6;29 ab==>1ehn4>;:k61?6=,mn19:5adb81?>o2<3:1(ij5569m`f<432c>?7>5$ef912=ilj0?76g:2;29 ab==>1ehn4:;:k55?6=,mn19:5adb85?>o183:1(ij5569m`f<032c>j7>5$ef912=ilj0376g:e;29 ab==>1ehn46;:k6`?6=,mn19:5adb8b?>o2k3:1(ij5569m`f<e32c>n7>5$ef912=ilj0h76g:a;29 ab==>1ehn4k;:k6=?6=,mn19:5adb8f?>o293:1(ij5569m`f<a32c9n7>5$ef96d=ilj0;76g=9;29 ab=:h1ehn4>;:k1<?6=,mn1>l5adb81?>o4<3:1(ij52`9m`f<432c8?7>5$ef96d=ilj0?76g<2;29 ab=:h1ehn4:;:k05?6=,mn1>l5adb85?>o483:1(ij52`9m`f<032c9j7>5$ef96d=ilj0376g=e;29 ab=:h1ehn46;:k1`?6=,mn1>l5adb8b?>o5k3:1(ij52`9m`f<e32c9;7>5$ef96d=ilj0h76a62;29 ab=181ehn4?;:m:4?6=,mn15<5adb82?>i?n3:1(ij5909m`f<532e3i7>5$ef9=4=ilj0876a7d;29 ab=181ehn4;;:m;g?6=,mn15<5adb86?>i>j3:1(ij5909m`f<132e2m7>5$ef9=4=ilj0<76a69;29 ab=181ehn47;:m:<?6=,mn15<5adb8:?>i>?3:1(ij5909m`f<f32e2:7>5$ef9=4=ilj0i76a65;29 ab=181ehn4l;:m:0?6=,mn15<5adb8g?>i>;3:1(ij5909m`f<b32e3n7>5$ef9=4=ilj0m76g85;29 ab=?=1ehn4?;:k47?6=,mn1;95adb82?>{en<0;6;k50;2x c7=lo1C==<4Hg48^60=kr>197k5f;`9e?e=l321;7859;\7f'`<<6jh1e8k46;o73><=i0h0;7c7l:19'e0<f?2.j:7o8;%cb>6=#ik087)ol:29'ea<43-kn6>5+ag80?!d72:1/n<4<;%`1>6=#j:087)l;:29'f0<43-h=6>5+b680?!d?2:1/n44<;%`b>6=#jk087)ll:29'fa<43-hn6>5+bg80?!e72:1/o<4<;%a1>6=#k:087)m;:29'g0<43-i=6>5+c680?!e?2:1/o44<;%ab>6=#kk087)ml:29'ga<43-in6?5+cg81?!b72m20(h>5f19'a0<bn2.n:7=8;%g4>61<,lk1?85+eb81?!cc2;1/jk4ie:&245<am2cn87>5;hc7>5<<al;1<75fa283>>o3;3:17d:::188m`4=831bi>4?::kee?6=,mn1j45adb83?>oa03:1(ij5f89m`f<632e3<7>5$ef93c=ilj0;76a8e;29 ab=?o1ehn4>;:m4`?6=,mn1;k5adb81?>i0k3:1(ij57g9m`f<432e<n7>5$ef93c=ilj0?76a8a;29 ab=?o1ehn4:;:m;=?6=,mn1;k5adb85?>i?03:1(ij57g9m`f<032e3;7>5$ef93c=ilj0376a76;29 ab=?o1ehn46;:m;1?6=,mn1;k5adb8b?>i?<3:1(ij57g9m`f<e32e3?7>5$ef93c=ilj0h76a72;29 ab=?o1ehn4k;:m;5?6=,mn1;k5adb8f?>i013:1(ij57g9m`f<a32e2j7>5$ef9=`=ilj0;76a6d;29 ab=1l1ehn4>;:mb6?6=,mn1m<5adb83?>if83:1(ij5a09m`f<632cmh7>5$ef9bf=ilj0;76gib;29 ab=nj1ehn4>;:k2`?6=,mn1=n5adb83?>o6j3:1(ij51b9m`f<632c:m7>5$ef95f=ilj0976g=6;29 ab=9j1ehn4<;:k11?6=,mn1=n5adb87?>o5<3:1(ij51b9m`f<232c9?7>5$ef95f=ilj0=76g=2;29 ab=9j1ehn48;:k15?6=,mn1=n5adb8;?>o583:1(ij51b9m`f<>32c:j7>5$ef95f=ilj0j76g>e;29 ab=9j1ehn4m;:k2=?6=,mn1=n5adb8`?>o003:1(ij5769m`f<732c<:7>5$ef932=ilj0:76g99;29 ab=>11ehn4?;:k53?6=,mn1:55adb82?>o1>3:1(ij5699m`f<532c=97>5$ef92==ilj0876g94;29 ab=>11ehn4;;:k57?6=,mn1:55adb86?>o0:3:1(ij5699m`f<132c<=7>5$ef92==ilj0<76g80;29 ab=>11ehn47;:k5b?6=,mn1:55adb8:?>o1m3:1(ij5699m`f<f32c=h7>5$ef92==ilj0i76g9c;29 ab=>11ehn4l;:k5f?6=,mn1:55adb8g?>o1i3:1(ij5699m`f<b32c=>7>5$ef92==ilj0m76g:8;29 ab==>1ehn4?;:k62?6=,mn19:5adb82?>o2=3:1(ij5569m`f<532c>87>5$ef912=ilj0876g:3;29 ab==>1ehn4;;:k66?6=,mn19:5adb86?>o193:1(ij5569m`f<132c=<7>5$ef912=ilj0<76g:f;29 ab==>1ehn47;:k6a?6=,mn19:5adb8:?>o2l3:1(ij5569m`f<f32c>o7>5$ef912=ilj0i76g:b;29 ab==>1ehn4l;:k6e?6=,mn19:5adb8g?>o213:1(ij5569m`f<b32c>=7>5$ef912=ilj0m76g=b;29 ab=:h1ehn4?;:k1=?6=,mn1>l5adb82?>o503:1(ij52`9m`f<532c887>5$ef96d=ilj0876g<3;29 ab=:h1ehn4;;:k06?6=,mn1>l5adb86?>o493:1(ij52`9m`f<132c8<7>5$ef96d=ilj0<76g=f;29 ab=:h1ehn47;:k1a?6=,mn1>l5adb8:?>o5l3:1(ij52`9m`f<f32c9o7>5$ef96d=ilj0i76g=7;29 ab=:h1ehn4l;:m:6?6=,mn15<5adb83?>i>83:1(ij5909m`f<632e3j7>5$ef9=4=ilj0976a7e;29 ab=181ehn4<;:m;`?6=,mn15<5adb87?>i?k3:1(ij5909m`f<232e2n7>5$ef9=4=ilj0=76a6a;29 ab=181ehn48;:m:=?6=,mn15<5adb8;?>i>03:1(ij5909m`f<>32e2;7>5$ef9=4=ilj0j76a66;29 ab=181ehn4m;:m:1?6=,mn15<5adb8`?>i><3:1(ij5909m`f<c32e2?7>5$ef9=4=ilj0n76a7b;29 ab=181ehn4i;:k41?6=,mn1;95adb83?>o0;3:1(ij5759m`f<632wxh;4?:93x94642h201k<51e9>b7<6n27m>7?j;<d1>4?<5o81>o52f381`>;a:38h70h=:3589c4==116j?4:6:?e6?3234l968:4=g0916=:n;0>>63i2;42?8`52?:01k<5689>b7<1?27m>789;<d1>33<5o81:952f3857>;a:3=970h=:6389c4=?<16j?483:?e6?1?34l96:84=g09a4=:n;0n>63i2;g0?8`52l>01k=51e9>b6<6n27m?7?j;<d0>4?<5o91>o52f281`>;a;38h70h<:3589c5==116j>4:6:?e7?3234l868:4=g1916=:n:0>>63i3;42?8`42?:01k=5689>b6<1?27m?789;<d0>33<5o91:952f2857>;a;3=970h<:6389c5=?<16j>483:?e7?1?34l86:84=g19a4=:n:0n>63i3;g0?8`42l>01k:51e9>b1<6n27m87?j;<d7>4?<5o>1>o52f581`>;a<38h70h;:3589c2==116j94:6:?e0?3234l?68:4=g6916=:n=0>>63i4;42?8`32?:01k:5689>b1<1?27m8789;<d7>33<5o>1:952f5857>;a<3=970h;:6389c2=?<16j9483:?e0?1?34l?6:84=g69a4=:n=0n>63i4;g0?8`32l>01k;51e9>b0<6n27m97?j;<d6>4?<5o?1>o52f481`>;a=38h70h::3589c3==116j84:6:?e1?3234l>68:4=g7916=:n<0>>63i5;42?8`22?:01k;5689>b0<1?27m9789;<d6>33<5o?1:952f4857>;a=3=970h::6389c3=?<16j8483:?e1?1?34l>6:84=g79a4=:n<0n>63i5;g0?8`22l>0q~?66;296~X61?16j?47b:\7fp5d7=838pR<o>;<d1><5<uz;jo7>52z\2ef=:n;0286s|1c294?4|V8h;70h=:878yv7e93:1>vP>b09>b7<>>2wx=o<50;0xZ4d534l96494}r3a7?6=:rT:n>52f38:<>{t9k>1<7<t^0`7?8`52030q~?m5;296~X6j<16j>47b:\7fp5g0=838pR<l9;<d0><5<uz;2;7>52z\2=2=:n:0286s|18:94?4|V83370h<:878yv7>13:1>vP>989>b6<>>2wx=4o50;0xZ4?f34l86494}r3:f?6=:rT:5o52f28:<>{t90i1<7<t^0;`?8`42030q~?6d;296~X61m16j947b:\7fp5<c=838pR<7j;<d7><5<uz;2j7>52z\2=c=:n=0286s|1`294?4|V8k;70h;:878yv7f:3:1>vP>a39>b1<>>2wx=l=50;0xZ4g434l?6494}r3b0?6=:rT:m952f58:<>{t9h?1<7<t^0c6?8`32030q~?n6;296~X6i?16j847b:\7fp5d1=838pR<o8;<d6><5<uz;j47>52z\2e==:n<0286s|1`;94?4|V8k270h::878yv7fi3:1>vP>a`9>b0<>>2wx=ll50;0xZ4ge34l>6494}r3b`?6=:rT:mi52f48:<>{t9hl1<7<t^0ce?8`22030q~?85;296~X6?<16j?489:\7fp5=6=838pR<6?;<d1>=7<uz;3n7>52z\2<g=:n;03>6s|19d94?4|V82m70h=:918yv7>83:1>vP>919>b7<?<2wx=4?50;0xZ4?634l965;4}r3:6?6=:rT:5?52f38;2>{t9091<7<t^0;0?8`521=0q~?64;296~X61=16j>489:\7fp5<3=838pR<7:;<d0>=7<uz;<:7>52z\233=:n:03>6s|16594?4|V8=<70h<:918yv7003:1>vP>799>b6<?<2wx=:750;0xZ41>34l865;4}r34e?6=:rT:;l52f28;2>{t9>h1<7<t^05a?8`421=0q~?8c;296~X6?j16j9489:\7fp52b=838pR<9k;<d7>=7<uz;<i7>52z\23`=:n=03>6s|16d94?4|V8=m70h;:918yv7?93:1>vP>809>b1<?<2wx=5<50;0xZ4>534l?65;4}r3;7?6=:rT:4>52f58;2>{t91>1<7<t^0:7?8`321=0q~?75;296~X60<16j8489:\7fp5=0=838pR<69;<d6>=7<uz;3;7>52z\2<2=:n<03>6s|19:94?4|V82370h::918yv7?13:1>vP>889>b0<?<2wx=5o50;0xZ4>f34l>65;4}r3;g?6=:rT:4n52f48;2>{t91o1<7<t^0:f?8`221=0q~?m8;291~X6j116j?4n4:?e7?g334l?6l:4=g79e1=z{88m6=4:{_31b>;a:3>>70h<:5789c2=<<16j84;5:\7fp5g1=83?pR<l8;<d1>d5<5o91m>52f58b7>;a=3k87p}>2d83>0}Y9;o01k<5429>b6<3;27m87:<;<d6>15<uz;>87>52z\211=:n;0=>6s|14d94?4|V8?m70h=:7c8yv71i3:1>vP>6`9>b7<1j2wx=;k50;0xZ40b34l96;m4}r35b?6=:rT::k52f385`>{t9>:1<7<t^053?8`52?o0q~?81;296~X6?816j?49f:\7fp524=838pR<9=;<d1>26<uz;<?7>52z\236=:n:0=>6s|16694?4|V8=?70h<:7c8yv72=3:1>vP>549>b6<1j2wx=8850;0xZ43134l86;m4}r363?6=:rT:9:52f285`>{t9<21<7<t^07;?8`42?o0q~?:9;296~X6=016j>49f:\7fp50g=838pR<;n;<d0>26<uz;>n7>52z\21g=:n=0=>6s|14a94?4|V8?h70h;:7c8yv72l3:1>vP>5e9>b1<1j2wx=8k50;0xZ43b34l?6;m4}r354?6=:rT::=52f585`>{t9?;1<7<t^042?8`32?o0q~?92;296~X6>;16j949f:\7fp535=838pR<8<;<d7>26<uz;=87>52z\221=:n<0=>6s|17794?4|V8<>70h::7c8yv71>3:1>vP>679>b0<1j2wx=;950;0xZ40034l>6;m4}r35<?6=:rT::552f485`>{t9?31<7<t^04:?8`22?o0q~?9b;296~X6>k16j849f:\7fp53b=838pR<8k;<d6>26<uz;:97>55z\250=:n;09i63i3;0f?8`32;o01k;52d9~w471290>wS?>6:?e6?4a34l86?h4=g696c=:n<09j6s|10594?3|V8;<70h=:2289c5=;916j94<0:?e1?573ty:=54?:4y]54><5o81?<52f2805>;a<39:70h::238yv7613:19vP>189>b7<4:27m?7==;<d7>64<5o?1??5rs03b>5<2sW;:m63i2;10?8`42:901k:5329>b0<4;2wx=<l50;7xZ47e34l96>:4=g1971=:n=08863i5;17?xu69j0;68uQ10a89c4=:116j>4=8:?e0?4?34l>6?64}r32a?6==rT:=h52f381=>;a;38270h;:3;89c3=:01v\7f<m?:180\7f[7d827m>7hk;<d1>cd<uz;h=7>53z\2g4=:n:0mh63i3;da?xu6k;0;6>uQ1b089c2=nm16j94ib:\7fp5f2=839pR<m;;<d6>cb<5o?1jo5rs010>5<5sW;8?63i2;72?xu6;l0;6?uQ12g89c4==01v\7f<:6:181\7f[73127m>7;n;|q20a<72;qU=9j4=g091g=z{8>n6=4={_37a>;a:3?h7p}>4g83>7}Y9=l01k<55e9~w4372909wS?:0:?e6?3b3ty:9<4?:3y]507<5o819k5rs071>5<5sW;>>63i3;72?xu6=:0;6?uQ14189c5==01v\7f<=;:181\7f[74<27m?7;n;|q270<72;qU=>;4=g191g=z{89=6=4={_302>;a;3?h7p}>3683>7}Y9:=01k=55e9~w45?2909wS?<8:?e7?3b3ty:?44?:3y]56?<5o919k5rs01b>5<5sW;8m63i4;72?xu6;k0;6?uQ12`89c2==01v\7f<=l:181\7f[74k27m87;n;|q27a<72;qU=>j4=g691g=z{89m6=4={_30b>;a<3?h7p}>4183>7}Y9=:01k:55e9~w4262909wS?;1:?e0?3b3ty:8?4?:3y]514<5o>19k5rs060>5<5sW;??63i5;72?xu6<=0;6?uQ15689c3==01v\7f<:::181\7f[73=27m97;n;|q203<72;qU=984=g791g=z{8><6=4={_373>;a=3?h7p}>4983>7}Y9=201k;55e9~w42f2909wS?;a:?e1?3b3ty:8n4?:3y]51e<5o?19k5rs02a>5<2sW;;n63i2;03?8`42;:01k:5219>b0<582wx==m50;7xZ46d34l96??4=g1964=:n=09=63i5;02?xu68m0;68uQ11f89c4=:;16j>4=2:?e0?4534l>6?<4}r33a?6==rT:<h52f3817>;a;38870h;:3189c3=::1v\7f<>i:186\7f[77n27m>7<;;<d0>72<5o>1>952f4810>{t98:1<7;t^033?8`52;?01k=5249>b1<5=27m97<:;|q254<72<qU=<?4=g0963=:n:09:63i4;05?8`22;<0q~?>2;291~X69;16j?4>a:?e7?7f34l?6<o4=g795d=z{8;?6=4:{_320>;a:3;i70h<:0`89c2=9k16j84>b:\7fp5gd=839pR<lm;<d1>cg<5o81j55rs0``>5<4sW;io63i3;db?8`42o20q~?md;297~X6jm16j94ia:?e0?`?3ty:nk4?:2y]5g`<5o?1jl52f48e<>{zf;<<6=4>{Id5?xh5>10;6<uGf79~j70>290:wEh9;|l12d<728qCj;5rn34a>5<6sAl=7p`=6b83>4}On?1vb?8k:182\7fM`13td9:h4?:0yKb3=zf;<m6=4>{Id5?xh5?90;6<uGf79~j716290:wEh9;|l137<728qCj;5rn350>5<6sAl=7p`=7583>4}On?1vb?9::182\7fM`13td9;;4?:0yKb3=zf;=<6=4>{Id5?xh5?10;6<uGf79~j71>290:wEh9;|l13d<728qCj;5rn35a>5<6sAl=7p`=7b83>4}On?1vb?9k:182\7fM`13td9;h4?:0yKb3=zf;=m6=4>{Id5?xh5090;6<uGf79~j7>6290:wEh9;|l1<7<728qCj;5rn3:0>5<6sAl=7p`=8583>4}On?1vb?6::182\7fM`13td94;4?:0yKb3=zf;2<6=4>{Id5?xh5010;6<uGf79~j7>>290:wEh9;|l1<d<728qCj;5rn3:a>5<6sAl=7p`=8b83>4}On?1vb?6k:182\7fM`13td94h4?:0yKb3=zf;2m6=4>{Id5?xh5190;6<uGf79~j7?6290:wEh9;|l1=7<728qCj;5rn3;0>5<6sAl=7p`=9583>4}On?1vb?7::182\7fM`13td95;4?:0yKb3=zf;3<6=4>{Id5?xh5110;6<uGf79~j7?>290:wEh9;|l1=d<728qCj;5rn3;a>5<6sAl=7p`=9b83>4}On?1vb?7k:182\7fM`13td95h4?:0yKb3=zf;3m6=4>{Id5?xh5i90;6<uGf79~j7g6290:wEh9;|l1e7<728qCj;5rn3c0>5<6sAl=7p`=a583>4}On?1vb?o::182\7fM`13td9m;4?:0yKb3=zf;k<6=4>{Id5?xh5i10;6<uGf79~j7g>290:wEh9;|l1ed<728qCj;5rn3ca>5<6sAl=7p`=ab83>4}On?1vb?ok:182\7fM`13td9mh4?:0yKb3=zf;km6=4>{Id5?xh5j90;6<uGf79~j7d6290:wEh9;|l1f7<728qCj;5rn3`0>5<6sAl=7p`=b583>4}On?1vb?l::182\7fM`13td9n;4?:0yKb3=zf;h<6=4>{Id5?xh5j10;6<uGf79~j7d>290:wEh9;|l1fd<728qCj;5rn3`a>5<6sAl=7p`=bb83>4}On?1vb?lk:182\7fM`13td9nh4?:0yKb3=zf;hm6=4>{Id5?xh5k90;6<uGf79~j7e6290:wEh9;|l1g7<728qCj;5rn3a0>5<6sAl=7p`=c583>4}On?1vb?m::182\7fM`13td9o;4?:0yKb3=zf;i<6=4>{Id5?xh5k10;6<uGf79~j7e>290:wEh9;|l1gd<728qCj;5rn3aa>5<6sAl=7p`=cb83>4}On?1vb?mk:182\7fM`13td9oh4?:0yKb3=zf;im6=4>{Id5?xh5l90;6<uGf79~j7b6290:wEh9;|l1`7<728qCj;5rn3f0>5<6sAl=7p`=d583>4}On?1vb?j::182\7fM`13td9h;4?:0yKb3=zf;n<6=4>{Id5?xh5l10;6<uGf79~j7b>290:wEh9;|l1`d<728qCj;5rn3fa>5<6sAl=7p`=db83>4}On?1vb?jk:182\7fM`13td9hh4?:0yKb3=zf;nm6=4>{Id5?xh5m90;6<uGf79~j7c6290:wEh9;|l1a7<728qCj;5rn3g0>5<6sAl=7p`=e583>4}On?1vb?k::182\7fM`13td9i;4?:0yKb3=zf;o<6=4>{Id5?xh5m10;6<uGf79~j7c>290:wEh9;|l1ad<728qCj;5rn3ga>5<6sAl=7p`=eb83>4}On?1vb?kk:182\7fM`13td9ih4?:0yKb3=zf;om6=4>{Id5?xh5n90;6<uGf79~j7`6290:wEh9;|l1b7<728qCj;5rn3d0>5<6sAl=7p`=f583>4}On?1vb?h::182\7fM`13td9j;4?:0yKb3=zf;l<6=4>{Id5?xh5n10;6<uGf79~j7`>290:wEh9;|l1bd<728qCj;5rn3da>5<6sAl=7p`=fb83>4}On?1vb?hk:182\7fM`13td9jh4?:0yKb3=zf;lm6=4>{Id5?xh4890;6<uGf79~j666290:wEh9;|l047<728qCj;5rn220>5<6sAl=7p`<0583>4}On?1vb>>::182\7fM`13twvqMNL{2c6>a7al:;9<pNOBz2~DEV|uIJ
\ No newline at end of file
+++ /dev/null
---------------------------------------------------------------------------------
--- This file is owned and controlled by Xilinx and must be used solely --
--- for design, simulation, implementation and creation of design files --
--- limited to Xilinx devices or technologies. Use with non-Xilinx --
--- devices or technologies is expressly prohibited and immediately --
--- terminates your license. --
--- --
--- XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS" SOLELY --
--- FOR USE IN DEVELOPING PROGRAMS AND SOLUTIONS FOR XILINX DEVICES. BY --
--- PROVIDING THIS DESIGN, CODE, OR INFORMATION AS ONE POSSIBLE --
--- IMPLEMENTATION OF THIS FEATURE, APPLICATION OR STANDARD, XILINX IS --
--- MAKING NO REPRESENTATION THAT THIS IMPLEMENTATION IS FREE FROM ANY --
--- CLAIMS OF INFRINGEMENT, AND YOU ARE RESPONSIBLE FOR OBTAINING ANY --
--- RIGHTS YOU MAY REQUIRE FOR YOUR IMPLEMENTATION. XILINX EXPRESSLY --
--- DISCLAIMS ANY WARRANTY WHATSOEVER WITH RESPECT TO THE ADEQUACY OF THE --
--- IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OR --
--- REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE FROM CLAIMS OF --
--- INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A --
--- PARTICULAR PURPOSE. --
--- --
--- Xilinx products are not intended for use in life support appliances, --
--- devices, or systems. Use in such applications are expressly --
--- prohibited. --
--- --
--- (c) Copyright 1995-2013 Xilinx, Inc. --
--- All rights reserved. --
---------------------------------------------------------------------------------
---------------------------------------------------------------------------------
--- You must compile the wrapper file control_bram.vhd when simulating
--- the core, control_bram. When compiling the wrapper file, be sure to
--- reference the XilinxCoreLib VHDL simulation library. For detailed
--- instructions, please refer to the "CORE Generator Help".
-
--- The synthesis directives "translate_off/translate_on" specified
--- below are supported by Xilinx, Mentor Graphics and Synplicity
--- synthesis tools. Ensure they are correct for your synthesis tool(s).
-
-LIBRARY ieee;
-USE ieee.std_logic_1164.ALL;
--- synthesis translate_off
-LIBRARY XilinxCoreLib;
--- synthesis translate_on
-ENTITY control_bram IS
- PORT (
- clka : IN STD_LOGIC;
- ena : IN STD_LOGIC;
- wea : IN STD_LOGIC_VECTOR(3 DOWNTO 0);
- addra : IN STD_LOGIC_VECTOR(8 DOWNTO 0);
- dina : IN STD_LOGIC_VECTOR(31 DOWNTO 0);
- douta : OUT STD_LOGIC_VECTOR(31 DOWNTO 0);
- clkb : IN STD_LOGIC;
- enb : IN STD_LOGIC;
- web : IN STD_LOGIC_VECTOR(3 DOWNTO 0);
- addrb : IN STD_LOGIC_VECTOR(8 DOWNTO 0);
- dinb : IN STD_LOGIC_VECTOR(31 DOWNTO 0);
- doutb : OUT STD_LOGIC_VECTOR(31 DOWNTO 0)
- );
-END control_bram;
-
-ARCHITECTURE control_bram_a OF control_bram IS
--- synthesis translate_off
-COMPONENT wrapped_control_bram
- PORT (
- clka : IN STD_LOGIC;
- ena : IN STD_LOGIC;
- wea : IN STD_LOGIC_VECTOR(3 DOWNTO 0);
- addra : IN STD_LOGIC_VECTOR(8 DOWNTO 0);
- dina : IN STD_LOGIC_VECTOR(31 DOWNTO 0);
- douta : OUT STD_LOGIC_VECTOR(31 DOWNTO 0);
- clkb : IN STD_LOGIC;
- enb : IN STD_LOGIC;
- web : IN STD_LOGIC_VECTOR(3 DOWNTO 0);
- addrb : IN STD_LOGIC_VECTOR(8 DOWNTO 0);
- dinb : IN STD_LOGIC_VECTOR(31 DOWNTO 0);
- doutb : OUT STD_LOGIC_VECTOR(31 DOWNTO 0)
- );
-END COMPONENT;
-
--- Configuration specification
- FOR ALL : wrapped_control_bram USE ENTITY XilinxCoreLib.blk_mem_gen_v7_3(behavioral)
- GENERIC MAP (
- c_addra_width => 9,
- c_addrb_width => 9,
- c_algorithm => 0,
- c_axi_id_width => 4,
- c_axi_slave_type => 0,
- c_axi_type => 1,
- c_byte_size => 8,
- c_common_clk => 0,
- c_default_data => "0",
- c_disable_warn_bhv_coll => 0,
- c_disable_warn_bhv_range => 0,
- c_enable_32bit_address => 0,
- c_family => "spartan6",
- c_has_axi_id => 0,
- c_has_ena => 1,
- c_has_enb => 1,
- c_has_injecterr => 0,
- c_has_mem_output_regs_a => 0,
- c_has_mem_output_regs_b => 0,
- c_has_mux_output_regs_a => 0,
- c_has_mux_output_regs_b => 0,
- c_has_regcea => 0,
- c_has_regceb => 0,
- c_has_rsta => 0,
- c_has_rstb => 0,
- c_has_softecc_input_regs_a => 0,
- c_has_softecc_output_regs_b => 0,
- c_init_file => "BlankString",
- c_init_file_name => "no_coe_file_loaded",
- c_inita_val => "0",
- c_initb_val => "0",
- c_interface_type => 0,
- c_load_init_file => 0,
- c_mem_type => 2,
- c_mux_pipeline_stages => 0,
- c_prim_type => 3,
- c_read_depth_a => 288,
- c_read_depth_b => 288,
- c_read_width_a => 32,
- c_read_width_b => 32,
- c_rst_priority_a => "CE",
- c_rst_priority_b => "CE",
- c_rst_type => "SYNC",
- c_rstram_a => 0,
- c_rstram_b => 0,
- c_sim_collision_check => "ALL",
- c_use_bram_block => 0,
- c_use_byte_wea => 1,
- c_use_byte_web => 1,
- c_use_default_data => 1,
- c_use_ecc => 0,
- c_use_softecc => 0,
- c_wea_width => 4,
- c_web_width => 4,
- c_write_depth_a => 288,
- c_write_depth_b => 288,
- c_write_mode_a => "WRITE_FIRST",
- c_write_mode_b => "WRITE_FIRST",
- c_write_width_a => 32,
- c_write_width_b => 32,
- c_xdevicefamily => "spartan6"
- );
--- synthesis translate_on
-BEGIN
--- synthesis translate_off
-U0 : wrapped_control_bram
- PORT MAP (
- clka => clka,
- ena => ena,
- wea => wea,
- addra => addra,
- dina => dina,
- douta => douta,
- clkb => clkb,
- enb => enb,
- web => web,
- addrb => addrb,
- dinb => dinb,
- doutb => doutb
- );
--- synthesis translate_on
-
-END control_bram_a;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;
use ieee.numeric_std.all;
+use work.lx_rocon_pkg.all;
-- IRC reader module
entity irc_reader is
port
(
- clk : in std_logic;
- reset : in std_logic;
- a0, b0 : in std_logic;
- index0 : in std_logic;
- mark0 : in std_logic;
-
- qcount : out std_logic_vector (31 downto 0);
- ab_event : out std_logic;
- ab_error : out std_logic;
- out_index : out std_logic;
- out_mark : out std_logic
+ clk : in std_logic;
+ reset : in std_logic;
+ a0, b0 : in std_logic;
+ index0 : in std_logic;
+ mark0 : in std_logic;
+
+ qcount : out std_logic_vector (31 downto 0);
+ qcount_index : out std_logic_vector (31 downto 0);
+ ab_event : out std_logic;
+ ab_error : out std_logic;
+ out_mark : out std_logic
);
end irc_reader;
-architecture Behavioral of irc_reader is
- component qcounter
- port
- (
- clk : in std_logic;
- reset : in std_logic;
- a0, b0 : in std_logic;
-
- a_rise : out std_logic;
- a_fall : out std_logic;
- b_rise : out std_logic;
- b_fall : out std_logic;
-
- qcount : out std_logic_vector (31 downto 0);
- ab_event : out std_logic;
- ab_error : out std_logic
- );
- end component;
-
- component dff
- port
- (
- clk : in std_logic;
- reset : in std_logic;
- d : in std_logic;
- q : out std_logic
- );
- end component;
+architecture rtl of irc_reader is
begin
- dff_index: dff
+ dff_mark: dff2
port map
(
clk => clk,
- reset => reset,
- d => index0,
- q => out_index
- );
-
- dff_mark: dff
- port map
- (
- clk => clk,
- reset => reset,
+ reset => '0',
d => mark0,
q => out_mark
);
reset => reset,
a0 => a0,
b0 => b0,
+ index0 => index0,
qcount => qcount,
+ qcount_index => qcount_index,
ab_event => ab_event,
ab_error => ab_error,
a_rise => open,
b_fall => open
);
-end Behavioral;
-
+end rtl;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;
use ieee.numeric_std.all;
+use work.lx_rocon_pkg.all;
-- IRC register: connects IRC output to memory bus
index0 : in std_logic;
mark0 : in std_logic;
- -- Data bus
+ -- Data bus for Master CPU
data_in : in std_logic; -- 1 bit input
data_out : out std_logic_vector(31 downto 0);
signal qcount_error : std_logic;
signal qcount : std_logic_vector (31 downto 0);
signal qcount_index : std_logic_vector (31 downto 0);
- signal qcount_index_prev : std_logic_vector (31 downto 0);
signal ab_event : std_logic;
signal ab_error : std_logic;
- signal old_index : std_logic;
- signal out_index : std_logic;
signal out_mark : std_logic;
component irc_reader
port
(
- clk : in std_logic;
- reset : in std_logic;
- a0, b0 : in std_logic;
- index0 : in std_logic;
- mark0 : in std_logic;
-
- qcount : out std_logic_vector (31 downto 0);
- ab_event : out std_logic;
- ab_error : out std_logic;
- out_index : out std_logic;
- out_mark : out std_logic
+ clk : in std_logic;
+ reset : in std_logic;
+ a0, b0 : in std_logic;
+ index0 : in std_logic;
+ mark0 : in std_logic;
+
+ qcount : out std_logic_vector (31 downto 0);
+ qcount_index : out std_logic_vector (31 downto 0);
+ ab_event : out std_logic;
+ ab_error : out std_logic;
+ out_mark : out std_logic
);
end component;
index0 => index0,
mark0 => mark0,
qcount => qcount,
+ qcount_index => qcount_index,
ab_event => ab_event,
ab_error => ab_error,
- out_index => out_index,
out_mark => out_mark
);
else
qcount_error <= qcount_error or ab_error;
end if;
-
- old_index <= out_index;
- qcount_index_prev <= qcount_index;
end if;
end process;
- signals: process(reset, old_index, out_index, qcount, qcount_index_prev)
- begin
-
- if reset = '0' and old_index = '0' and out_index = '1' then
- qcount_index <= qcount;
- elsif reset = '1' then
- qcount_index <= (others => '0');
- else
- qcount_index <= qcount_index_prev;
- end if;
-
- end process;
memory_bus: process(ce, rd, qcount, qcount_index, qcount_error, ab_event, ab_error, out_mark)
begin
-- Reset signals
- ta <= '1';
+ ta <= rd;
data_out <= (others => 'X');
-- Check chip enable
case ce is
when "00" =>
- if rd = '0' then
- data_out <= qcount;
- ta <= '0';
- end if;
+ data_out <= qcount;
when "01" =>
- if rd = '0' then
- data_out <= qcount_index;
- ta <= '0';
- end if;
+ data_out <= qcount_index;
when "10" =>
- if rd = '0' then
- data_out(0) <= ab_event;
- data_out(1) <= ab_error;
- data_out(2) <= qcount_error;
- data_out(3) <= out_mark;
- data_out(31 downto 4) <= (others => '0');
- ta <= '0';
- end if;
-
- when others =>
- data_out <= (others => 'X');
+ data_out(0) <= ab_event;
+ data_out(1) <= ab_error;
+ data_out(2) <= qcount_error;
+ data_out(3) <= out_mark;
+ data_out(31 downto 4) <= (others => '0');
+
+ when others => NULL;
end case;
# ====================================================================
# Clock
-NET CLK_CPU PERIOD = 13.8ns HIGH 50%;
-NET CLK_CPU LOC = P15 | IOSTANDARD = LVCMOS33;
-#NET CLK_50M PERIOD = 20.0ns HIGH 50%;
-#NET CLK_50M LOC = P14 | IOSTANDARD = LVCMOS33;
+#NET CLK_CPU PERIOD = 13.8ns HIGH 50%;
+#NET CLK_CPU LOC = P15 | IOSTANDARD = LVCMOS33;
+NET CLK_50M PERIOD = 20.0ns HIGH 50%;
+NET CLK_50M LOC = P14 | IOSTANDARD = LVCMOS33;
# Reset (active LOW)
NET INIT LOC = P39 | IOSTANDARD = LVCMOS33;
--- /dev/null
+/* Firmware file for lx-rocon tumbl coprocessor */
+
+#include <stdint.h>
+
+typedef struct
+{
+ int16_t p;
+ int16_t i;
+ int32_t irc_period;
+ int16_t req_current;
+ int16_t acc_dev;
+ int16_t max_acc;
+} axis_settings;
+
+typedef struct
+{
+ /* Input */
+ int16_t current;
+ int32_t irc;
+ int32_t irc_last;
+ int32_t irc_norm;
+
+ /* Output */
+ uint16_t pwm[3];
+} axis_io;
+
+axis_settings a_settings;
+
+axis_io a_io;
+int32_t irc_a_reg;
+int16_t current_a_reg;
+uint32_t count;
+int16_t phase_table[1][1];
+
+void init_defvals()
+{
+ a_settings.p = 20;
+ a_settings.i = 2;
+ a_settings.irc_period = 7000;
+ a_settings.req_current = 500;
+ a_settings.acc_dev = 0;
+}
+
+void update_axis(axis_settings *settings, axis_io* io)
+{
+ int i;
+ int16_t dev;
+ int32_t mag, irc_diff;
+
+ dev = settings->req_current - io->current;
+ settings->acc_dev += dev;
+
+ if (settings->acc_dev > settings->max_acc)
+ settings->acc_dev = settings->max_acc;
+ else if (-(settings->acc_dev) <= -(settings->max_acc))
+ settings->acc_dev = -(settings->max_acc);
+
+ mag = settings->acc_dev * settings->i + dev * settings->p;
+
+ irc_diff = io->irc - io->irc_last;
+ io->irc_last = io->irc;
+ io->irc_norm += irc_diff;
+
+ if (io->irc_norm > settings->irc_period)
+ io->irc_norm -= settings->irc_period;
+ else if (io->irc_norm < 0)
+ io->irc_norm += settings->irc_period;
+
+ for (i = 0; i < 3; i++)
+ io->pwm[i] = (uint16_t)((mag * phase_table[/*i*/ 0][/*irc_norm*/ 0]) >> 16);
+}
+
+void main()
+{
+ while (1)
+ {
+ update_axis(&a_settings, &a_io);
+ a_io.irc = irc_a_reg;
+ a_io.current = current_a_reg;
+ count++;
+ }
+}
+
--- /dev/null
+/* LX ROCON firmware startup file */
+
+.globl _main
+.align 2
+
+_main:
+
+ /* Stack pointer */
+ addi r1, r0, 0xFFC
+
+ /* Other register values are not initialized to 0 */
+ addi r2, r0, 0
+ addi r3, r0, 0
+ addi r4, r0, 0
+ addi r5, r0, 0
+ addi r6, r0, 0
+ addi r7, r0, 0
+ addi r8, r0, 0
+ addi r9, r0, 0
+ addi r10, r0, 0
+ addi r11, r0, 0
+ addi r12, r0, 0
+ addi r13, r0, 0
+ addi r14, r0, 0
+ addi r15, r0, 0
+ addi r16, r0, 0
+ addi r17, r0, 0
+ addi r18, r0, 0
+ addi r19, r0, 0
+ addi r20, r0, 0
+ addi r21, r0, 0
+ addi r22, r0, 0
+ addi r23, r0, 0
+ addi r24, r0, 0
+ addi r25, r0, 0
+ addi r26, r0, 0
+ addi r27, r0, 0
+ addi r28, r0, 0
+ addi r29, r0, 0
+ addi r30, r0, 0
+ addi r31, r0, 0
+
+ /* reset data */
+ addi r6, r0, _sdata
+ addi r7, r0, _edata
+ rsub r18, r6, r7
+ blei r18, .Lenddata
+.Lloopdata:
+ swi r0, r6, 0
+ addi r6, r6, 4
+ rsub r18, r6, r7
+ bgti r18, .Lloopdata
+ or r0, r0, r0
+.Lenddata:
+ /* Init default values */
+ brlid r15, init_defvals
+ addi r31, r0, 20
+ or r0, r0, r0
+
+ /* Run program */
+ brlid r15, main
+ or r0, r0, r0
+
+ /* End of program */
+ bri 0x00
+ or r0, r0, r0
--- /dev/null
+../../submodule/tumbl/utils
\ No newline at end of file
--- /dev/null
+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;
+use work.mbl_Pkg.all;
+use work.lx_rocon_pkg.all;
+
+-- 4 kB data memory for Thumbl core
+-- To be flashed from the Master CPU
+
+entity lx_rocon_dmem is
+ port
+ (
+ -- Memory wiring for Tumbl
+ clk_i : in std_logic;
+ ce_i : in std_logic;
+ adr_i : in std_logic_vector(11 downto 2);
+ wre_i : in std_logic;
+ bsel_i : in std_logic_vector(3 downto 0);
+ dat_i : in std_logic_vector(31 downto 0);
+ dat_o : out std_logic_vector(31 downto 0);
+
+ -- Memory wiring for Master CPU
+ clk_m : in std_logic;
+ en_m : in std_logic;
+ we_m : in std_logic_vector(3 downto 0);
+ addr_m : in std_logic_vector(9 downto 0);
+ din_m : in std_logic_vector(31 downto 0);
+ dout_m : out std_logic_vector(31 downto 0)
+
+ );
+end lx_rocon_dmem;
+
+architecture rtl of lx_rocon_dmem is
+
+ signal wre_i_s : std_logic_vector(3 downto 0);
+
+begin
+
+ wre_i_s <= bsel_i when (wre_i = '1') else "0000";
+
+ I_RAMB: xilinx_dualport_bram
+ generic map
+ (
+ we_width => 4,
+ byte_width => 8,
+ address_width => 10
+ )
+ port map
+ (
+ -- Tumblr port
+ clka => clk_i,
+ rsta => '0',
+ ena => ce_i,
+ wea => wre_i_s,
+ addra => adr_i(11 downto 2),
+ dina => dat_i,
+ douta => dat_o,
+
+ -- Master CPU port
+ clkb => clk_m,
+ rstb => '0',
+ enb => en_m,
+ web => we_m,
+ addrb => addr_m,
+ dinb => din_m,
+ doutb => dout_m
+ );
+
+end rtl;
--- /dev/null
+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;
+use work.mbl_Pkg.all;
+use work.lx_rocon_pkg.all;
+
+-- 32x32b General Puprose Registers for Tumbl Core
+-- Uses 3 BRAMs
+
+entity lx_rocon_gprf_abd is
+ port
+ (
+ clk_i : in std_logic;
+ rst_i : in std_logic;
+ clken_i : in std_logic;
+
+ ID2GPRF_i : in ID2GPRF_Type;
+ MEM_WRB_i : in WRB_Type;
+ GPRF2EX_o : out GPRF2EX_Type
+ );
+end entity lx_rocon_gprf_abd;
+
+architecture rtl of lx_rocon_gprf_abd is
+
+ signal rdix_rA_s : std_logic_vector(4 downto 0);
+ signal rdix_rB_s : std_logic_vector(4 downto 0);
+ signal rdix_rD_s : std_logic_vector(4 downto 0);
+
+ signal wre_rD_s : std_logic;
+ signal ena_rA_s : std_logic;
+ signal ena_rB_s : std_logic;
+ signal ena_rD_s : std_logic;
+
+ signal clken_s : std_logic;
+
+ signal wthru_rA_r : std_logic;
+ signal rA_DOA_s : std_logic_vector(31 downto 0);
+ signal rA_DOB_s : std_logic_vector(31 downto 0);
+ signal wthru_rB_r : std_logic;
+ signal rB_DOA_s : std_logic_vector(31 downto 0);
+ signal rB_DOB_s : std_logic_vector(31 downto 0);
+ signal wthru_rD_r : std_logic;
+ signal rD_DOA_s : std_logic_vector(31 downto 0);
+ signal rD_DOB_s : std_logic_vector(31 downto 0);
+
+begin
+
+ -- writeback if WRB_EX or WRB_MEM, but not when r0 involved
+ wre_rD_s <= '1' when ((MEM_WRB_i.wrb_Action /= NO_WRB) and
+ (MEM_WRB_i.wrix_rD /= "00000")) else '0';
+
+ -- ports A should remain unchanged when clken_i is low, while also
+ -- reading from the same address as will be written to should be disabled
+ -- (setup for writeThru of data_rD)
+ ena_rA_s <= '1' when rst_i = '1' else clken_i when ((ID2GPRF_i.rdix_rA /= MEM_WRB_i.wrix_rD)) else '0';
+ ena_rB_s <= '1' when rst_i = '1' else clken_i when ((ID2GPRF_i.rdix_rB /= MEM_WRB_i.wrix_rD)) else '0';
+ ena_rD_s <= '1' when rst_i = '1' else clken_i when ((ID2GPRF_i.rdix_rD /= MEM_WRB_i.wrix_rD)) else '0';
+
+ -- make sure reset does it's job (writes 0 to R0 and resets the ports)
+ clken_s <= rst_i or clken_i;
+ rdix_rA_s <= (others => '0') when rst_i = '1' else ID2GPRF_i.rdix_rA;
+ rdix_rB_s <= (others => '0') when rst_i = '1' else ID2GPRF_i.rdix_rB;
+ rdix_rD_s <= (others => '0') when rst_i = '1' else ID2GPRF_i.rdix_rD;
+
+ GPRF2EX_o.data_rA <= rA_DOA_s when (wthru_rA_r = '0') else rA_DOB_s;
+ GPRF2EX_o.data_rB <= rB_DOA_s when (wthru_rB_r = '0') else rB_DOB_s;
+ GPRF2EX_o.data_rD <= rD_DOA_s when (wthru_rD_r = '0') else rD_DOB_s; -- also for rD ???
+
+ I_rA: xilinx_dualport_bram
+ generic map
+ (
+ byte_width => 32,
+ we_width => 1,
+ address_width => 5
+ )
+ port map
+ (
+ clka => clk_i,
+ rsta => rst_i,
+ ena => ena_rA_s,
+ wea(0) => rst_i,
+ addra => rdix_rA_s,
+ dina => C_32_ZEROS,
+ douta => rA_DOA_s,
+ -- Write-back
+ clkb => clk_i,
+ rstb => rst_i,
+ enb => clken_s,
+ web(0) => wre_rD_s,
+ addrb => MEM_WRB_i.wrix_rD,
+ dinb => MEM_WRB_i.data_rD,
+ doutb => rA_DOB_s
+ );
+
+ I_rB: xilinx_dualport_bram
+ generic map
+ (
+ byte_width => 32,
+ we_width => 1,
+ address_width => 5
+ )
+ port map
+ (
+ clka => clk_i,
+ rsta => rst_i,
+ ena => ena_rB_s,
+ wea(0) => rst_i,
+ addra => rdix_rB_s,
+ dina => C_32_ZEROS,
+ douta => rB_DOA_s,
+ -- Write-back
+ clkb => clk_i,
+ rstb => rst_i,
+ enb => clken_s,
+ web(0) => wre_rD_s,
+ addrb => MEM_WRB_i.wrix_rD,
+ dinb => MEM_WRB_i.data_rD,
+ doutb => rB_DOB_s
+ );
+
+ I_rD: xilinx_dualport_bram
+ generic map
+ (
+ byte_width => 32,
+ we_width => 1,
+ address_width => 5
+ )
+ port map
+ (
+ clka => clk_i,
+ rsta => rst_i,
+ ena => ena_rD_s,
+ wea(0) => rst_i,
+ addra => rdix_rD_s,
+ dina => C_32_ZEROS,
+ douta => rD_DOA_s,
+ -- Write-back
+ clkb => clk_i,
+ rstb => rst_i,
+ enb => clken_s,
+ web(0) => wre_rD_s,
+ addrb => MEM_WRB_i.wrix_rD,
+ dinb => MEM_WRB_i.data_rD,
+ doutb => rD_DOB_s
+ );
+
+ p_regd: process(clk_i)
+ begin
+ if clk_i = '1' and clk_i'event then
+ if (clken_i = '1') then
+ wthru_rA_r <= not ena_rA_s;
+ wthru_rB_r <= not ena_rB_s;
+ wthru_rD_r <= not ena_rD_s;
+ end if;
+ end if;
+ end process;
+
+end architecture rtl;
--- /dev/null
+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;
+use work.mbl_Pkg.all;
+use work.lx_rocon_pkg.all;
+
+-- 2 kB instruction memory for Thumbl core
+-- To be flashed from the Master CPU
+
+entity lx_rocon_imem is
+ port
+ (
+ -- Memory wiring for Tumbl
+ clk_i : in std_logic;
+ cs_i : in std_logic;
+ adr_i : in std_logic_vector(10 downto 2);
+ dat_o : out std_logic_vector(31 downto 0);
+
+ -- Memory wiring for Master CPU
+ clk_m : in std_logic;
+ en_m : in std_logic;
+ we_m : in std_logic_vector(3 downto 0);
+ addr_m : in std_logic_vector(8 downto 0);
+ din_m : in std_logic_vector(31 downto 0);
+ dout_m : out std_logic_vector(31 downto 0)
+
+ );
+end lx_rocon_imem;
+
+architecture rtl of lx_rocon_imem is
+begin
+
+ I_RAMB: xilinx_dualport_bram
+ generic map
+ (
+ we_width => 4,
+ byte_width => 8,
+ address_width => 9
+ )
+ port map
+ (
+ -- Tumblr port
+ clka => clk_i,
+ rsta => '0',
+ ena => cs_i,
+ wea => "0000",
+ addra => adr_i(10 downto 2),
+ dina => C_32_ZEROS,
+ douta => dat_o,
+
+ -- Master CPU port
+ clkb => clk_m,
+ rstb => '0',
+ enb => en_m,
+ web => we_m,
+ addrb => addr_m,
+ dinb => din_m,
+ doutb => dout_m
+ );
+
+end rtl;
--- /dev/null
+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;
+use work.mbl_Pkg.all;
+use work.lx_rocon_pkg.all;
+
+-- Tumbl configured as a coprocessor for lx_rocon
+-- Uses 10 bits width address bus with HW barrel and multiplier
+
+entity lx_rocon_tumbl is
+ generic
+ (
+ IMEM_ABITS_g : positive := 11;
+ DMEM_ABITS_g : positive := 12;
+ --
+ USE_HW_MUL_g : boolean := true;
+ USE_BARREL_g : boolean := true
+ );
+ port
+ (
+ clk_i : in std_logic;
+ rst_i : in std_logic;
+ halt_i : in std_logic;
+ int_i : in std_logic;
+ trace_i : in std_logic;
+ trace_kick_i : in std_logic;
+
+ -- Program counter
+ pc_o : out std_logic_vector(31 downto 0);
+
+ -- Internal memory (instruction)
+ imem_clk : in std_logic;
+ imem_en : in std_logic;
+ imem_we : in std_logic_vector(3 downto 0);
+ imem_addr : in std_logic_vector(8 downto 0);
+ imem_din : in std_logic_vector(31 downto 0);
+ imem_dout : out std_logic_vector(31 downto 0);
+
+ -- Internal memory (data)
+ dmem_clk : in std_logic;
+ dmem_en : in std_logic;
+ dmem_we : in std_logic_vector(3 downto 0);
+ dmem_addr : in std_logic_vector(9 downto 0);
+ dmem_din : in std_logic_vector(31 downto 0);
+ dmem_dout : out std_logic_vector(31 downto 0);
+
+ -- External memory bus
+ XMEMB_sel_o : out std_logic;
+ XMEMB_i : in DMEMB2CORE_Type;
+ XMEMB_o : out CORE2DMEMB_Type;
+ --
+ bad_op_o : out std_logic;
+ done_o : out std_logic
+ );
+end entity lx_rocon_tumbl;
+
+architecture rtl of lx_rocon_tumbl is
+
+ constant DMEM_TEST_c : std_logic_vector((31-DMEM_ABITS_g) downto 0) := (others => '0');
+
+ signal imem_clken_s : std_logic;
+ signal imem_addr_s : std_logic_vector(31 downto 0);
+ signal imem_data_s : std_logic_vector(31 downto 0);
+ signal gprf_clken_s : std_logic;
+ signal core_clk_en_s : std_logic;
+ signal pc_ctrl_s : std_logic;
+ signal c2dmemb_s : CORE2DMEMB_Type;
+ signal dmem_data_s : std_logic_vector(31 downto 0);
+ signal DMEMB_i_s : DMEMB2CORE_Type;
+
+ signal MEM2CTRL_s : MEM2CTRL_Type;
+ signal INT_CTRL_s : INT_CTRL_Type;
+ signal ID2CTRL_s : ID2CTRL_Type;
+
+ signal IF2ID_s, IF2ID_r : IF2ID_Type;
+ signal ID2EX_s, ID2EX_r : ID2EX_Type;
+ signal ID2GPRF_s : ID2GPRF_Type;
+ signal GPRF2EX_s : GPRF2EX_Type;
+ signal EX2IF_s, EX2IF_r : EX2IF_Type;
+ signal EX2MEM_s, EX2MEM_r : EX2MEM_Type;
+ signal EX_WRB_s, EX_WRB_r : WRB_Type;
+ signal MEM_WRB_s : WRB_Type;
+ signal IMM_LOCK_s, IMM_LOCK_r : IMM_LOCK_Type;
+ signal HAZARD_WRB_s, HAZARD_WRB_r : HAZARD_WRB_Type;
+ signal EX2MSR_s : MSR_Type;
+ signal MSR2EX_s : MSR_Type;
+ signal MEM_REG_s, MEM_REG_r : MEM_REG_Type;
+ signal dmem_sel_s, dmem_sel_r : std_logic;
+ signal BAD_OP_s : std_logic;
+ signal BAD_OP_up_s : std_logic;
+ signal halt_s : std_logic;
+
+ signal imem_really_clken_s : std_logic;
+ signal dmem_really_sel_s : std_logic;
+ signal gprf_really_clken_s : std_logic;
+
+begin
+
+ -- select internal data memory when all address bits above DMEM_ABITS_g are zero
+ dmem_sel_s <= '1' when (c2dmemb_s.addr(31 downto DMEM_ABITS_g) = DMEM_TEST_c)
+ else '0';
+ XMEMB_sel_o <= not dmem_sel_s;
+ XMEMB_o <= c2dmemb_s;
+ pc_o <= ID2EX_r.program_counter; -- Program counter for EXEQ
+ bad_op_o <= BAD_OP_s;
+ halt_s <= halt_i or BAD_OP_up_s;
+
+ imem_really_clken_s <= imem_clken_s and core_clk_en_s;
+ dmem_really_sel_s <= dmem_sel_s and core_clk_en_s;
+ gprf_really_clken_s <= gprf_clken_s and core_clk_en_s;
+
+ I_IMEM: lx_rocon_imem
+ port map
+ (
+ clk_i => clk_i,
+ cs_i => imem_really_clken_s,
+ adr_i => imem_addr_s((IMEM_ABITS_g-1) downto 2),
+ dat_o => imem_data_s,
+
+ clk_m => imem_clk,
+ en_m => imem_en,
+ we_m => imem_we,
+ addr_m => imem_addr,
+ din_m => imem_din,
+ dout_m => imem_dout
+ );
+
+ I_DMEM: lx_rocon_dmem
+ port map
+ (
+ clk_i => clk_i,
+ ce_i => dmem_really_sel_s,
+ adr_i => c2dmemb_s.addr((DMEM_ABITS_g-1) downto 2),
+ wre_i => c2dmemb_s.wre,
+ bsel_i => c2dmemb_s.bSel,
+ dat_i => c2dmemb_s.data,
+ dat_o => dmem_data_s,
+
+ clk_m => dmem_clk,
+ en_m => dmem_en,
+ we_m => dmem_we,
+ addr_m => dmem_addr,
+ din_m => dmem_din,
+ dout_m => dmem_dout
+ );
+
+ I_FETCH: fetch
+ port map
+ (
+ prog_cntr_i => IF2ID_r.program_counter,
+ inc_pc_i => pc_ctrl_s,
+ EX2IF_i => EX2IF_r,
+ IF2ID_o => IF2ID_s
+ );
+
+ I_DECODE: decode
+ generic map(USE_HW_MUL_g, USE_BARREL_g)
+ port map
+ (
+ IF2ID_i => IF2ID_r,
+ imem_data_i => imem_data_s,
+ --
+ ID2GPRF_o => ID2GPRF_s,
+ ID2EX_o => ID2EX_s,
+ --
+ INT_CTRL_i => INT_CTRL_s,
+ ID2CTRL_o => ID2CTRL_s,
+ --
+ noLiteOpc_o => BAD_OP_s
+ );
+
+ I_GPRF: lx_rocon_gprf_abd
+ port map
+ (
+ clk_i => clk_i,
+ rst_i => rst_i,
+ clken_i => gprf_really_clken_s,
+ --
+ ID2GPRF_i => ID2GPRF_s,
+ MEM_WRB_i => MEM_WRB_s,
+ GPRF2EX_o => GPRF2EX_s
+ );
+
+ I_EXEQ: exeq
+ generic map(USE_HW_MUL_g, USE_BARREL_g)
+ port map
+ (
+ ID2EX_i => ID2EX_r,
+ GPRF2EX_i => GPRF2EX_s,
+ EX2IF_o => EX2IF_s,
+ --
+ EX_WRB_i => EX_WRB_r,
+ EX_WRB_o => EX_WRB_s,
+ MEM_WRB_i => MEM_WRB_s,
+ --
+ HAZARD_WRB_i => HAZARD_WRB_r,
+ HAZARD_WRB_o => HAZARD_WRB_s,
+ --
+ IMM_LOCK_i => IMM_LOCK_r,
+ IMM_LOCK_o => IMM_LOCK_s,
+ --
+ MSR_i => MSR2EX_s,
+ MSR_o => EX2MSR_s,
+ --
+ EX2MEM_o => EX2MEM_s
+ );
+
+ -- this is a very simple address block decoder, just "internal" dmem or "external"
+ -- clken and int hardwired for fast internal data-memory
+ DMEMB_i_s.clken <= '1' when (dmem_sel_s = '1') else XMEMB_i.clken;
+ DMEMB_i_s.data <= dmem_data_s when (dmem_sel_r = '1') else XMEMB_i.data;
+ DMEMB_i_s.int <= XMEMB_i.int;
+
+ I_MEM: mem
+ port map
+ (
+ EX2MEM_i => EX2MEM_r,
+ MEM_WRB_o => MEM_WRB_s,
+ --
+ DMEMB_i => DMEMB_i_s,
+ DMEMB_o => c2dmemb_s,
+ --
+ MEM_REG_i => MEM_REG_r,
+ MEM_REG_o => MEM_REG_s,
+ --
+ MEM2CTRL_o => MEM2CTRL_s
+ );
+
+ I_CTRL: core_ctrl
+ port map
+ (
+ clk_i => clk_i,
+ rst_i => rst_i,
+ halt_i => halt_s,
+ int_i => int_i,
+ trace_i => trace_i,
+ trace_kick_i => trace_kick_i,
+ core_clk_en_o => core_clk_en_s,
+ -- specific fetch i/o
+ imem_addr_o => imem_addr_s,
+ imem_clken_o => imem_clken_s,
+ pc_ctrl_o => pc_ctrl_s,
+ -- fetch to decode pipeline registers
+ IF2ID_REG_i => IF2ID_s,
+ IF2ID_REG_o => IF2ID_r,
+ -- decode to exeq pipeline registers
+ ID2EX_REG_i => ID2EX_s,
+ ID2EX_REG_o => ID2EX_r,
+ -- GPRF control
+ gprf_clken_o => gprf_clken_s,
+ -- exeq to fetch feedback registers
+ EX2IF_REG_i => EX2IF_s,
+ EX2IF_REG_o => EX2IF_r,
+ -- exeq to mem pipeline registers
+ EX2MEM_REG_i => EX2MEM_s,
+ EX2MEM_REG_o => EX2MEM_r,
+ -- mem pipeline register
+ MEM_REG_i => MEM_REG_s,
+ MEM_REG_o => MEM_REG_r,
+ -- decode control i/o
+ ID2CTRL_i => ID2CTRL_s,
+ INT_CTRL_o => INT_CTRL_s,
+ -- exeq control i/o
+ EX_WRB_i => EX_WRB_s,
+ EX_WRB_o => EX_WRB_r,
+ -- data hazard i/o
+ HAZARD_WRB_i => HAZARD_WRB_s,
+ HAZARD_WRB_o => HAZARD_WRB_r,
+ -- for handling the 'IMM' instruction
+ IMM_LOCK_i => IMM_LOCK_s,
+ IMM_LOCK_o => IMM_LOCK_r,
+ -- for handling the Machine Status Register
+ MSR_i => EX2MSR_s,
+ MSR_o => MSR2EX_s,
+ -- miscellaneous
+ MEM2CTRL_i => MEM2CTRL_s,
+ done_o => done_o
+ );
+
+ regd_proc: process(clk_i, rst_i)
+ begin
+ if clk_i = '1' and clk_i'event then
+ if (rst_i = '1') then -- synchronous reset ...
+ dmem_sel_r <= '1';
+ BAD_OP_up_s <= '0';
+ else -- delay select_external_mem (needed for reading ...)
+ if (DMEMB_i_s.clken = '1') then
+ dmem_sel_r <= dmem_sel_s; -- OR c2dmemb_s.wre; ??
+ end if;
+ BAD_OP_up_s <= BAD_OP_up_s or BAD_OP_s;
+ end if;
+ end if;
+ end process regd_proc;
+
+end architecture rtl;
--- /dev/null
+LIBRARY ieee;
+USE ieee.std_logic_1164.ALL;
+USE ieee.numeric_std.ALL;
+USE work.mbl_Pkg.ALL;
+USE work.lx_rocon_pkg.ALL;
+
+-- Tumbl core testbench
+
+ENTITY lx_rocon_tumbl_tb IS
+END lx_rocon_tumbl_tb;
+
+ARCHITECTURE behavior OF lx_rocon_tumbl_tb IS
+
+ -- Component Declaration for the Unit Under Test (UUT)
+
+ COMPONENT lx_rocon_tumbl
+ PORT(
+ clk_i : IN std_logic;
+ rst_i : IN std_logic;
+ halt_i : IN std_logic;
+ int_i : IN std_logic;
+ trace_i : IN std_logic;
+ trace_kick_i : IN std_logic;
+ pc_o : OUT std_logic_vector(31 downto 0);
+ imem_clk : IN std_logic;
+ imem_en : IN std_logic;
+ imem_we : IN std_logic_vector(3 downto 0);
+ imem_addr : IN std_logic_vector(8 downto 0);
+ imem_din : IN std_logic_vector(31 downto 0);
+ imem_dout : OUT std_logic_vector(31 downto 0);
+ dmem_clk : IN std_logic;
+ dmem_en : IN std_logic;
+ dmem_we : IN std_logic_vector(3 downto 0);
+ dmem_addr : IN std_logic_vector(9 downto 0);
+ dmem_din : IN std_logic_vector(31 downto 0);
+ dmem_dout : OUT std_logic_vector(31 downto 0);
+ XMEMB_sel_o : OUT std_logic;
+ XMEMB_i : IN DMEMB2CORE_Type;
+ XMEMB_o : OUT CORE2DMEMB_Type;
+ bad_op_o : OUT std_logic;
+ done_o : OUT std_logic
+ );
+ END COMPONENT;
+
+
+ --Inputs
+ signal clk_i : std_logic := '0';
+ signal rst_i : std_logic := '0';
+ signal halt_i : std_logic := '0';
+ signal int_i : std_logic := '0';
+ signal trace_i : std_logic := '0';
+ signal trace_kick_i : std_logic := '0';
+ signal imem_clk : std_logic := '0';
+ signal imem_en : std_logic := '0';
+ signal imem_we : std_logic_vector(3 downto 0) := (others => '0');
+ signal imem_addr : std_logic_vector(8 downto 0) := (others => '0');
+ signal imem_din : std_logic_vector(31 downto 0) := (others => '0');
+ signal dmem_clk : std_logic := '0';
+ signal dmem_en : std_logic := '0';
+ signal dmem_we : std_logic_vector(3 downto 0) := (others => '0');
+ signal dmem_addr : std_logic_vector(9 downto 0) := (others => '0');
+ signal dmem_din : std_logic_vector(31 downto 0) := (others => '0');
+ signal XMEMB_i : DMEMB2CORE_Type := (clken => '0', data => (others => '0'), int => '0');
+
+ --Outputs
+ signal pc_o : std_logic_vector(31 downto 0);
+ signal imem_dout : std_logic_vector(31 downto 0);
+ signal dmem_dout : std_logic_vector(31 downto 0);
+ signal XMEMB_sel_o : std_logic;
+ signal XMEMB_o : CORE2DMEMB_Type;
+ signal bad_op_o : std_logic;
+ signal done_o : std_logic;
+
+ -- Clock period definitions
+ constant clk_i_period : time := 20 ns; -- 50 MHz
+ constant imem_clk_period : time := 13.8 ns; -- 72 MHz
+ constant dmem_clk_period : time := 13.8 ns; -- 72 MHz
+
+BEGIN
+
+ -- Instantiate the Unit Under Test (UUT)
+ uut: lx_rocon_tumbl PORT MAP (
+ clk_i => clk_i,
+ rst_i => rst_i,
+ halt_i => halt_i,
+ int_i => int_i,
+ trace_i => trace_i,
+ trace_kick_i => trace_kick_i,
+ pc_o => pc_o,
+ imem_clk => imem_clk,
+ imem_en => imem_en,
+ imem_we => imem_we,
+ imem_addr => imem_addr,
+ imem_din => imem_din,
+ imem_dout => imem_dout,
+ dmem_clk => dmem_clk,
+ dmem_en => dmem_en,
+ dmem_we => dmem_we,
+ dmem_addr => dmem_addr,
+ dmem_din => dmem_din,
+ dmem_dout => dmem_dout,
+ XMEMB_sel_o => XMEMB_sel_o,
+ XMEMB_i => XMEMB_i,
+ XMEMB_o => XMEMB_o,
+ bad_op_o => bad_op_o,
+ done_o => done_o
+ );
+
+ -- Clock process definitions
+ clk_i_process :process
+ begin
+ clk_i <= '0';
+ wait for clk_i_period/2;
+ clk_i <= '1';
+ wait for clk_i_period/2;
+ end process;
+
+ imem_clk_process :process
+ begin
+ imem_clk <= '0';
+ wait for imem_clk_period/2;
+ imem_clk <= '1';
+ wait for imem_clk_period/2;
+ end process;
+
+ dmem_clk_process :process
+ begin
+ dmem_clk <= '0';
+ wait for dmem_clk_period/2;
+ dmem_clk <= '1';
+ wait for dmem_clk_period/2;
+ end process;
+
+
+ -- Stimulus process
+ stim_proc: process
+ begin
+ -- External ModelSim script
+
+ wait;
+ end process;
+
+END;
--- /dev/null
+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;
+use work.mbl_Pkg.all;
+
+-- Entities within lx_rocon
+
+package lx_rocon_pkg is
+
+ -- IRC register
+ component irc_register
+ port
+ (
+ clk : in std_logic;
+ reset : in std_logic;
+ a0, b0 : in std_logic;
+ index0 : in std_logic;
+ mark0 : in std_logic;
+ data_in : in std_logic;
+ data_out : out std_logic_vector(31 downto 0);
+ ce : in std_logic_vector(1 downto 0);
+ rd : in std_logic;
+ ta : out std_logic;
+ wr : in std_logic
+ );
+ end component;
+
+ -- BCD counter
+ component bcd
+ generic
+ (
+ width : integer
+ );
+ port
+ (
+ reset : in std_logic;
+ en : in std_logic;
+ clk : in std_logic;
+ value : out std_logic_vector((width-1) downto 0)
+ );
+ end component;
+
+ -- Quadcount
+ component qcounter
+ port
+ (
+ clk : in std_logic;
+ reset : in std_logic;
+ a0, b0 : in std_logic;
+ index0 : in std_logic;
+
+ a_rise : out std_logic;
+ a_fall : out std_logic;
+ b_rise : out std_logic;
+ b_fall : out std_logic;
+
+ qcount : out std_logic_vector (31 downto 0);
+ qcount_index : out std_logic_vector (31 downto 0);
+ ab_event : out std_logic;
+ ab_error : out std_logic
+ );
+ end component;
+
+ -- D sampler
+ component dff
+ port
+ (
+ clk : in std_logic;
+ reset : in std_logic;
+ d : in std_logic;
+ q : out std_logic
+ );
+ end component;
+
+ -- D sampler (filtered)
+ component dff2
+ port
+ (
+ clk : in std_logic;
+ reset : in std_logic;
+ d : in std_logic;
+ q : out std_logic
+ );
+ end component;
+
+ --------------------------------------------------------------------------------
+ -- TUMBL
+ --------------------------------------------------------------------------------
+
+ component lx_rocon_tumbl
+ generic
+ (
+ IMEM_ABITS_g : positive := 12;
+ DMEM_ABITS_g : positive := 12;
+ --
+ USE_HW_MUL_g : boolean := true;
+ USE_BARREL_g : boolean := true
+ );
+ port
+ (
+ clk_i : in std_logic;
+ rst_i : in std_logic;
+ halt_i : in std_logic;
+ int_i : in std_logic;
+ trace_i : in std_logic;
+ trace_kick_i : in std_logic;
+ pc_o : out std_logic_vector(31 downto 0);
+ imem_clk : in std_logic;
+ imem_en : in std_logic;
+ imem_we : in std_logic_vector(3 downto 0);
+ imem_addr : in std_logic_vector(8 downto 0);
+ imem_din : in std_logic_vector(31 downto 0);
+ imem_dout : out std_logic_vector(31 downto 0);
+ dmem_clk : in std_logic;
+ dmem_en : in std_logic;
+ dmem_we : in std_logic_vector(3 downto 0);
+ dmem_addr : in std_logic_vector(9 downto 0);
+ dmem_din : in std_logic_vector(31 downto 0);
+ dmem_dout : out std_logic_vector(31 downto 0);
+ XMEMB_sel_o : out std_logic;
+ XMEMB_i : in DMEMB2CORE_Type;
+ XMEMB_o : out CORE2DMEMB_Type;
+ bad_op_o : out std_logic;
+ done_o : out std_logic
+ );
+ end component;
+
+ component lx_rocon_imem
+ port
+ (
+ clk_i : in std_logic;
+ cs_i : in std_logic;
+ adr_i : in std_logic_vector(10 downto 2);
+ dat_o : out std_logic_vector(31 downto 0);
+ clk_m : in std_logic;
+ en_m : in std_logic;
+ we_m : in std_logic_vector(3 downto 0);
+ addr_m : in std_logic_vector(8 downto 0);
+ din_m : in std_logic_vector(31 downto 0);
+ dout_m : out std_logic_vector(31 downto 0)
+
+ );
+ end component;
+
+ component lx_rocon_dmem
+ port
+ (
+ clk_i : in std_logic;
+ ce_i : in std_logic;
+ adr_i : in std_logic_vector(11 downto 2);
+ wre_i : in std_logic;
+ bsel_i : in std_logic_vector(3 downto 0);
+ dat_i : in std_logic_vector(31 downto 0);
+ dat_o : out std_logic_vector(31 downto 0);
+ clk_m : in std_logic;
+ en_m : in std_logic;
+ we_m : in std_logic_vector(3 downto 0);
+ addr_m : in std_logic_vector(9 downto 0);
+ din_m : in std_logic_vector(31 downto 0);
+ dout_m : out std_logic_vector(31 downto 0)
+ );
+ end component;
+
+ component lx_rocon_gprf_abd
+ port
+ (
+ clk_i : in std_logic;
+ rst_i : in std_logic;
+ clken_i : in std_logic;
+ ID2GPRF_i : in ID2GPRF_Type;
+ MEM_WRB_i : in WRB_Type;
+ GPRF2EX_o : out GPRF2EX_Type
+ );
+ end component;
+
+ --------------------------------------------------------------------------------
+ -- MEMORY BUS
+ --------------------------------------------------------------------------------
+
+ -- Calibration read register
+ component calibration_read_register
+ generic
+ (
+ id : std_logic_vector(31 downto 0)
+ );
+ port
+ (
+ data_out : out std_logic_vector(31 downto 0);
+ rd : in std_logic;
+ ta : out std_logic
+ );
+ end component;
+
+ -- Calibration write register
+ component calibration_write_register
+ port
+ (
+ clk : in std_logic;
+ reset : in std_logic;
+ ce : in std_logic;
+ data_in : in std_logic_vector(31 downto 0);
+ data_out : out std_logic_vector(31 downto 0);
+ rd : in std_logic;
+ bls : in std_logic_vector(3 downto 0);
+ ta : out std_logic
+ );
+ end component;
+
+ -- Calibration interconnect
+ component bus_calibration
+ port
+ (
+ clk : in std_logic;
+ reset : in std_logic;
+ ce : in std_logic;
+ address : in std_logic_vector(1 downto 0);
+ data_in : in std_logic_vector(31 downto 0);
+ data_out : out std_logic_vector(31 downto 0);
+ rd : in std_logic;
+ bls : in std_logic_vector(3 downto 0);
+ ta : out std_logic
+ );
+ end component;
+
+ -- IRC interconnect
+ component bus_irc
+ port
+ (
+ clk : in std_logic;
+ reset : in std_logic;
+
+ address : in std_logic_vector(3 downto 0);
+ ce : in std_logic;
+
+ data_in : in std_logic;
+ data_out : out std_logic_vector(31 downto 0);
+
+ rd : in std_logic;
+ wr : in std_logic;
+ ta : out std_logic;
+
+ irc1_a : in std_logic;
+ irc1_b : in std_logic;
+ irc1_index : in std_logic;
+ irc1_mark : in std_logic;
+
+ irc2_a : in std_logic;
+ irc2_b : in std_logic;
+ irc2_index : in std_logic;
+ irc2_mark : in std_logic;
+
+ irc3_a : in std_logic;
+ irc3_b : in std_logic;
+ irc3_index : in std_logic;
+ irc3_mark : in std_logic;
+
+ irc4_a : in std_logic;
+ irc4_b : in std_logic;
+ irc4_index : in std_logic;
+ irc4_mark : in std_logic
+ );
+ end component;
+
+ -- BCD interconnect
+ component bus_bcd
+ port
+ (
+ reset : in std_logic;
+ en : in std_logic;
+ clk : in std_logic;
+ data_out : out std_logic_vector(31 downto 0);
+ rd : in std_logic;
+ ta : out std_logic
+ );
+ end component;
+
+ -- Tumbl interconnect
+ component bus_tumbl
+ port
+ (
+ clk_100m : in std_logic;
+ clk_50m : in std_logic;
+ ce : in std_logic;
+ reset : in std_logic;
+ rd : in std_logic;
+ bls : in std_logic_vector(3 downto 0);
+ address : in std_logic_vector(11 downto 0);
+ data_in : in std_logic_vector(31 downto 0);
+ data_out : out std_logic_vector(31 downto 0);
+ ta : out std_logic;
+ XMEMB_sel_o : out std_logic;
+ XMEMB_i : in DMEMB2CORE_Type;
+ XMEMB_o : out CORE2DMEMB_Type
+ );
+ end component;
+
+ --------------------------------------------------------------------------------
+ -- BRAM
+ --------------------------------------------------------------------------------
+
+ component xilinx_dualport_bram
+ generic
+ (
+ byte_width : positive := 8;
+ address_width : positive := 8;
+ we_width : positive := 4
+ );
+ port
+ (
+ clka : in std_logic;
+ rsta : in std_logic;
+ ena : in std_logic;
+ wea : in std_logic_vector((we_width-1) downto 0);
+ addra : in std_logic_vector((address_width-1) downto 0);
+ dina : in std_logic_vector(((byte_width*we_width)-1) downto 0);
+ douta : out std_logic_vector(((byte_width*we_width)-1) downto 0);
+ clkb : in std_logic;
+ rstb : in std_logic;
+ enb : in std_logic;
+ web : in std_logic_vector((we_width-1) downto 0);
+ addrb : in std_logic_vector((address_width-1) downto 0);
+ dinb : in std_logic_vector(((byte_width*we_width)-1) downto 0);
+ doutb : out std_logic_vector(((byte_width*we_width)-1) downto 0)
+ );
+ end component;
+
+end lx_rocon_pkg;
+
+package body lx_rocon_pkg is
+
+
+end lx_rocon_pkg;
-vhdl work "dff.vhd"
+vhdl work "tumbl/mbl_Pkg.vhd"
+vhdl work "lx_rocon_pkg.vhd"
+vhdl work "dff2.vhd"
+vhdl work "xilinx_dualport_bram.vhd"
vhdl work "qcounter.vhd"
+vhdl work "tumbl/mem.vhd"
+vhdl work "tumbl/fetch.vhd"
+vhdl work "tumbl/exeq.vhd"
+vhdl work "tumbl/decode.vhd"
+vhdl work "tumbl/core_ctrl.vhd"
+vhdl work "lx-rocon_tumbl/lx_rocon_imem.vhd"
+vhdl work "lx-rocon_tumbl/lx_rocon_gprf_abd.vhd"
+vhdl work "lx-rocon_tumbl/lx_rocon_dmem.vhd"
vhdl work "irc_reader.vhd"
+vhdl work "lx-rocon_tumbl/lx_rocon_tumbl.vhd"
vhdl work "irc_register.vhd"
-vhdl work "ipcore_dir/control_bram.vhd"
vhdl work "calibration_write_register.vhd"
vhdl work "calibration_read_register.vhd"
-vhdl work "bcd.vhd"
+vhdl work "bus_tumbl.vhd"
vhdl work "bus_irc.vhd"
-vhdl work "bus_control_bram.vhd"
vhdl work "bus_calibration.vhd"
-vhdl work "bus_bcd.vhd"
vhdl work "lx_rocon_top.vhd"
use ieee.std_logic_unsigned.all;
use ieee.numeric_std.all;
--- lx_rocon_top - wires the modules with outside world
+library unisim;
+use unisim.vcomponents.all;
+
+use work.mbl_Pkg.all;
+use work.lx_rocon_pkg.all;
+
+-- lx_rocon_top - wires the modules with the outside world
-- ======================================================
--- INTERNAL MEMORY BUS
+-- MASTER CPU EXTERNAL MEMORY BUS
-- ======================================================
--
--- Internal memory bus has the following wires:
+-- Master cpu memory bus has the following wires:
--
-- - address[15..0] The address
-- - data_in[31..0] The data coming to bus
-- - bls[3..0] Write enable for respective bytes, active LOW
-- In some cases, only WR is used
-- - ta Transaction acknowledge (latches data out), active LOW, multiplexed
+--
+-- ======================================================
+-- TUMBL EXTERNAL MEMORY BUS
+-- ======================================================
entity lx_rocon_top is
port
(
-- External
- clk_cpu : in std_logic;
+ --clk_cpu : in std_logic;
+ clk_50m : in std_logic;
cs0_xc : in std_logic;
-- Reset signal
signal reset : std_logic;
+ signal neg_init : std_logic;
+
+ -- 100 MHz clock
+ signal clk_100m : std_logic;
+ signal clk_100m_fb : std_logic;
+ signal clk_100m_locked : std_logic;
-- Peripherals on the memory bus
- signal bram_out : std_logic_vector(31 downto 0);
- signal bram_ta : std_logic;
- signal bram_ce : std_logic;
+ signal tumbl_out : std_logic_vector(31 downto 0);
+ signal tumbl_ta : std_logic;
+ signal tumbl_ce : std_logic;
signal irc_reg_out : std_logic_vector(31 downto 0);
signal irc_reg_ta : std_logic;
signal irc_reg_ce : std_logic;
- signal bcd_out : std_logic_vector(31 downto 0);
- signal bcd_ta : std_logic;
- signal bcd_ce : std_logic;
-
signal calib_out : std_logic_vector(31 downto 0);
signal calib_ta : std_logic;
signal calib_ce : std_logic;
-- Data latching is synchronous - it's purpose is to
-- provide stable data for CPU on the bus on high rise
-- of trans. ack signal
+ signal rd_f : std_logic;
+ signal rd_d : std_logic;
+
+ signal data_read : std_logic_vector(31 downto 0);
+
signal i_ta : std_logic;
signal i_rd : std_logic;
- signal data_read : std_logic_vector(31 downto 0);
signal acked : std_logic;
-- Writing logic:
- signal i_bls : std_logic_vector(3 downto 0);
+ signal bls_f : std_logic_vector(3 downto 0);
+ signal bls_d : std_logic_vector(3 downto 0);
+
signal data_write : std_logic_vector(31 downto 0);
- component bus_irc
- port
- (
- clk : in std_logic;
- reset : in std_logic;
-
- address : in std_logic_vector(3 downto 0);
- ce : in std_logic;
-
- data_in : in std_logic;
- data_out : out std_logic_vector(31 downto 0);
-
- rd : in std_logic;
- wr : in std_logic;
- ta : out std_logic;
-
- irc1_a : in std_logic;
- irc1_b : in std_logic;
- irc1_index : in std_logic;
- irc1_mark : in std_logic;
-
- irc2_a : in std_logic;
- irc2_b : in std_logic;
- irc2_index : in std_logic;
- irc2_mark : in std_logic;
-
- irc3_a : in std_logic;
- irc3_b : in std_logic;
- irc3_index : in std_logic;
- irc3_mark : in std_logic;
-
- irc4_a : in std_logic;
- irc4_b : in std_logic;
- irc4_index : in std_logic;
- irc4_mark : in std_logic
- );
- end component;
+ signal i_bls : std_logic_vector(3 downto 0);
- component bus_control_bram
- port
- (
- clk : in std_logic;
-
- ena : in std_logic;
- wea : in std_logic_vector(3 downto 0);
- addra : in std_logic_vector(8 downto 0);
- dina : in std_logic_vector(31 downto 0);
- douta : out std_logic_vector(31 downto 0);
- taa : out std_logic;
-
- enb : in std_logic;
- web : in std_logic_vector(3 downto 0);
- addrb : in std_logic_vector(8 downto 0);
- dinb : in std_logic_vector(31 downto 0);
- doutb : out std_logic_vector(31 downto 0)
- );
- end component;
-
- component bus_bcd
- port
- (
- reset : in std_logic;
- en : in std_logic;
- clk : in std_logic;
- ce : in std_logic;
- data_out : out std_logic_vector(31 downto 0);
- rd : in std_logic;
- ta : out std_logic
- );
- end component;
+begin
- component bus_calibration
- port
+ -- Clocking
+ clk_100m_dcm_sp : DCM_SP
+ generic map
(
- clk : in std_logic;
- reset : in std_logic;
- ce : in std_logic;
- address : in std_logic_vector(1 downto 0);
- data_in : in std_logic_vector(31 downto 0);
- data_out : out std_logic_vector(31 downto 0);
- rd : in std_logic;
- bls : in std_logic_vector(3 downto 0);
- ta : out std_logic
+ clkdv_divide => 2.0,
+ clkfx_divide => 1,
+ clkfx_multiply => 2,
+ clkin_divide_by_2 => false,
+ clkin_period => 20.0, -- 50 MHz
+ clkout_phase_shift => "NONE",
+ clk_feedback => "1X",
+ deskew_adjust => "SYSTEM_SYNCHRONOUS",
+ dfs_frequency_mode => "LOW",
+ dll_frequency_mode => "LOW",
+ dss_mode => "NONE",
+ duty_cycle_correction => true,
+ factory_jf => X"c080",
+ phase_shift => 0,
+ startup_wait => false
+ )
+ port map
+ (
+ clk0 => clk_100m_fb,
+ clk180 => open,
+ clk270 => open,
+ clk2x => clk_100m,
+ clk2x180 => open,
+ clk90 => open,
+ clkdv => open,
+ clkfx => open,
+ clkfx180 => open,
+ locked => clk_100m_locked,
+ psdone => open,
+ status => open,
+ clkfb => clk_100m_fb,
+ clkin => clk_50m,
+ dssen => '0',
+ psclk => '0',
+ psen => '0',
+ psincdec => '0',
+ rst => neg_init
);
- end component;
-
-begin
-- IRC interconnect
memory_bus_irc: bus_irc
port map
(
- clk => clk_cpu,
+ clk => clk_100m,
reset => reset,
address => address(3 downto 0),
ce => irc_reg_ce,
data_in => data_in_bus(0),
data_out => irc_reg_out,
rd => i_rd,
- wr => bls(0),
+ wr => i_bls(0),
ta => irc_reg_ta,
irc1_a => irc1_a,
irc4_mark => irc4_mark
);
- -- Control BRAM interconnect (9 kib)
- memory_bus_control_bram: bus_control_bram
+ -- Tumbl coprocessor
+ memory_bus_tumbl: bus_tumbl
port map
(
- clk => clk_cpu,
- ena => bram_ce,
- taa => bram_ta,
- wea => i_bls,
- addra => address(8 downto 0),
- dina => data_in_bus,
- douta => bram_out,
-
- enb => '0',
- web => (others => '0'),
- addrb => (others => '0'),
- dinb => (others => '0'),
- doutb => open
- );
-
- -- BCD
- memory_bus_bcd: bus_bcd
- port map
- (
- clk => clk_cpu,
+ clk_100m => clk_100m,
+ clk_50m => clk_50m,
reset => reset,
- en => '1',
- ce => bcd_ce,
+ ce => tumbl_ce,
+ ta => tumbl_ta,
rd => i_rd,
- ta => bcd_ta,
- data_out => bcd_out
+ bls => i_bls,
+ address => address(11 downto 0),
+ data_in => data_in_bus,
+ data_out => tumbl_out,
+
+ XMEMB_o => open,
+ XMEMB_i.clken => '1',
+ XMEMB_i.data => (others => '1'),
+ XMEMB_i.int => '0',
+ XMEMB_sel_o => open
);
-- Calibration
memory_bus_calibration: bus_calibration
port map
(
- clk => clk_cpu,
+ clk => clk_100m,
reset => reset,
ce => calib_ce,
address => address(1 downto 0),
data_out => calib_out
);
+ -- Filters
+ bls_f <= bls when bls = bls_d else "1111";
+ rd_f <= rd when rd = rd_d else '1';
+
-- Bus update
- memory_bus_update: process(clk_cpu)
+ memory_bus_update: process(clk_100m)
begin
- if clk_cpu = '1' and clk_cpu'event then
+ if clk_100m = '1' and clk_100m'event then
-- Set every signal to inactive state here
irc_reg_ce <= '1';
- bram_ce <= '1';
- bcd_ce <= '1';
+ tumbl_ce <= '1';
calib_ce <= '1';
i_rd <= '1';
i_bls <= (others => '1');
-- Memory Map (16-bit address @ 32-bit each)
-- Each address is seen as 32-bit entry now
- -- 0x0000 - 0x011F: Control dual-port BRAM
+ -- 0x0000 - 0x0FFF: Tumbl
-- 0x8000 - 0x800F: IRC registers
- -- 0xFFFB: 32-bit BCD
-- 0xFFFC - 0xFFFF: Calibration
- if address < "0000000100100000" then -- Control BRAM
- bram_ce <= '0';
- i_ta <= bram_ta;
- data_out_bus <= bram_out;
+ if address < "0001000000000000" then -- Tumbl
+ tumbl_ce <= '0';
+ i_ta <= tumbl_ta;
+ data_out_bus <= tumbl_out;
elsif address(15 downto 4) = "100000000000" then -- IRC
irc_reg_ce <= '0';
i_ta <= irc_reg_ta;
data_out_bus <= irc_reg_out;
- elsif address = "1111111111111011" then -- BCD
- bcd_ce <= '0';
- i_ta <= bcd_ta;
- data_out_bus <= bcd_out;
elsif address(15 downto 2) = "11111111111111" then -- Calibration
calib_ce <= '0';
i_ta <= calib_ta;
end if;
-- Reading
- if rd = '0' then
+ if rd_f = '0' then
if last_rd = '1' or last_address /= address then
-- Getting something new
-- Set internal RD to active and reset ack and latched data
data_read <= (others => 'X');
end if;
- last_rd <= rd;
+ last_rd <= rd_f;
- -- Writing
- if bls /= "1111" then
- if last_bls /= bls or last_address /= address then
- -- Data are valid when BLS is active, broadcast it for one cycle
- i_bls <= bls;
+ -- Writing (BLS is filtered due to bus error otherwise)
+ if bls_f /= "1111" then
+
+ if last_bls /= bls_f or last_address /= address then
+ -- Broadcast BLS for once cycle to write the data
+ i_bls <= bls_f;
data_in_bus <= data_write;
end if;
last_address <= address;
end if;
- last_bls <= bls;
+ last_bls <= bls_f;
else
end if;
+ -- Filters
+ bls_d <= bls;
+ rd_d <= rd;
+
end if;
end process;
end process;
-- Reset
- initialization: process(init)
+ initialization: process(init, clk_100m_locked)
begin
- reset <= not init;
+ neg_init <= not init;
+ reset <= (not init) or (not clk_100m_locked);
end process;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;
use ieee.numeric_std.all;
+use work.lx_rocon_pkg.all;
-- Quadcounter (for IRC)
clk : in std_logic;
reset : in std_logic;
a0, b0 : in std_logic;
+ index0 : in std_logic;
qcount : out std_logic_vector (31 downto 0);
+ qcount_index : out std_logic_vector (31 downto 0);
a_rise, a_fall, b_rise, b_fall, ab_event: out std_logic;
ab_error : out std_logic
);
end qcounter;
architecture behavioral of qcounter is
- component dff
- port
- (
- clk : in std_logic;
- reset : in std_logic;
- d : in std_logic;
- q : out std_logic
- );
- end component;
-subtype std_logic4 is std_logic_vector (3 downto 0);
signal last_reset: std_logic;
signal a, b, a_prev, b_prev: std_logic;
+ signal index: std_logic;
signal count_prev: std_logic_vector (29 downto 0);
signal count: std_logic_vector (29 downto 0);
+ signal count_index_prev: std_logic_vector (31 downto 0);
+ signal count_index: std_logic_vector (31 downto 0);
+
begin
- dff_a: dff
+ dff_a: dff2
port map
(
clk => clk,
q => a
);
- dff_b: dff
+ dff_b: dff2
port map
(
clk => clk,
q => b
);
+ dff_index: dff2
+ port map
+ (
+ clk => clk,
+ reset => '0',
+ d => index0,
+ q => index
+ );
+
qcount(0) <= a xor b;
qcount(1) <= b;
qcount(31 downto 2) <= count;
+ qcount_index <= count_index;
+
comb_event: process (reset, last_reset, a_prev, b_prev, a, b)
begin
a_rise <= '0';
end if;
end process;
- comb_count: process (reset, last_reset, a_prev, b_prev, a, b, count_prev)
+ comb_count: process (reset, last_reset, a_prev, b_prev, a, b, index, count_prev, count_index_prev)
begin
if reset = '1' or last_reset = '1' then
count <= count_prev;
+ count_index <= count_index_prev;
+
elsif (a_prev = '0') and (b_prev = '1') and (a = '0') and (b = '0') then
count <= count_prev + 1;
+
+ if index = '1' then
+ count_index(0) <= a xor b;
+ count_index(1) <= b;
+ count_index(31 downto 2) <= count_prev + 1;
+ else
+ count_index <= count_index_prev;
+ end if;
+
elsif (a_prev = '0') and (b_prev = '0') and (a = '0') and (b = '1') then
count <= count_prev - 1;
+
+ if index = '1' then
+ count_index(0) <= a xor b;
+ count_index(1) <= b;
+ count_index(31 downto 2) <= count_prev - 1;
+ else
+ count_index <= count_index_prev;
+ end if;
+
else
count <= count_prev;
+
+ if index = '1' then
+ count_index(0) <= a xor b;
+ count_index(1) <= b;
+ count_index(31 downto 2) <= count_prev;
+ else
+ count_index <= count_index_prev;
+ end if;
+
end if;
+
end process;
seq: process (clk)
if clk = '1' and clk'event then
if reset = '0' then
count_prev <= count;
+ count_index_prev <= count_index;
else
count_prev <= (others => '0');
+ count_index_prev <= (others => '0');
end if;
a_prev <= a;
b_prev <= b;
COMPONENT lx_rocon_top
PORT(
- clk_cpu : IN std_logic;
+ --clk_cpu : IN std_logic;
+ clk_50m : IN std_logic;
cs0_xc : IN std_logic;
rd : IN std_logic;
bls : IN std_logic_vector(3 downto 0);
--Inputs
- signal clk_cpu : std_logic := '0';
+ --signal clk_cpu : std_logic := '0';
+ signal clk_50m : std_logic := '0';
signal cs0_xc : std_logic := '1';
signal rd : std_logic := '1';
signal bls : std_logic_vector(3 downto 0) := (others => '1');
signal data : std_logic_vector(31 downto 0);
-- Clock period definitions
- constant clk_period : time := 20 ns;
+ constant clk_period_cpu : time := 13.8 ns;
+ constant clk_period_50m : time := 20 ns;
BEGIN
-- Instantiate the Unit Under Test (UUT)
uut: lx_rocon_top PORT MAP (
- clk_cpu => clk_cpu,
+ --clk_cpu => clk_cpu,
+ clk_50m => clk_50m,
cs0_xc => cs0_xc,
rd => rd,
bls => bls,
);
-- Clock process definitions
- clk_process :process
+-- clk_cpu_process :process
+-- begin
+-- clk_cpu <= '0';
+-- wait for clk_period_cpu/2;
+-- clk_cpu <= '1';
+-- wait for clk_period_cpu/2;
+-- end process;
+
+ clk_50m_process :process
begin
- clk_cpu <= '0';
- wait for clk_period/2;
- clk_cpu <= '1';
- wait for clk_period/2;
+ clk_50m <= '0';
+ wait for clk_period_50m/2;
+ clk_50m <= '1';
+ wait for clk_period_50m/2;
end process;
-- Stimulus process
stim_proc: process
begin
- -- hold reset state for 100 ns.
- init <= '0';
- data <= (others => 'Z');
- wait for 100 ns;
- init <= '1';
-
- wait for clk_period*10;
-
- -- insert stimulus here
-
- -- Increment IRC1
- irc1_a <= '1';
- wait for clk_period*2;
-
- irc1_b <= '1';
- wait for clk_period*2;
-
- irc1_a <= '0';
- wait for clk_period*2;
-
- irc1_b <= '0';
- wait for clk_period*2;
-
- irc1_a <= '1';
- wait for clk_period*2;
-
- irc1_b <= '1';
- wait for clk_period*2;
-
- irc1_a <= '0';
- wait for clk_period*2;
-
- -- Read IRC1 value (bus has 72 MHz, but signals are set to stay longer)
- cs0_xc <= '0';
- wait for clk_period;
-
- address <= "1000000000000000";
- wait for clk_period;
-
- rd <= '0';
- wait for 5*clk_period;
-
- cs0_xc <= '1';
- wait for clk_period;
-
- rd <= '1';
- wait for clk_period*3;
-
- -- Test BRAM: Write something and then read it back
- cs0_xc <= '0';
- wait for clk_period;
-
- address <= "0000000000011000";
- data <= "10101010101010101010101010101010";
- wait for clk_period;
-
- bls <= "0000";
- wait for 5*clk_period;
-
- cs0_xc <= '1';
- wait for clk_period;
-
- bls <= "1111";
- wait for clk_period;
-
- -- Now read it back
- cs0_xc <= '0';
- wait for clk_period;
-
- rd <= '0';
- wait for 5*clk_period;
-
- cs0_xc <= '1';
- wait for clk_period;
-
- rd <= '1';
- wait for clk_period*3;
-
- -- Now try writing to above address but with only some bytes active
- cs0_xc <= '0';
- wait for clk_period;
-
- address <= "0000000000011100";
- data <= "10101010101010101010101010101010";
- wait for clk_period;
-
- bls <= "0011";
- wait for 5*clk_period;
-
- cs0_xc <= '1';
- wait for clk_period;
-
- bls <= "1111";
- wait for clk_period;
-
- data <= (others => 'Z');
- wait for clk_period;
-
- -- Now read it back
- cs0_xc <= '0';
- wait for clk_period;
-
- rd <= '0';
- wait for 5*clk_period;
-
- cs0_xc <= '1';
- wait for clk_period;
-
- rd <= '1';
- wait for clk_period;
-
- -- Poke the bcd a few times
- cs0_xc <= '0';
- address <= "1111111111111011";
- wait for clk_period;
-
- rd <= '0';
- wait for 5*clk_period;
-
- cs0_xc <= '1';
- wait for clk_period;
-
- rd <= '1';
- wait for clk_period*5;
-
- cs0_xc <= '0';
- wait for clk_period;
-
- rd <= '0';
- wait for 5*clk_period;
-
- cs0_xc <= '1';
- wait for clk_period;
-
- rd <= '1';
- wait for clk_period;
-
- -- Read calibration register
- cs0_xc <= '0';
- address <= "1111111111111100";
- wait for clk_period;
-
- rd <= '0';
- wait for 8*clk_period;
-
- cs0_xc <= '1';
- wait for clk_period;
-
- rd <= '1';
- wait for clk_period*5;
-
- -- Write & Read calibration register
- cs0_xc <= '0';
- address <= "1111111111111110";
- data <= "10101010101010101010101010101010";
- wait for clk_period;
-
- bls <= "0000";
- wait for 8*clk_period;
-
- cs0_xc <= '1';
- wait for clk_period;
-
- rd <= '1';
- wait for clk_period*5;
-
- cs0_xc <= '0';
- address <= "1111111111111110";
- data <= (others => 'Z');
- wait for clk_period;
-
- rd <= '0';
- wait for 8*clk_period;
-
- cs0_xc <= '1';
- wait for clk_period;
-
- rd <= '1';
- wait for clk_period*5;
+ -- External ModelSim script
wait;
end process;
--- /dev/null
+../submodule/tumbl/hw
\ No newline at end of file
--- /dev/null
+-- Xilinx dualport BRAM template, write-first mode, no delay
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+use work.lx_rocon_pkg.all;
+
+entity xilinx_dualport_bram is
+ generic
+ (
+ -- Not all combinations are plausible for BRAMs
+ -- byte width: 8, 9, 32, 36
+ -- we_width: 1, 2, 3, 4
+ byte_width : positive := 8;
+ address_width : positive := 8;
+ we_width : positive := 4
+ );
+ port
+ (
+ clka : in std_logic;
+ rsta : in std_logic;
+ ena : in std_logic;
+ wea : in std_logic_vector((we_width-1) downto 0);
+ addra : in std_logic_vector((address_width-1) downto 0);
+ dina : in std_logic_vector(((byte_width*we_width)-1) downto 0);
+ douta : out std_logic_vector(((byte_width*we_width)-1) downto 0);
+ clkb : in std_logic;
+ rstb : in std_logic;
+ enb : in std_logic;
+ web : in std_logic_vector((we_width-1) downto 0);
+ addrb : in std_logic_vector((address_width-1) downto 0);
+ dinb : in std_logic_vector(((byte_width*we_width)-1) downto 0);
+ doutb : out std_logic_vector(((byte_width*we_width)-1) downto 0)
+ );
+end xilinx_dualport_bram;
+
+architecture Behavioral of xilinx_dualport_bram is
+ type ram is array (0 to ((2**address_width) - 1)) of std_logic_vector(((byte_width*we_width)-1) downto 0);
+ shared variable ram_block : ram := (others => (others => '0'));
+
+begin
+
+ -- CLKA process
+ ram_process_a : process(clka)
+ begin
+
+ if clka = '1' and clka'event then
+
+ if ena = '1' then
+
+ for i in 0 to (we_width-1) loop
+ if wea(i) = '1' then
+ ram_block(to_integer(unsigned(addra)))(((i+1)*byte_width-1) downto (i*byte_width))
+ := dina(((i+1)*byte_width-1) downto (i*byte_width));
+ end if;
+ end loop;
+
+ if rsta = '1' then
+ douta <= (others => '0');
+ else
+ douta <= ram_block(to_integer(unsigned(addra)));
+ end if;
+
+ end if;
+
+ end if;
+
+ end process;
+
+ -- CLKB process
+ ram_process_b : process(clkb)
+ begin
+
+ if clkb = '1' and clkb'event then
+
+ if enb = '1' then
+
+ for i in 0 to (we_width-1) loop
+ if web(i) = '1' then
+ ram_block(to_integer(unsigned(addrb)))(((i+1)*byte_width-1) downto (i*byte_width))
+ := dinb(((i+1)*byte_width-1) downto (i*byte_width));
+ end if;
+ end loop;
+
+ if rstb = '1' then
+ doutb <= (others => '0');
+ else
+ doutb <= ram_block(to_integer(unsigned(addrb)));
+ end if;
+
+ end if;
+
+ end if;
+
+ end process;
+
+end Behavioral;
--- /dev/null
+Subproject commit 342b65f43eca19d8169829aa8d342d1424c6d323