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.

236 lines
7.2 KiB

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