-- -- Transition Radiation Detector -- -- MCM Control Unit - Configuration Network -- -- -- -- $Id$ -- -- Robin Gareus, Kirchhoff Institute for Physics, Heidelberg -- rgareus@kip.uni-heidelberg.de -- ------------------------------------------------------------ -- -- Application Layer -- -- in here the data part of the frame is beeing processed. -- the command,address and data extracted. -- The commands are parsed... (also the bridge command is processed here) -- A bus transaction may be issued ... -- ...and the answer-frames are generated, if needed. -- -- This is also the interface to the I/O. -- -- The interfaces are described in detail in -- .../report_2/main.ps -- -- here's a summary of the signals: -- request : data to be processed and executed -- request_valid: strobe like signal. is '1' as long as 'request' contains -- : valid data. -- reply : to be filled in - when finished executing the command -- reply_valid : set this to '1' when reply is valid and then wait -- : until request becomes invalid. -- altered_frame: set this to '1' if the frame to send is an answer/reply -- : if (reply /= request) - see .../report_2/main.ps -- bridge_alter : request the bridge state to be set to 'bridge_mode' -- bridge_mode : mode to set bridge to when bridge_alter = '1' -- : 0: serial mode ; 1: bridged/crossed mode -- cfg_req : request Power on from the Global-State-Machine -- cfg_ack : System Powered on. (high active) -- -- This interface acts as a bus-master, so every read and write to -- the bus will always suceed in 1 clock cycle. -- description of the bus can be found in the documentation. -- -- bus_addr : the address to read/write -- bus_dout : data to write -- bus_din : read data -- bus_req : request the bus -- bus_we : if the bus is requested, this is the write enable -- : if set to '0' a read is executed. -- -- -- State Machine: -- idle : wait for incoming request, and then enter appropriate state. -- : according to command to be executed. -- gsm_req : request configuration mode from GlobalStateMachine (GSM) -- bridge : bridge command recieved. set bridge request lines and -- : wait until request becomes invalid. (*reply*) -- read : execute read request on global I/O. Then go to read_hold_data -- read_hold_data: hold read data until request becomes invalid. (*reply*) -- write : execute write request on global I/O. Then go to noop -- noop : wait until request becomes invalid. (*forward*) -- read_broadcast: execute read request on gI/O. if bit(0) of read data -- : is 1 act as if this was a read, else go into noop. -- err : reply error command (in valid frame -- this is no -- : error frame and is currently only sent when an -- : unknown/undefined command is requested). (*reply*) -------------------------------------------------- -- standard includes, library definitions. -------------------------------------------------- library ieee,work; use ieee.std_logic_1164.all; use IEEE.std_logic_unsigned.all; -------------------------------------------------- -- ENTITY -------------------------------------------------- entity mcm_nw_apl is port( -- Signals from Network Layer request : in std_logic_vector(52 downto 0); request_valid : in std_logic; -- Signals to Network Layer reply : out std_logic_vector(52 downto 0); reply_valid : out std_logic; altered_frame : out std_logic; bridge_alter : out std_logic; bridge_mode : out std_logic; -- Bus interface bus_addr : out std_logic_vector(15 downto 0); bus_dout : out std_logic_vector(31 downto 0); bus_din : in std_logic_vector(31 downto 0); bus_req : out std_logic; bus_we : out std_logic; bus_ack : in std_logic; -- dp -- cfg_req : out std_logic; -- dp -- cfg_ack : in std_logic; -- Modif -- rq_cmd_out : out std_logic_vector(3 downto 0); -- this port added by Deyan Atanasov on 28.03.03 -- since the OASE ACT Interface needs to know what kind of transaction -- is schedulled upon cfg_req assertion chipRST_n: out std_logic; reset_n : in std_logic; clk : in std_logic ); end mcm_nw_apl; -------------------------------------------------- -- ARCHITECTURE -------------------------------------------------- architecture structural of mcm_nw_apl is -------------------------------------------------- -- internal signals -------------------------------------------------- subtype state_type is std_logic_vector(3 downto 0); constant idle : state_type := "0000"; constant gsm_req : state_type := "0001"; constant bridge : state_type := "0010"; constant read : state_type := "0011"; constant read_hold_data : state_type := "0100"; constant write : state_type := "0101"; constant noop : state_type := "0110"; constant read_broadcast : state_type := "0111"; constant err : state_type := "1000"; constant cycle : state_type := "1001"; constant reset : state_type := "1011"; constant l_prewrite : state_type := "1100"; constant l_postwrite : state_type := "1110"; constant request_bus : state_type := "1111"; SIGNAL current_state,next_state : state_type; SIGNAL answer : std_logic; SIGNAL bridge_alt : std_logic; SIGNAL rq_cmd,ry_cmd : std_logic_vector(3 downto 0); SIGNAL rq_addr,ry_addr : std_logic_vector(16 downto 0); SIGNAL rq_data,ry_data : std_logic_vector(31 downto 0); SIGNAL read_data : std_logic_vector(31 downto 0); SIGNAL long_transaction : std_logic; SIGNAL waitcount : std_logic_vector (5 downto 0); -- dp signal current_state_dp : std_logic_vector(2 downto 0) := "001"; signal next_state_dp : std_logic_vector(2 downto 0); constant idle_dp : std_logic_vector(2 downto 0) := "001"; constant assert_va : std_logic_vector(2 downto 0) := "010"; constant deassert_va : std_logic_vector(2 downto 0) := "100"; signal req_rise : std_logic; signal req_fall : std_logic; signal req_reg : std_logic; signal cfg_req : std_logic; -- dp signal cfg_ack : std_logic; signal ack_oase : std_logic; signal valid_oase : std_logic; signal rd_wr_oase : std_logic; signal bus_req_intrnl : std_logic; signal bus_we_intrnl : std_logic; -------------------------------------------------- -- components -------------------------------------------------- COMPONENT hamm_reg generic(Nbits : Integer := 4; Init_value : Integer := 0); port (clk, rst_n : in std_logic; data_in : in std_logic_vector(Nbits-1 downto 0); data_out : out std_logic_vector(Nbits-1 downto 0) ); END COMPONENT; -------------------------------------------------- -- processes -------------------------------------------------- begin -- calucate next state of state-machine -- the command decoding is also done here -- by selecting the state to enter depending on the request... nextstate: process ( current_state,request_valid,rq_cmd,bus_din,cfg_ack,waitcount,long_transaction) begin next_state <= current_state; case current_state is when idle => if (request_valid = '1') then case rq_cmd is when "0010" => next_state <= bridge; when "1010" => next_state <= cycle; when "1110" => next_state <= noop; when "0110" => next_state <= reset; when "1000" => next_state <= request_bus; -- read when "0100" => next_state <= request_bus; -- write when "1100" => next_state <= request_bus; -- read broadcast when "1001" => next_state <= gsm_req; -- read w/req when "0101" => next_state <= gsm_req; -- write w/req when "1101" => next_state <= gsm_req; -- read broadcast w/req when OTHERS => next_state <= err; end case; end if; when gsm_req => if (request_valid = '0') then next_state <= err; elsif (cfg_ack = '1') then next_state <= request_bus; end if; when request_bus => if (request_valid = '0') then next_state <= err; else case rq_cmd is when "1000" => next_state <= read; when "0100" => next_state <= write; when "1100" => next_state <= read_broadcast; when "1001" => next_state <= read; when "0101" => next_state <= write; when "1101" => next_state <= read_broadcast; when OTHERS => next_state <= err; end case; end if; when bridge => if (request_valid = '0') then next_state <= idle; end if; when cycle => next_state <= noop; when reset => next_state <= noop; when write => if ( long_transaction = '1' and waitcount > "000000") then next_state <= write; elsif( long_transaction = '1') then next_state <= l_postwrite; else next_state <= noop; end if; when l_postwrite => next_state <= noop; when read => if ( long_transaction = '1' and waitcount > "000000") then next_state <= read; else next_state <= read_hold_data; end if; when read_broadcast => if ( long_transaction = '1' and waitcount > "000000") then next_state <= read_broadcast; elsif ( bus_din(0) = '1') then next_state <= read_hold_data; else next_state <= noop; end if; when read_hold_data => if (request_valid = '0') then next_state <= idle; end if; when noop => if (request_valid = '0') then next_state <= idle; end if; when err => if (request_valid = '0') then next_state <= idle; end if; when OTHERS => next_state <= idle; -- THIS SHOULD NEVER HAPPEN! end case; end process nextstate; -- assign next state h1: hamm_reg generic map(Nbits => 4, Init_value => 0) port map ( clk => clk, rst_n => reset_n, data_in => next_state, data_out => current_state); -- set long or short bus transaction cycle -- also remember cfg_req to get rid of 6 additional read/write/r_brcast states transaction_length:process (clk,reset_n) begin if (reset_n = '0') then long_transaction <= '0'; cfg_req<='0'; chipRST_n <= '1'; -- check! elsif (clk'event and clk='1') then if (current_state = cycle) then long_transaction <= request(31); end if; if (current_state = reset) then chipRST_n <= '0'; else chipRST_n <= '1'; end if; if (current_state = idle or current_state = noop or current_state = read_hold_data ) then cfg_req<='0'; elsif (current_state = gsm_req) then cfg_req<='1'; end if; end if; end process transaction_length; -- set signals to global bus according to state and request-data globalbus: process( current_state,reset_n,rq_data,rq_addr,long_transaction) begin bus_addr <= rq_addr(15 downto 0); -- Modified by Deyan Atanasov; originally: (OTHERS => '-'); -- check if this is good for long tranaction - when bus req is still on! bus_dout <= rq_data; -- Modified by Deyan Atanasov; originally:(OTHERS => '-'); bus_req_intrnl <= '0'; --dp bus_we_intrnl <= '0'; --dp case current_state is when read => bus_addr <= rq_addr(15 downto 0); bus_req_intrnl <= long_transaction;--dp when read_broadcast => bus_addr <= rq_addr(15 downto 0); bus_req_intrnl <= '0';--dp when write => bus_addr <= rq_addr(15 downto 0); bus_dout <= rq_data; bus_req_intrnl <= long_transaction; bus_we_intrnl <= '1'; when l_postwrite => bus_addr <= rq_addr(15 downto 0); bus_dout <= rq_data; bus_req_intrnl <= '0'; -- check , but should be ok. when request_bus => bus_req_intrnl <= '1'; -- request bus for next cycle. when OTHERS => NULL; end case; end process globalbus; -- buffer the data from a global I/O read_request -- The data of the GIO will be valid for only one clock cycle -- our reply has to be valid, until data is written in the output-buffer -- So we have to introduce 32 DFF here :) read_data_buffer: process (clk,reset_n) begin if reset_n = '0' then read_data <= (OTHERS => '-'); waitcount <= (others => '0'); elsif ( clk'event and clk = '1') then if (current_state = read or current_state = read_broadcast) then read_data <= bus_din; end if; if (current_state = request_bus and long_transaction = '1') then waitcount <= "001000"; elsif ((current_state = read or current_state = read_broadcast or current_state = write) and waitcount > "000000") then waitcount <= waitcount - 1; end if; end if; end process read_data_buffer; -- Set output valued to NWL here setoutput: process( current_state,reset_n, rq_cmd,rq_addr,rq_data,read_data) begin case current_state is when bridge => bridge_alt <= '1'; reply_valid <= '1'; answer <= '1'; ry_cmd <= rq_cmd; ry_addr <= rq_addr; ry_data <= rq_data; when noop => bridge_alt <= '0'; reply_valid <= '1'; answer <= '0'; ry_cmd <= rq_cmd; ry_addr <= rq_addr; ry_data <= rq_data; when read_hold_data => bridge_alt <= '0'; reply_valid <= '1'; answer <= '1'; ry_cmd <= rq_cmd; ry_addr <= rq_addr; ry_data <= read_data; when err => bridge_alt <= '0'; reply_valid <= '1'; answer <= '1'; ry_cmd <= "1110"; -- internal ERROR. ry_addr <= (OTHERS => '0'); ry_data <= (OTHERS => '0'); when OTHERS => -- (idle,read,write) bridge_alt <= '0'; reply_valid <= '0'; answer <= '0'; ry_cmd <= (OTHERS => '-'); ry_addr <= (OTHERS => '-'); ry_data <= (OTHERS => '-'); end case; end process setoutput; -- just a play with signal-names and LSB,MSB convention, ... -- Bridge command : LSB(31) or MSB(0) bit defines the state of the -- bridge (0 serial, 1 bridged) bridge_mode <= request(31) when (bridge_alt= '1' and request_valid = '1') ELSE '-'; bridge_alter <= bridge_alt and request_valid; altered_frame <= answer; -- have we altered the frame here? -- reply or forward ? -- since we handle the commad internally, we dont have to convert LSB-MSB. rq_cmd <= request(52 downto 49); -- requested Command reply(52 downto 49) <= ry_cmd; -- replied command r0: for i in 0 to 16 generate rq_addr(i) <= request(48-i); -- Address reply(48-i) <= ry_addr(i); end generate; r1: for i in 0 to 31 generate rq_data(i) <= request(31-i); -- Data reply(31-i) <= ry_data(i); end generate; -- rq_cmd_out <= rq_cmd; -- dp valid_sync : process(clk, reset_n, next_state_dp) begin if (reset_n = '0') then current_state_dp <= idle_dp; elsif (clk = '1' and clk'event) then current_state_dp <= next_state_dp; end if; end process valid_sync; valid_sm : process(req_rise, bus_ack, current_state_dp) begin case current_state_dp is when idle_dp => if (req_rise = '1') then next_state_dp <= assert_va; ASSERT FALSE REPORT "Assert VALID to Bus Interface. Awaiting ACK..." SEVERITY NOTE; else next_state_dp <= idle_dp; end if; when assert_va => if (bus_ack = '1') then next_state_dp <= deassert_va; ASSERT FALSE REPORT "Received ACK from Bus Interface" SEVERITY NOTE; ASSERT ( rd_wr_oase = '1') REPORT "Performing Write to Bus" SEVERITY NOTE; ASSERT ( rd_wr_oase = '0') REPORT "Performing Read from Bus" SEVERITY NOTE; else next_state_dp <= assert_va; end if; when deassert_va => next_state_dp <= idle_dp; ASSERT FALSE REPORT "End of Cycle" SEVERITY NOTE; when others => next_state_dp <= idle_dp; ASSERT FALSE REPORT "Error in Valid-Acknowledge Protocol between MCM NIF and the Device being configured." SEVERITY ERROR; end case; end process valid_sm; valid_oase <= current_state_dp(1); -- assert_va cfg_ack <= bus_ack; bus_req <= valid_oase; cfg_edge_detect : process(clk) begin if (clk = '1' and clk'event) then req_reg <= cfg_req; end if; end process; req_rise <= cfg_req and (not req_reg); req_fall <= (not cfg_req) and req_reg; process(clk) begin if (clk = '1' and clk'event) then if (rq_cmd = "0101") then -- write with gsm req rd_wr_oase <= '0'; -- Write elsif (rq_cmd = "1001") then -- read with gsm req rd_wr_oase <= '1'; -- Read else rd_wr_oase <= '1'; end if; end if; end process; bus_we <= not rd_wr_oase; end structural; -------------------------------------------------- -- CONFIGURATION -------------------------------------------------- -- synopsys translate_off CONFIGURATION mcm_nw_apl_CFG of mcm_nw_apl is for structural end for; end mcm_nw_apl_CFG; -- synopsys translate_on