mem_sim.v 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190
  1. /*
  2. * mem_sim.v
  3. *
  4. * vim: ts=4 sw=4
  5. *
  6. * Copyright (C) 2020 Sylvain Munaut <tnt@246tNt.com>
  7. * All rights reserved.
  8. *
  9. * BSD 3-clause, see LICENSE.bsd
  10. *
  11. * Redistribution and use in source and binary forms, with or without
  12. * modification, are permitted provided that the following conditions are met:
  13. * * Redistributions of source code must retain the above copyright
  14. * notice, this list of conditions and the following disclaimer.
  15. * * Redistributions in binary form must reproduce the above copyright
  16. * notice, this list of conditions and the following disclaimer in the
  17. * documentation and/or other materials provided with the distribution.
  18. * * Neither the name of the <organization> nor the
  19. * names of its contributors may be used to endorse or promote products
  20. * derived from this software without specific prior written permission.
  21. *
  22. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
  23. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  24. * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  25. * DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
  26. * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  27. * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  28. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  29. * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  30. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  31. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  32. */
  33. `default_nettype none
  34. module mem_sim #(
  35. parameter INIT_FILE = "",
  36. parameter integer AW = 20,
  37. // auto
  38. parameter integer AL = AW - 1
  39. )(
  40. // Memory controller interface
  41. input wire [AL:0] mi_addr,
  42. input wire [ 6:0] mi_len,
  43. input wire mi_rw,
  44. input wire mi_valid,
  45. output wire mi_ready,
  46. input wire [31:0] mi_wdata,
  47. output wire mi_wack,
  48. output wire mi_wlast,
  49. output wire [31:0] mi_rdata,
  50. output wire mi_rstb,
  51. output wire mi_rlast,
  52. // Common
  53. input wire clk,
  54. input wire rst
  55. );
  56. localparam [1:0]
  57. ST_IDLE = 0,
  58. ST_WRITE = 2,
  59. ST_READ = 3;
  60. // Signals
  61. // -------
  62. // Memory array
  63. reg [31:0] mem[0:(1<<AW)-1];
  64. wire [19:0] mem_addr;
  65. wire [31:0] mem_wdata;
  66. reg [31:0] mem_rdata;
  67. wire mem_we;
  68. // FSM
  69. reg [1:0] state_cur;
  70. reg [1:0] state_nxt;
  71. // Command counters
  72. reg [19:0] cmd_addr;
  73. reg [ 7:0] cmd_len;
  74. wire cmd_last;
  75. // Memory
  76. // ------
  77. initial
  78. begin : mem_init
  79. integer a;
  80. if (INIT_FILE == "") begin
  81. for (a=0; a<(1<<20)-1; a=a+1)
  82. mem[a] = a;
  83. end else begin
  84. $readmemh(INIT_FILE, mem);
  85. end
  86. end
  87. always @(posedge clk)
  88. begin
  89. if (mem_we)
  90. mem[mem_addr] <= mem_wdata;
  91. mem_rdata <= mem[mem_addr];
  92. end
  93. // Main FSM
  94. // --------
  95. always @(posedge clk)
  96. if (rst)
  97. state_cur <= ST_IDLE;
  98. else
  99. state_cur <= state_nxt;
  100. always @(*)
  101. begin
  102. // Default is to stay put
  103. state_nxt = state_cur;
  104. // ... or not
  105. case (state_cur)
  106. ST_IDLE:
  107. if (mi_valid)
  108. state_nxt = mi_rw ? ST_READ : ST_WRITE;
  109. ST_READ:
  110. if (cmd_last)
  111. state_nxt = ST_IDLE;
  112. ST_WRITE:
  113. if (cmd_last)
  114. state_nxt = ST_IDLE;
  115. endcase
  116. end
  117. // Command channel
  118. // ---------------
  119. // Register command
  120. always @(posedge clk)
  121. begin
  122. if (state_cur == ST_IDLE) begin
  123. cmd_addr <= mi_addr;
  124. cmd_len <= { 1'b0, mi_len } - 1;
  125. end else begin
  126. cmd_addr <= cmd_addr + 1;
  127. cmd_len <= cmd_len - 1;
  128. end
  129. end
  130. assign cmd_last = cmd_len[7];
  131. // Ready ?
  132. assign mi_ready = (state_cur == ST_IDLE);
  133. // Mem access
  134. assign mem_addr = cmd_addr;
  135. // Write data channel
  136. // ------------------
  137. assign mem_wdata = mi_wdata;
  138. delay_bit #(2) dly_we( (state_cur == ST_WRITE), mem_we, clk );
  139. assign mi_wack = mem_we;
  140. delay_bit #(2) dly_wlast( cmd_last, mi_wlast, clk );
  141. // Read data channel
  142. // -----------------
  143. wire [31:0] mi_rdata_i;
  144. delay_bus #(5, 32) dly_rdata (mem_rdata, mi_rdata_i, clk);
  145. delay_bit #(6) dly_rstb ((state_cur == ST_READ), mi_rstb, clk);
  146. delay_bit #(6) dly_rlast ((state_cur == ST_READ) ? cmd_last : 1'bx, mi_rlast, clk);
  147. assign mi_rdata = mi_rstb ? mi_rdata_i : 32'hxxxxxxxx;
  148. endmodule