-- -- Transition Radiation Detector -- -- MCM Control Unit - Configuration Network -- -- -- -- $Id: mcm_excalibur_simulator.vhd,v 1.8 2002/07/01 13:12:36 rgareus Exp $ -- -- Robin Gareus, Kirchhoff Institute for Physics, Heidelberg -- rgareus@kip.uni-heidelberg.de -- ------------------------------------------------------------ -- Network Master Top Level, using the data-link layer of the MCMs to -- emulate/simulate the work to be done by the excalibur-master. -- -- This file is a fast hack - just to be able to test the network -- in hardware. -- -- Network-interface to CPU: -- -- IRQ is set on any incoming frame. and reset when reading -- the status register. -- -- address : in std_logic_vector( 3 downto 0); -- WE,CS : in std_logic; -- data_in : in std_logic_vector(15 downto 0); -- data_out : out std_logic_vector(15 downto 0); -- IRQ : out std_logic; -- -- address -- -- Ring 0: -- 0, 1 - Data -- 2 - address (Global I/O) -- 3 - command -- 4 - mcmaddress, writing here also starts sending -- 7 - status (bits 3-0 equal for both rings) (read only) -- Ring 1: -- 8, 9 - Data -- 10 - address (Global I/O) -- 11 - command -- 12 - mcmaddress, writing here also starts sending -- 15 - status (bits 3-0 equal for both rings) (read only) -- -- mcmaddress "0" is the reserved id for this master-unit. -- so first mcm in row is addressed with "1". -- setting mcmaddress to 127 means broadcast. -- -- Status Data -- status(0) <= d0_recieved -- status(1) <= d0_recieve_error -- status(2) <= recieved frame (ring0) is an answer-frame -- status(3) <= currently sending data out on ring0. -- status(4) <= d1_recieved -- status(5) <= d1_recieve_error -- status(6) <= recieved frame (ring1) is an answer-frame -- status(7) <= currently sending data out on ring1. -- status(15 downto 8) <= hop counter of recieved frame. -- -- MCM-Commands -- 0x1 -> read -- 0x2 -> write -- 0x3 -> read_broadcast (check status) -- MCM performs read. and if read_data[0] is '1' -- this command is interpreted as read and -- replied, else the command-request -- it is forwarded to the next MCM. -- 0x4 -> bridge -- set bridge to value of data[0] -- '0' is serial, '1' is bridged -- default state after reset is '0'. address is ignored. -- 0x7 -> NOP -- just forward the frame. -------------------------------------------------- -- standard includes, library definitions. -------------------------------------------------- library ieee,work; use ieee.std_logic_1164.all; use work.mcm_nw_dll; use work.mcm_nw_pl; -------------------------------------------------- -- ENTITY -------------------------------------------------- entity mcm_excalibur_simulator is port( -- external Network Interface d_in_0 : in std_logic ; d_out_0 : out std_logic ; d_in_1 : in std_logic ; d_out_1 : out std_logic ; --- clock and reset Signals reset_n : in std_logic; clk : in std_logic; address : in std_logic_vector(3 downto 0); CLK_CPU, CS, WE : in std_logic; data_in : in std_logic_vector(15 downto 0); data_out : out std_logic_vector(15 downto 0); IRQ : out std_logic ); end mcm_excalibur_simulator; -------------------------------------------------- -- ARCHITECTURE -------------------------------------------------- architecture structural of mcm_excalibur_simulator is -------------------------------------------------- -- internal signals -------------------------------------------------- TYPE excalibur_send_state_type IS ( idle, start_send, wait_for_send_to_finish ); signal current_state0,next_state0 : excalibur_send_state_type; signal current_state1,next_state1 : excalibur_send_state_type; signal d0_data_to_send : std_logic_vector(68 downto 0); signal d0_revieved_data : std_logic_vector(68 downto 0); signal d0_recieved,d0_recieve_error,d0_recv_buffer_half,d0_we, d0_send_start,d0_buffer_ready : std_logic; signal d1_data_to_send : std_logic_vector(68 downto 0); signal d1_revieved_data : std_logic_vector(68 downto 0); signal d1_recieved,d1_recieve_error,d1_recv_buffer_half,d1_we, d1_send_start,d1_buffer_ready : std_logic; signal new_data0,new_data1, WE_i : std_logic; signal data0_0s, data0_1s : std_logic_vector(15 downto 0); signal data1_0s, data1_1s : std_logic_vector(15 downto 0); signal addr0_s,addr1_s : std_logic_vector(15 downto 0); signal command0_s,command1_s : std_logic_vector(3 downto 0); signal mcmaddr0_s,mcmaddr1_s : std_logic_vector(6 downto 0); signal data0_0r, data0_1r : std_logic_vector(15 downto 0); signal data1_0r, data1_1r : std_logic_vector(15 downto 0); signal addr0_r,addr1_r : std_logic_vector(15 downto 0); signal command0_r,command1_r : std_logic_vector(3 downto 0); signal mcmaddr0_r,mcmaddr1_r : std_logic_vector(6 downto 0); signal mcmhop0_r,mcmhop1_r : std_logic_vector(7 downto 0); signal status : std_logic_vector(7 downto 0); signal new_frame : std_logic; signal d0_mask,d1_mask : std_logic; signal bridge : std_logic; SIGNAL data_in_0,data_in_1 : std_logic; signal d0_recieved_r : std_logic; signal d0_recieve_error_r : std_logic; signal d0_revieved_data61_r : std_logic; signal d1_recieved_r : std_logic; signal d1_recieve_error_r : std_logic; signal d1_revieved_data61_r : std_logic; -------------------------------------------------- -- components -------------------------------------------------- COMPONENT mcm_nw_dll is generic (timing_count_range : integer := 7; timing_recv_on : integer := 2; stuff_length : integer := 4; timing_sleep_length : integer := 63; BUFSIZ : integer := 69; COUNTER : integer := 7); port( -- Signals from/to phyiscal layer : serial data d0_fr_pl : in std_logic; d0_to_pl : out std_logic; d1_fr_pl : in std_logic; d1_to_pl : out std_logic; -- Signals to Network Layer (recv) d0_to_nwl : out std_logic_vector(BUFSIZ-1 downto 0); s0_to_nwl : out std_logic ; buf0_half : out std_logic ; buf0_err : out std_logic ; d1_to_nwl : out std_logic_vector(BUFSIZ-1 downto 0); s1_to_nwl : out std_logic ; buf1_half : out std_logic ; buf1_err : out std_logic ; -- Signals from Network Layer (send) d0_fr_nwl : in std_logic_vector(BUFSIZ-1 downto 0); d0_we : in std_logic; d0_send : in std_logic; d0_buffer_ready : out std_logic; d1_fr_nwl : in std_logic_vector(BUFSIZ-1 downto 0); d1_we : in std_logic; d1_send : in std_logic; d1_buffer_ready : out std_logic; -- X-bar data paths bridge : in std_logic; reset_n : in std_logic; clk_buf : in std_logic; clk : in std_logic ); END COMPONENT; COMPONENT mcm_nw_pl is generic ( len : integer := 1); port( -- Signals from outside ser0_din : in std_logic; ser1_din : in std_logic; -- Signals to Data Link Layer d0_to_dll : out std_logic; d1_to_dll : out std_logic; clk_dis : out std_logic; reset_n : in std_logic; clk : in std_logic ); END COMPONENT; -------------------------------------------------- -- port maps -------------------------------------------------- begin nw_pl: mcm_nw_pl generic map ( len => 1 ) port map( ser0_din => d_in_0, ser1_din => d_in_1, d0_to_dll => data_in_0, d1_to_dll => data_in_1, clk_dis => open, reset_n => reset_n, clk => clk); -- data_in_0<=d_in_0; -- skip physical layer filter -- data_in_1<=d_in_1; nw_dll: mcm_nw_dll generic map( timing_count_range => 4, -- must be >2; default : 7 timing_recv_on => 2, -- < timing_count_range - 3; -- default : 2 stuff_length => 7, -- default : 4 timing_sleep_length=> 63) -- default : 144 port map( d0_fr_pl => data_in_0 , d0_to_pl => d_out_0, buf0_half => d0_recv_buffer_half, s0_to_nwl => d0_recieved, buf0_err => d0_recieve_error, d0_to_nwl => d0_revieved_data, d0_fr_nwl => d0_data_to_send, d0_we => d0_we, d0_send => d0_send_start, d0_buffer_ready => d0_buffer_ready, d1_fr_pl => data_in_1 , d1_to_pl => d_out_1, buf1_half => d1_recv_buffer_half, s1_to_nwl => d1_recieved, buf1_err => d1_recieve_error, d1_to_nwl => d1_revieved_data, d1_fr_nwl => d1_data_to_send, d1_we => d1_we, d1_send => d1_send_start, d1_buffer_ready => d1_buffer_ready, bridge => bridge, reset_n => reset_n, clk_buf => clk, clk => clk ); bridge <= '0'; -------------------------------------------------- -- processes -------------------------------------------------- WE_i <= WE and CS; IRQ <= new_frame; -- -- Frame structure -- -- LSB first -> 68 is the first... -- 68..62 : address (MCM) -- 61 : source/dest : '1' -- 60..53 : hopcounter => 0 from NIOS -- 52..49 : command -- 0x1 -> read "1000" -- 0x2 -> write "0100" -- 0x3 -> read_broadcast (check status) -- 0x4 -> bridge -- 0x7 -> NOP -- 48..32 : global bus address (17bit, 32 (16) is unused) -- 31..0 : data(0 .. 31) gen0: for i in 0 to 15 generate d0_data_to_send(31-i) <= data0_0s(i); d0_data_to_send(15-i) <= data0_1s(i); d0_data_to_send(48-i) <= addr0_s(i); d1_data_to_send(31-i) <= data1_0s(i); d1_data_to_send(15-i) <= data1_1s(i); d1_data_to_send(48-i) <= addr1_s(i); data0_0r(i) <= d0_revieved_data(31-i); data0_1r(i) <= d0_revieved_data(15-i); addr0_r(i) <= d0_revieved_data(48-i); data1_0r(i) <= d1_revieved_data(31-i); data1_1r(i) <= d1_revieved_data(15-i); addr1_r(i) <= d1_revieved_data(48-i); end generate; gen1: for i in 0 to 3 generate d0_data_to_send(52-i) <= command0_s(i); d1_data_to_send(52-i) <= command1_s(i); command0_r(i) <= d0_revieved_data(52-i); command1_r(i) <= d1_revieved_data(52-i); end generate; gen2: for i in 0 to 6 generate d0_data_to_send(68-i) <= mcmaddr0_s(i); d1_data_to_send(68-i) <= mcmaddr1_s(i); mcmaddr0_r(i) <= d0_revieved_data(68-i); mcmaddr1_r(i) <= d1_revieved_data(68-i); end generate; gen3: for i in 0 to 7 generate mcmhop0_r(i) <= d0_revieved_data(60-i); mcmhop1_r(i) <= d1_revieved_data(60-i); end generate; d0_data_to_send(32) <= '0'; d1_data_to_send(32) <= '0'; d0_data_to_send(61) <= '1'; d1_data_to_send(61) <= '1'; d0_data_to_send(60 downto 53) <= (others => '0'); d1_data_to_send(60 downto 53) <= (others => '0'); -- status(0) <= d0_recieved and (not d0_mask); -- status(1) <= d0_recieve_error and (not d0_mask); -- status(2) <= '1' when d0_revieved_data(61) = '1' ELSE '0'; status(3) <= '0' when current_state0 = idle ELSE '1'; -- status(4) <= d1_recieved and (not d1_mask); -- status(5) <= d1_recieve_error and (not d1_mask); -- status(6) <= '1' when d1_revieved_data(61) = '1' ELSE '0'; status(7) <= '0' when current_state1 = idle ELSE '1'; d0_we <= '1'; -- always (try) to write to the output_buffer. d1_we <= '1'; -- always (try) to write to the output_buffer. -- decode address and assign read/write data process(CLK_CPU) begin if CLK_CPU'event and CLK_CPU='1' then if WE_i='1' then case address is when "0000" => data0_0s <= data_in; when "0001" => data0_1s <= data_in; when "0010" => addr0_s <= data_in; when "0011" => command0_s <= data_in(3 downto 0); when "0100" => mcmaddr0_s <= data_in(6 downto 0); when "1000" => data1_0s <= data_in; when "1001" => data1_1s <= data_in; when "1010" => addr1_s <= data_in; when "1011" => command1_s <= data_in(3 downto 0); when "1100" => mcmaddr1_s <= data_in(6 downto 0); when others => NULL; end case; end if; data_out <= (others => '0'); -- if CS = '1' then case address is when "0000" => data_out <= data0_0r; when "0001" => data_out <= data0_1r; when "0010" => data_out <= addr0_r; when "0011" => data_out(3 downto 0) <= command0_r; when "0100" => data_out(6 downto 0) <= mcmaddr0_r; when "0111" => data_out(7 downto 0) <= status; data_out(15 downto 8)<= mcmhop0_r; when "1000" => data_out <= data1_0r; when "1001" => data_out <= data1_1r; when "1010" => data_out <= addr1_r; when "1011" => data_out(3 downto 0) <= command1_r; when "1100" => data_out(6 downto 0) <= mcmaddr1_r; when "1111" => data_out(7 downto 0) <= status; data_out(15 downto 8)<= mcmhop1_r; when others => NULL; end case; -- end if; end if; end process; -- -- set IRQ if new frame arrived. -- mask this irq after a read on address 1111 until next frame arrives. process(clk) begin if clk'event and clk='1' then d0_recieved_r <= d0_recieved; d0_recieve_error_r <= d0_recieve_error; d0_revieved_data61_r <= d0_revieved_data(61); d1_recieved_r <= d1_recieved; d1_recieve_error_r <= d1_recieve_error; d1_revieved_data61_r <= d1_revieved_data(61); end if; end process; -- process(CLK_CPU, reset_n) begin if (reset_n = '0') then new_frame<='0'; d0_mask <= '0'; d1_mask <= '0'; status(0) <= '0'; status(1) <= '0'; status(2) <= '0'; status(4) <= '0'; status(5) <= '0'; status(6) <= '0'; elsif CLK_CPU'event and CLK_CPU='1' then status(0) <= d0_recieved_r and not d0_mask; status(1) <= d0_recieve_error_r and not d0_mask; status(2) <= d0_revieved_data61_r and not d0_mask; status(4) <= d1_recieved_r and not d1_mask; status(5) <= d1_recieve_error_r and not d1_mask; status(6) <= d1_revieved_data61_r and not d1_mask; if WE_i='1' and (address="0111" or address="0100") then d0_mask<='1'; elsif d0_recieved='0' then d0_mask<='0'; end if; if WE_i='1' and (address="1111" or address="1100") then d1_mask<='1'; elsif d1_recieved='0' then d1_mask<='0'; end if; -- ring 0 -- if d0_recieved='1' then status(0) <= '1'; -- elsif WE_i='1' and (address="0111" or address="0100") then status(0)<='0'; end if; -- -- if d0_recieve_error='1' then status(1) <= '1'; -- elsif WE_i='1' and (address="0111" or address="0100") then status(1)<='0'; end if; -- -- ring 1 -- if d1_recieved='1' then status(4) <= '1'; -- elsif WE_i='1' and (address="1111" or address="1100") then status(4)<='0'; end if; -- -- if d1_recieve_error='1' then status(5) <= '1'; -- elsif WE_i='1' and (address="1111" or address="1100") then status(5)<='0'; end if; -- -- IRQ -- if d0_recieved='1' or d1_recieved='1' then new_frame<='1'; -- elsif WE_i= '1' and (address(2 downto 0)="111" or address(2 downto 0)="100") then new_frame<='0'; -- end if; end if; end process; -- if data is written to address 0100/1100 start sending. process(CLK_CPU, current_state0,reset_n) begin if (reset_n = '0') then new_data0<='0'; elsif current_state0 /= idle then new_data0<='0'; elsif CLK_CPU'event and CLK_CPU='1' then -- writing to the mcmaddr starts sending if WE_i='1' and address="0100" then new_data0<='1'; end if; end if; end process; process(CLK_CPU, current_state1,reset_n) begin if (reset_n = '0') then new_data1<='0'; elsif current_state1 /= idle then new_data1<='0'; elsif CLK_CPU'event and CLK_CPU='1' then -- writing to the mcmaddr starts sending if WE_i='1' and address="1100" then new_data1<='1'; end if; end if; end process; ------------------------------------------------------------ -- -- state machines. -- communication to dll is handled here. -- pc: process(clk,reset_n) begin if reset_n = '0' then current_state0 <= idle; current_state1 <= idle; elsif ( clk'event and clk = '1') then current_state0 <= next_state0; current_state1 <= next_state1; end if; end process pc; nextstate1: process (current_state1,d1_buffer_ready,new_data1) begin next_state1 <= current_state1; case current_state1 is when idle => if (new_data1 = '1') then next_state1 <= start_send; end if; when start_send => if ( d1_buffer_ready = '0') then next_state1 <= wait_for_send_to_finish; end if; when wait_for_send_to_finish => if ( d1_buffer_ready = '1') then next_state1 <= idle; end if; end case; end process nextstate1; setoutput1: process(current_state1) begin case current_state1 is when idle => d1_send_start <= '0'; when start_send => d1_send_start <= '1'; when wait_for_send_to_finish => d1_send_start <= '0'; end case; end process setoutput1; nextstate0: process (current_state0,d0_buffer_ready,new_data0) begin next_state0 <= current_state0; case current_state0 is when idle => if (new_data0 = '1') then next_state0 <= start_send; end if; when start_send => if ( d0_buffer_ready = '0') then next_state0 <= wait_for_send_to_finish; end if; when wait_for_send_to_finish => if ( d0_buffer_ready = '1') then next_state0 <= idle; end if; end case; end process nextstate0; setoutput0: process(current_state0) begin case current_state0 is when idle => d0_send_start <= '0'; when start_send => d0_send_start <= '1'; when wait_for_send_to_finish => d0_send_start <= '0'; end case; end process setoutput0; end structural; -------------------------------------------------- -- CONFIGURATION -------------------------------------------------- -- synopsys translate_off CONFIGURATION mcm_excalibur_simulator_CFG of mcm_excalibur_simulator is for structural for ALL : mcm_nw_dll use configuration WORK.mcm_nw_dll_CFG; end for; for ALL : mcm_nw_pl use configuration WORK.mcm_nw_pl_CFG; end for; end for; end mcm_excalibur_simulator_CFG; -- synopsys translate_on