memtest.v 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
  1. /*
  2. * memtest.v
  3. *
  4. * vim: ts=4 sw=4
  5. *
  6. * Copyright (C) 2020-2021 Sylvain Munaut <tnt@246tNt.com>
  7. * SPDX-License-Identifier: CERN-OHL-P-2.0
  8. */
  9. `default_nettype none
  10. module memtest #(
  11. parameter integer ADDR_WIDTH = 32,
  12. // auto
  13. parameter integer AL = ADDR_WIDTH - 1
  14. )(
  15. // Memory interface
  16. output wire [AL:0] mi_addr,
  17. output wire [ 6:0] mi_len,
  18. output wire mi_rw,
  19. output wire mi_valid,
  20. input wire mi_ready,
  21. output wire [31:0] mi_wdata,
  22. output wire [ 3:0] mi_wmsk,
  23. input wire mi_wack,
  24. input wire [31:0] mi_rdata,
  25. input wire mi_rstb,
  26. // Wishbone interface
  27. input wire [31:0] wb_wdata,
  28. output wire [31:0] wb_rdata,
  29. input wire [ 8:0] wb_addr,
  30. input wire wb_we,
  31. input wire wb_cyc,
  32. output wire wb_ack,
  33. // Clock / Reset
  34. input wire clk,
  35. input wire rst
  36. );
  37. // Signals
  38. // -------
  39. // Buffers
  40. wire [ 7:0] bw_waddr;
  41. wire [31:0] bw_wdata;
  42. wire bw_wren;
  43. reg [ 7:0] bw_raddr;
  44. wire [31:0] bw_rdata;
  45. wire bw_rden;
  46. reg [ 7:0] br_waddr;
  47. wire [31:0] br_wdata;
  48. wire br_wren;
  49. wire [ 7:0] br_raddr;
  50. wire [31:0] br_rdata;
  51. wire br_rden;
  52. // Wishbone
  53. reg wb_ack_i;
  54. reg wb_we_cmd;
  55. reg wb_we_addr;
  56. // Commands
  57. reg cmd_valid;
  58. reg cmd_start;
  59. reg cmd_read;
  60. reg [ 6:0] cmd_len;
  61. reg [AL:0] cmd_addr;
  62. reg cmd_dual;
  63. // Validate
  64. reg val_ok;
  65. // Buffers
  66. // -------
  67. ram_sdp #(
  68. .AWIDTH(8),
  69. .DWIDTH(32)
  70. ) buf_wr_I (
  71. .wr_addr (bw_waddr),
  72. .wr_data (bw_wdata),
  73. .wr_ena (bw_wren),
  74. .rd_addr (bw_raddr),
  75. .rd_data (bw_rdata),
  76. .rd_ena (bw_rden),
  77. .clk (clk)
  78. );
  79. ram_sdp #(
  80. .AWIDTH(8),
  81. .DWIDTH(32)
  82. ) buf_rd_I (
  83. .wr_addr (br_waddr),
  84. .wr_data (br_wdata),
  85. .wr_ena (br_wren),
  86. .rd_addr (br_raddr),
  87. .rd_data (br_rdata),
  88. .rd_ena (br_rden),
  89. .clk (clk)
  90. );
  91. // Wishbone interface
  92. // ------------------
  93. // Ack
  94. always @(posedge clk)
  95. wb_ack_i <= wb_cyc & ~wb_ack_i;
  96. assign wb_ack = wb_ack_i;
  97. // Read Mux
  98. assign wb_rdata = wb_ack_i ?
  99. (wb_addr[8] ? br_rdata : { 30'h00000000, val_ok, mi_ready }) :
  100. 32'h00000000;
  101. // Buffer accesses
  102. assign bw_waddr = wb_addr[7:0];
  103. assign bw_wdata = wb_wdata;
  104. assign bw_wren = wb_ack_i & wb_we & wb_addr[8];
  105. assign br_raddr = wb_addr[7:0];
  106. assign br_rden = 1'b1;
  107. // Write Strobes
  108. always @(posedge clk)
  109. if (wb_ack_i) begin
  110. wb_we_cmd <= 1'b0;
  111. wb_we_addr <= 1'b0;
  112. end else begin
  113. wb_we_cmd <= wb_cyc & wb_we & ~wb_addr[8] & ~wb_addr[0];
  114. wb_we_addr <= wb_cyc & wb_we & ~wb_addr[8] & wb_addr[0];
  115. end
  116. always @(posedge clk)
  117. cmd_start <= wb_we_cmd;
  118. always @(posedge clk)
  119. if (rst)
  120. cmd_valid <= 1'b0;
  121. else
  122. cmd_valid <= (cmd_valid & (~mi_ready | cmd_dual)) | cmd_start;
  123. always @(posedge clk)
  124. if (wb_we_cmd)
  125. cmd_dual <= wb_wdata[18];
  126. else if (mi_ready & mi_valid)
  127. cmd_dual <= 1'b0;
  128. always @(posedge clk)
  129. if (wb_we_cmd) begin
  130. cmd_read <= wb_wdata[ 16];
  131. cmd_len <= wb_wdata[ 6: 0];
  132. end
  133. always @(posedge clk)
  134. if (wb_we_addr)
  135. cmd_addr <= wb_wdata[ADDR_WIDTH-1:0];
  136. else if (mi_ready & mi_valid)
  137. cmd_addr <= cmd_addr + cmd_len + 1;
  138. // Memory interface
  139. // ----------------
  140. // Requests
  141. assign mi_addr = cmd_addr;
  142. assign mi_len = cmd_len;
  143. assign mi_rw = cmd_read;
  144. assign mi_valid = cmd_valid;
  145. // Write data (and read-validate)
  146. always @(posedge clk)
  147. if (wb_we_cmd)
  148. bw_raddr <= wb_wdata[15:8];
  149. else
  150. bw_raddr <= bw_raddr + bw_rden;
  151. assign mi_wdata = bw_rdata;
  152. assign mi_wmsk = 4'h0;
  153. assign bw_rden = (cmd_read ? mi_rstb : mi_wack) | cmd_start;
  154. // Read data
  155. assign br_wdata = mi_rdata;
  156. assign br_wren = mi_rstb;
  157. always @(posedge clk)
  158. if (wb_we_cmd)
  159. br_waddr <= wb_wdata[15:8];
  160. else
  161. br_waddr <= br_waddr + mi_rstb;
  162. // Data validation
  163. always @(posedge clk)
  164. if (wb_we_cmd)
  165. val_ok <= val_ok | wb_wdata[17];
  166. else
  167. val_ok <= val_ok & (~mi_rstb | (mi_rdata == bw_rdata));
  168. endmodule