wtr
Full Member level 5
Hello all,
Basically in simulation land the following works. However the question is can an FPGA handle tristating internally, because on hardware I've just bricked the device.
OVERSEER takes response from peripherals and sends response to master. If the system times out then dtackb is set to mirror the csb & subsequently the bus acknowledges a response and fails "gracefully"
Here is an example of the version registers, whereby if the address is within range then it response otherwise the dtackb is left in tristate 'Z'.
Basically in simulation land the following works. However the question is can an FPGA handle tristating internally, because on hardware I've just bricked the device.
OVERSEER takes response from peripherals and sends response to master. If the system times out then dtackb is set to mirror the csb & subsequently the bus acknowledges a response and fails "gracefully"
Code VHDL - [expand] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 -- Description : This block will forward the pcie -> csif command onto the rest of the system. -- However it shall forward a response after a watchdog timer & it shall only allow addresses -- within the range allowed library ieee; use ieee.std_logic_1164.all; library universal_lib; library xil_defaultlib; entity local_bus_overseer is port ( sys_clk : in std_logic; reset : in std_logic; MGT_CSb : in Std_Logic; MGT_ADD : in Std_Logic_Vector(31 downto 0); MGT_DATA_IN : in Std_Logic_Vector(31 downto 0); MGT_DATA_OUT : out Std_Logic_Vector(31 downto 0); MGT_writeb : in Std_Logic; MGT_DTACKb : out Std_Logic; lb_CSb : out std_logic; lb_ADDRESS : out Std_Logic_Vector(31 downto 0); lb_DATA_IN : out Std_Logic_Vector(31 downto 0); lb_DATA_out : in Std_Logic_Vector(31 downto 0); lb_WRITEb : out Std_Logic; lb_dtackb : in std_logic ); end entity local_bus_overseer; architecture rtl of local_bus_overseer is type fsm_t is (idle, transfer, timeout_trig); signal fsm : fsm_t; signal MGT_CSb_reg : Std_Logic; signal MGT_ADD_reg : Std_Logic_Vector(31 downto 0); signal MGT_DATA_IN_reg : Std_Logic_Vector(31 downto 0); signal MGT_DATA_OUT_reg : Std_Logic_Vector(31 downto 0); signal MGT_writeb_reg : Std_Logic; signal MGT_DTACKb_reg : Std_Logic; signal timer_reset : std_logic; signal timer_go : std_logic; signal timeout : std_logic; signal mux_ctrl : std_logic; signal fsm_slv : std_logic_vector(1 downto 0); COMPONENT overseer_ila PORT ( clk : IN STD_LOGIC; probe0 : IN STD_LOGIC_VECTOR(1 DOWNTO 0); probe1 : IN STD_LOGIC_VECTOR(0 DOWNTO 0); probe2 : IN STD_LOGIC_VECTOR(0 DOWNTO 0); probe3 : IN STD_LOGIC_VECTOR(0 DOWNTO 0); probe4 : IN STD_LOGIC_VECTOR(0 DOWNTO 0); probe5 : IN STD_LOGIC_VECTOR(0 DOWNTO 0); probe6 : IN STD_LOGIC_VECTOR(31 DOWNTO 0) ); END COMPONENT ; begin --wait for 100 us u_timer : entity universal_lib.delay_timer generic map ( delay_unit => 1 us, clk_period => 8 ns ) port map ( clk => sys_clk, rst => timer_reset, time_delay => 10, start_delay => timer_go, timer_complete => timeout ); reg : process(sys_clk) is begin if rising_edge(sys_clk) then if reset='1' then MGT_CSb_reg <= '1'; MGT_ADD_reg <= (others => '0'); MGT_DATA_IN_reg <= (others => '0'); MGT_DATA_OUT_reg <= (others => '0'); MGT_writeb_reg <= '1'; MGT_DTACKb_reg <= '1'; else MGT_CSb_reg <= MGT_CSb; MGT_ADD_reg <= MGT_ADD; MGT_DATA_IN_reg <= MGT_DATA_IN; MGT_writeb_reg <= MGT_writeb; for i in MGT_DATA_OUT_reg'range loop if lb_DATA_out(i) = 'Z' then MGT_DATA_OUT_reg(I) <= '1'; else MGT_DATA_OUT_reg(i) <= lb_DATA_out(i); end if; end loop; if lb_dtackb /= '0' then MGT_DTACKb_reg <= '1'; else MGT_DTACKb_reg <= lb_dtackb; end if; end if; end if; end process; ctrl : process(sys_clk) is begin if rising_edge(sys_clk) then if reset='1' then timer_reset <= '1'; fsm <= idle; timer_go <= '0'; mux_ctrl <= '0'; fsm_slv <= "00"; else timer_go <= '0'; mux_ctrl <= '0'; case fsm is when idle => fsm_slv <= "01"; timer_reset <= '1'; -- csb_trig if MGT_CSb='0' and MGT_CSb_reg='1' then timer_reset <= '0'; fsm <= transfer; timer_go <= '1'; end if; when transfer => -- dtackb returned fsm_slv <= "10"; if lb_dtackb = '0' and MGT_DTACKb_reg='1' then fsm <= idle; timer_reset <= '1'; end if; if timeout = '1' then fsm <= timeout_trig; end if; when timeout_trig => -- fail gracefully fsm_slv <= "11"; mux_ctrl <= '1'; if MGT_CSb='1' and MGT_CSb_reg='0' then fsm <= idle; end if; when others => fsm <= timeout_trig; end case; end if; end if; end process; MGT_DATA_OUT <= MGT_data_out_reg when mux_ctrl='0' else x"DEADFEED"; --bad5ec for blocks inside MGT_DTACKb <= MGT_dtackb_reg when mux_ctrl='0' else MGT_CSb_reg; --MGT_bresp <= "00" when mux_ctrl='0' else "10"; --MGT_rresp <= "00" when mux_ctrl='0' else "10"; lb_CSb <= MGT_CSb_reg when mux_ctrl='0' else '1'; lb_ADDRESS <= MGT_ADD_reg when mux_ctrl='0' else (others => '0'); lb_DATA_IN <= MGT_DATA_IN_reg when mux_ctrl='0' else (others => '0'); lb_WRITEb <= MGT_WRITEb_reg when mux_ctrl='0' else '1'; u_ila : overseer_ila port map ( clk => sys_clk, probe0 => fsm_slv, probe1(0) => mux_ctrl, probe2(0) => timer_go, probe3(0) => timeout, probe4(0) => timer_reset, probe5(0) => lb_dtackb, probe6 => lb_DATA_out ); end architecture;
Here is an example of the version registers, whereby if the address is within range then it response otherwise the dtackb is left in tristate 'Z'.
Code VHDL - [expand] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 library ieee; use ieee.std_logic_1164.all; Library CONFIGURATION_lib; Use CONFIGURATION_lib.Local_Bus_Configuration.ALL; entity version_reg is generic ( lower_address : std_logic_vector(31 downto 0) := x"00000100"; upper_address : std_logic_vector(31 downto 0) := x"000001A0" ); port ( clk : in std_logic; reset : in std_logic; writeb : in std_logic; csb : in std_logic; address : in std_logic_vector(31 downto 0); data_out : out std_logic_vector(31 downto 0); dtackb : out std_logic ); end entity version_reg; architecture rtl of version_reg is signal general_read_data : std_logic_vector(31 downto 0); --Signal PART_NO_VALUE : Std_Logic_Vector(15 downto 0); --Signal ISSUE_VALUE : Std_Logic_Vector(15 downto 0); Signal COMPILE_YEAR_VALUE : Std_Logic_Vector(15 downto 0); Signal COMPILE_DAY_VALUE : Std_Logic_Vector(15 downto 0); Signal COMPILE_TIME_VALUE : Std_Logic_Vector(15 downto 0); Signal COMPILE_TOOL_VALUE : Std_Logic_Vector(15 downto 0); signal dtackb_int : std_logic; begin dtackb <= dtackb_int when address >= lower_address and address <= upper_address else 'Z'; data_out <= general_read_data when address >= lower_address and address <= upper_address else (others => 'Z'); --PART_NUMBER_LOWER <= PART_NUMBER(5 to 5); --PART_NO_VALUE <= conv_hex_to_std(PART_NUMBER(1 to 4)); --ISSUE_VALUE(15 downto 12) <= conv_hex_to_std(PART_NUMBER_LOWER); --ISSUE_VALUE(11 downto 8) <= (Others => '0'); --ISSUE_VALUE( 7 downto 0) <= conv_alpha_to_std(ISSUE); COMPILE_YEAR_VALUE <= x"2019"; COMPILE_DAY_VALUE(15 downto 8) <= x"10"; COMPILE_DAY_VALUE( 7 downto 0) <= x"07"; COMPILE_TIME_VALUE(15 downto 8) <= x"16"; COMPILE_TIME_VALUE( 7 downto 0) <= x"20"; COMPILE_TOOL_VALUE <= x"7E28"; reg_proc : process(clk) is begin if rising_edge(clk) then if reset = '1' then dtackb_int <= '1'; general_read_data <= (others => '0'); else dtackb_int <= '1'; general_read_data <= (others => '0'); if address >= lower_address and address <= upper_address then if csb = '0' then Case ADDRESS(GENERAL_ADDR_RANGE) is --When PART_NO_UPPER_ADDR => GENERAL_READ_DATA(15 downto 0) <= PART_NO_VALUE; dtackb_int <= '0'; --When PART_NO_LOWER_ADDR => GENERAL_READ_DATA(15 downto 0) <= ISSUE_VALUE; dtackb_int <= '0'; When COMP_YEAR_ADDR => GENERAL_READ_DATA(15 downto 0) <= COMPILE_YEAR_VALUE; dtackb_int <= '0'; When COMP_DAY_ADDR => GENERAL_READ_DATA(15 downto 0) <= COMPILE_DAY_VALUE; dtackb_int <= '0'; When COMP_HOUR_ADDR => GENERAL_READ_DATA(15 downto 0) <= COMPILE_TIME_VALUE; dtackb_int <= '0'; When COMP_TOOL_ADDR => GENERAL_READ_DATA(15 downto 0) <= COMPILE_TOOL_VALUE; dtackb_int <= '0'; when others => GENERAL_READ_DATA <= x"bad0" & lower_address(31 downto 16); dtackb_int <= '0'; end case; end if; end if; end if; end if; end process; end architecture rtl;