mem.vhd 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  1. library ieee;
  2. use ieee.std_logic_1164.all;
  3. use ieee.numeric_std.all;
  4. use work.core_pkg.all;
  5. use work.mem_pkg.all;
  6. use work.op_pkg.all;
  7. entity mem is
  8. port (
  9. clk : in std_logic;
  10. res_n : in std_logic;
  11. stall : in std_logic;
  12. flush : in std_logic;
  13. -- to Ctrl
  14. mem_busy : out std_logic;
  15. -- from EXEC
  16. mem_op : in mem_op_type;
  17. wbop_in : in wb_op_type;
  18. pc_new_in : in pc_type;
  19. pc_old_in : in pc_type;
  20. aluresult_in : in data_type;
  21. wrdata : in data_type;
  22. zero : in std_logic;
  23. -- to EXEC (forwarding)
  24. reg_write : out reg_write_type;
  25. -- to FETCH
  26. pc_new_out : out pc_type;
  27. pcsrc : out std_logic;
  28. -- to WB
  29. wbop_out : out wb_op_type;
  30. pc_old_out : out pc_type;
  31. aluresult_out : out data_type;
  32. memresult : out data_type;
  33. -- memory controller interface
  34. mem_out : out mem_out_type;
  35. mem_in : in mem_in_type;
  36. -- exceptions
  37. exc_load : out std_logic;
  38. exc_store : out std_logic
  39. );
  40. end entity;
  41. architecture rtl of mem is
  42. type internal_t is record
  43. memop : mem_op_type;
  44. wbop : wb_op_type;
  45. pc_new : pc_type;
  46. pc_old : pc_type;
  47. aluresult : data_type;
  48. wrdata : data_type;
  49. zero : std_logic;
  50. memresult : mem_data_type; --this is for critical path see sync process
  51. end record;
  52. signal internal : internal_t;
  53. constant INITIAL_INTERNAL : internal_t := (
  54. MEM_NOP,
  55. WB_NOP,
  56. (others => '0'),
  57. (others => '0'),
  58. (others => '0'),
  59. (others => '0'),
  60. '0',
  61. (others => '0')
  62. );
  63. begin
  64. -- structural
  65. memu_inst : entity work.memu
  66. port map (
  67. op => internal.memop.mem,
  68. A => internal.aluresult,
  69. W => internal.wrdata,
  70. R => memresult,
  71. B => mem_busy,
  72. XL => exc_load,
  73. XS => exc_store,
  74. D => mem_in,
  75. M => mem_out
  76. );
  77. -- concurrent
  78. pc_new_out <= internal.pc_new;
  79. pcsrc <= '1' when
  80. (internal.memop.branch = BR_BR) or
  81. (internal.memop.branch = BR_CND and internal.zero = '1') or
  82. (internal.memop.branch = BR_CNDI and internal.zero = '0')
  83. else '0';
  84. aluresult_out <= internal.aluresult;
  85. pc_old_out <= internal.pc_old;
  86. wbop_out <= internal.wbop when flush = '0' else WB_NOP;
  87. --fwd cntrl
  88. reg_write.write <= internal.wbop.write;
  89. reg_write.reg <= internal.wbop.rd;
  90. with internal.wbop.src select reg_write.data <=
  91. internal.aluresult when WBS_ALU,
  92. internal.memresult when WBS_MEM,
  93. std_logic_vector(x"00000000" + unsigned(internal.pc_old) + x"4") when WBS_OPC;
  94. -- synchronous
  95. sync : process(clk, res_n, stall)
  96. begin
  97. if res_n = '0' then
  98. internal <= INITIAL_INTERNAL;
  99. elsif stall = '0' and rising_edge(clk) then
  100. internal.memop <= mem_op;
  101. internal.wbop <= wbop_in;
  102. internal.pc_new <= pc_new_in;
  103. internal.pc_old <= pc_old_in;
  104. internal.aluresult <= aluresult_in;
  105. internal.wrdata <= wrdata;
  106. internal.zero <= zero;
  107. internal.memresult <= memresult; -- memresult gets registered every clock, this signal is used for for forwarding, this is no problem because on a load forward the pipeline is stalled for a cycle
  108. elsif stall = '1' and rising_edge(clk) then
  109. internal.memop.mem.memread <= '0';
  110. internal.memop.mem.memwrite <= '0';
  111. internal.memresult <= memresult;
  112. end if;
  113. end process;
  114. end architecture;