Library of reusable VHDL components
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

252 lines
7.8 KiB

  1. -- Copyright (c) 2014 - 2022 by Torsten Meissner
  2. --
  3. -- Licensed under the Apache License, Version 2.0 (the "License");
  4. -- you may not use this file except in compliance with the License.
  5. -- You may obtain a copy of the License at
  6. --
  7. -- https://www.apache.org/licenses/LICENSE-2.0
  8. --
  9. -- Unless required by applicable law or agreed to in writing, software
  10. -- distributed under the License is distributed on an "AS IS" BASIS,
  11. -- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. -- See the License for the specific language governing permissions and
  13. -- limitations under the License.
  14. library ieee;
  15. use ieee.std_logic_1164.all;
  16. use ieee.numeric_std.all;
  17. entity WishBoneSlaveE is
  18. generic (
  19. Formal : boolean := false;
  20. Simulation : boolean := false;
  21. AddressWidth : natural := 32;
  22. DataWidth : natural := 32
  23. );
  24. port (
  25. --+ wishbone system if
  26. WbRst_i : in std_logic;
  27. WbClk_i : in std_logic;
  28. --+ wishbone inputs
  29. WbCyc_i : in std_logic;
  30. WbStb_i : in std_logic;
  31. WbWe_i : in std_logic;
  32. WbAdr_i : in std_logic_vector(AddressWidth-1 downto 0);
  33. WbDat_i : in std_logic_vector(DataWidth-1 downto 0);
  34. --+ wishbone outputs
  35. WbDat_o : out std_logic_vector(DataWidth-1 downto 0);
  36. WbAck_o : out std_logic;
  37. WbErr_o : out std_logic;
  38. --+ local register if
  39. LocalWen_o : out std_logic;
  40. LocalRen_o : out std_logic;
  41. LocalAdress_o : out std_logic_vector(AddressWidth-1 downto 0);
  42. LocalData_o : out std_logic_vector(DataWidth-1 downto 0);
  43. LocalData_i : in std_logic_vector(DataWidth-1 downto 0)
  44. );
  45. end entity WishBoneSlaveE;
  46. architecture rtl of WishBoneSlaveE is
  47. type t_wb_slave_fsm is (IDLE, ADDRESS, DATA);
  48. signal s_wb_slave_fsm : t_wb_slave_fsm;
  49. signal s_wb_active : boolean;
  50. begin
  51. WbSlaveControlP : process (WbClk_i) is
  52. begin
  53. if (rising_edge(WbClk_i)) then
  54. if (WbRst_i = '1') then
  55. s_wb_slave_fsm <= IDLE;
  56. else
  57. WbReadC : case s_wb_slave_fsm is
  58. when IDLE =>
  59. s_wb_slave_fsm <= ADDRESS;
  60. when ADDRESS =>
  61. if (s_wb_active and WbWe_i = '0') then
  62. s_wb_slave_fsm <= DATA;
  63. end if;
  64. when DATA =>
  65. s_wb_slave_fsm <= ADDRESS;
  66. when others =>
  67. s_wb_slave_fsm <= IDLE;
  68. end case;
  69. end if;
  70. end if;
  71. end process WbSlaveControlP;
  72. s_wb_active <= true when s_wb_slave_fsm /= IDLE and WbCyc_i = '1' and WbStb_i = '1' else false;
  73. --+ local register if outputs
  74. LocalWen_o <= WbWe_i when s_wb_slave_fsm = ADDRESS and s_wb_active else '0';
  75. LocalRen_o <= not(WbWe_i) when s_wb_slave_fsm = ADDRESS and s_wb_active else '0';
  76. LocalAdress_o <= WbAdr_i when s_wb_slave_fsm /= IDLE and s_wb_active else (others => '0');
  77. LocalData_o <= WbDat_i when s_wb_slave_fsm = ADDRESS and s_wb_active and WbWe_i = '1' else (others => '0');
  78. --+ wishbone if outputs
  79. WbDat_o <= LocalData_i when s_wb_slave_fsm = DATA and WbWe_i = '0' else (others => '0');
  80. WbAck_o <= '1' when (s_wb_slave_fsm = DATA and WbWe_i = '0') or (s_wb_slave_fsm = ADDRESS and s_wb_active and WbWe_i = '1') else '0';
  81. WbErr_o <= '1' when s_wb_slave_fsm = DATA and WbWe_i = '1' else '0';
  82. default clock is rising_edge(WbClk_i);
  83. FormalG : if Formal generate
  84. -- Glue logic
  85. signal s_wb_data : std_logic_vector(DataWidth-1 downto 0);
  86. signal s_wb_address : std_logic_vector(AddressWidth-1 downto 0);
  87. begin
  88. SyncWbSignals : process is
  89. begin
  90. wait until rising_edge(WbClk_i);
  91. if (s_wb_slave_fsm = ADDRESS and WbCyc_i = '1' and WbStb_i = '1') then
  92. if (WbWe_i = '1') then
  93. s_wb_data <= WbDat_i;
  94. end if;
  95. s_wb_address <= WbAdr_i;
  96. end if;
  97. end process SyncWbSignals;
  98. restrict {WbRst_i = '1'; WbRst_i = '0'[+]}[*1];
  99. assume always WbCyc_i = WbStb_i;
  100. assume always WbWe_i -> WbStb_i;
  101. assume always WbWe_i and WbAck_o -> next not WbWe_i;
  102. -- FSM state checks
  103. FSM_IDLE_TO_ADDRESS : assert always
  104. not WbRst_i and s_wb_slave_fsm = IDLE ->
  105. next s_wb_slave_fsm = ADDRESS abort WbRst_i;
  106. FSM_ADDRESS_TO_DATA : assert always
  107. not WbRst_i and s_wb_slave_fsm = ADDRESS and WbStb_i and WbCyc_i and not WbWe_i ->
  108. next s_wb_slave_fsm = DATA abort WbRst_i;
  109. FSM_ADDRESS_TO_ADDRESS : assert always
  110. not WbRst_i and s_wb_slave_fsm = ADDRESS and not (WbStb_i and WbCyc_i and not WbWe_i) ->
  111. next s_wb_slave_fsm = ADDRESS abort WbRst_i;
  112. FSM_DATA_TO_ADDRESS : assert always
  113. not WbRst_i and s_wb_slave_fsm = DATA ->
  114. next s_wb_slave_fsm = ADDRESS abort WbRst_i;
  115. -- Wishbone write cycle checks
  116. WB_WRITE_CYCLE_0 : assert always
  117. s_wb_slave_fsm = ADDRESS and WbStb_i and WbCyc_i and WbWe_i ->
  118. LocalWen_o and WbAck_o;
  119. WB_WRITE_CYCLE_1 : assert always
  120. LocalWen_o -> LocalAdress_o = WbAdr_i;
  121. WB_WRITE_CYCLE_2 : assert always
  122. LocalWen_o -> LocalData_o = WbDat_i;
  123. -- Wishbone read cycle checks
  124. WB_READ_CYCLE_0 : assert always
  125. s_wb_slave_fsm = ADDRESS and WbStb_i and WbCyc_i and not WbWe_i ->
  126. LocalRen_o and not WbAck_o;
  127. WB_READ_CYCLE_1 : assert always
  128. LocalRen_o -> LocalAdress_o = WbAdr_i;
  129. WB_READ_CYCLE_2 : assert always
  130. s_wb_slave_fsm = DATA and not WbWe_i ->
  131. WbAck_o and WbDat_o = LocalData_i;
  132. WB_READ_ERROR : assert always
  133. s_wb_slave_fsm = DATA and WbWe_i ->
  134. WbErr_o;
  135. WB_NEVER_ACK_AND_ERR : assert never
  136. WbAck_o and WbErr_o;
  137. WB_ERR : assert always
  138. WbErr_o ->
  139. (WbCyc_i and WbStb_i)
  140. report "PSL ERROR: WbErr invalid";
  141. LOCAL_WE : assert always
  142. LocalWen_o ->
  143. (WbCyc_i and WbStb_i and WbWe_i and not LocalRen_o) and
  144. (next not LocalWen_o)
  145. report "PSL ERROR: LocalWen invalid";
  146. LOCAL_RE : assert always
  147. LocalRen_o ->
  148. (WbCyc_i and WbStb_i and not WbWe_i and not LocalWen_o) and
  149. (next not LocalRen_o)
  150. report "PSL ERROR: LocalRen invalid";
  151. RESET : assert always
  152. WbRst_i -> next
  153. (to_integer(unsigned(WbDat_o)) = 0 and WbAck_o = '0' and WbErr_o = '0' and
  154. LocalWen_o = '0' and LocalRen_o = '0' and to_integer(unsigned(LocalAdress_o)) = 0 and to_integer(unsigned(LocalData_o)) = 0)
  155. report "PSL ERROR: Reset error";
  156. end generate FormalG;
  157. SimulationG : if Simulation generate
  158. LOCAL_WRITE : assert always
  159. ((WbCyc_i and WbStb_i and WbWe_i) ->
  160. (LocalWen_o = '1' and WbAck_o = '1' and LocalAdress_o = WbAdr_i and LocalData_o = WbDat_i)) abort WbRst_i
  161. report "PSL ERROR: Local write error";
  162. LOCAL_READ : assert always
  163. ({not(WbCyc_i) and not(WbStb_i); WbCyc_i and WbStb_i and not(WbWe_i)} |->
  164. {LocalRen_o = '1' and LocalAdress_o = WbAdr_i and WbAck_o = '0'; LocalRen_o = '0' and WbDat_o = LocalData_i and WbAck_o = '1'}) abort WbRst_i
  165. report "PSL ERROR: Local read error";
  166. WB_ACK : assert always
  167. WbAck_o ->
  168. (WbCyc_i and WbStb_i)
  169. report "PSL ERROR: WbAck invalid";
  170. WB_ERR : assert always
  171. WbErr_o ->
  172. (WbCyc_i and WbStb_i)
  173. report "PSL ERROR: WbErr invalid";
  174. LOCAL_WE : assert always
  175. LocalWen_o ->
  176. (WbCyc_i and WbStb_i and WbWe_i and not(LocalRen_o)) and
  177. (next not(LocalWen_o))
  178. report "PSL ERROR: LocalWen invalid";
  179. LOCAL_RE : assert always
  180. LocalRen_o ->
  181. (WbCyc_i and WbStb_i and not(WbWe_i) and not(LocalWen_o)) and
  182. (next not(LocalRen_o))
  183. report "PSL ERROR: LocalRen invalid";
  184. RESET : assert always
  185. WbRst_i ->
  186. (to_integer(unsigned(WbDat_o)) = 0 and WbAck_o = '0' and WbErr_o = '0' and
  187. LocalWen_o = '0' and LocalRen_o = '0' and to_integer(unsigned(LocalAdress_o)) = 0 and to_integer(unsigned(LocalData_o)) = 0)
  188. report "PSL ERROR: Reset error";
  189. end generate SimulationG;
  190. end architecture rtl;