mc97_wb.v 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312
  1. /*
  2. * mc97_wb.v
  3. *
  4. * vim: ts=4 sw=4
  5. *
  6. * Copyright (C) 2021 Sylvain Munaut <tnt@246tNt.com>
  7. * SPDX-License-Identifier: CERN-OHL-P-2.0
  8. */
  9. `default_nettype none
  10. module mc97_wb (
  11. // MC97 link
  12. output wire mc97_sdata_out,
  13. input wire mc97_sdata_in,
  14. output wire mc97_sync,
  15. input wire mc97_bitclk,
  16. output reg mc97_reset_n,
  17. // Wishbone slave
  18. input wire [ 3:0] wb_addr,
  19. output reg [31:0] wb_rdata,
  20. input wire [31:0] wb_wdata,
  21. input wire wb_we,
  22. input wire wb_cyc,
  23. output wire wb_ack,
  24. // Clock / Reset
  25. input wire clk,
  26. input wire rst
  27. );
  28. // Signals
  29. // -------
  30. // Wishbone
  31. reg b_ack;
  32. wire b_wr_rst;
  33. wire b_rd_rst;
  34. reg b_we_csr;
  35. reg b_we_ll_stat;
  36. reg b_we_ll_reg;
  37. reg b_we_ll_gpio_out;
  38. reg b_we_ll_fifo_data;
  39. reg b_re_ll_fifo_data;
  40. reg b_we_ll_fifo_csr;
  41. // FIFO PCM Input
  42. wire [15:0] fpi_w_data;
  43. wire fpi_w_ena;
  44. wire fpi_w_full;
  45. wire [15:0] fpi_r_data;
  46. wire fpi_r_ena;
  47. wire fpi_r_empty;
  48. wire [ 8:0] fpi_lvl;
  49. reg fpi_ena;
  50. reg fpi_flush;
  51. // FIFO PCM output
  52. wire [15:0] fpo_w_data;
  53. wire fpo_w_ena;
  54. wire fpo_w_full;
  55. wire [15:0] fpo_r_data;
  56. wire fpo_r_ena;
  57. wire fpo_r_empty;
  58. wire [ 8:0] fpo_lvl;
  59. reg fpo_ena;
  60. reg fpo_flush;
  61. // LL PCM interface
  62. wire [15:0] ll_pcm_out_data;
  63. wire ll_pcm_out_ack;
  64. wire [15:0] ll_pcm_in_data;
  65. wire ll_pcm_in_stb;
  66. // LL GPIO interface
  67. wire [19:0] ll_gpio_in;
  68. reg [19:0] ll_gpio_out;
  69. reg ll_gpio_ena;
  70. // LL Registers interface
  71. reg [ 5:0] ll_reg_addr;
  72. reg [15:0] ll_reg_wdata;
  73. wire [15:0] ll_reg_rdata;
  74. wire ll_reg_rerr;
  75. reg ll_reg_valid;
  76. reg ll_reg_we;
  77. wire ll_reg_ack;
  78. reg [15:0] ll_reg_rdata_r;
  79. wire ll_reg_rerr_r;
  80. // LL Misc interface
  81. reg ll_run;
  82. wire ll_rfi;
  83. wire ll_stat_codec_ready;
  84. wire [12:0] ll_stat_slot_valid;
  85. wire [12:0] ll_stat_slot_req;
  86. wire ll_stat_clr;
  87. // Bus Interface
  88. // -------------
  89. // Ack
  90. always @(posedge clk)
  91. b_ack <= wb_cyc & ~b_ack;
  92. assign wb_ack = b_ack;
  93. // Pre-control
  94. assign b_wr_rst = ~wb_cyc | b_ack | ~wb_we;
  95. assign b_rd_rst = ~wb_cyc | b_ack | wb_we;
  96. // Write
  97. always @(posedge clk)
  98. begin
  99. if (b_wr_rst) begin
  100. b_we_csr <= 1'b0;
  101. b_we_ll_stat <= 1'b0;
  102. b_we_ll_reg <= 1'b0;
  103. b_we_ll_gpio_out <= 1'b0;
  104. b_we_ll_fifo_data <= 1'b0;
  105. b_we_ll_fifo_csr <= 1'b0;
  106. end else begin
  107. b_we_csr <= wb_addr == 4'h0;
  108. b_we_ll_stat <= wb_addr == 4'h1;
  109. b_we_ll_reg <= wb_addr == 4'h2;
  110. b_we_ll_gpio_out <= wb_addr == 4'h5;
  111. b_we_ll_fifo_data <= wb_addr == 4'h6;
  112. b_we_ll_fifo_csr <= wb_addr == 4'h7;
  113. end
  114. end
  115. // Read mux
  116. always @(posedge clk)
  117. if (b_rd_rst)
  118. wb_rdata <= 32'h00000000;
  119. else
  120. casez (wb_addr[2:0])
  121. 3'h0: wb_rdata <= { 28'h0, ll_rfi, ll_gpio_ena, mc97_reset_n, ll_run };
  122. 3'h1: wb_rdata <= { ll_stat_codec_ready, 2'h0, ll_stat_slot_req, 3'h0, ll_stat_slot_valid };
  123. 3'h2: wb_rdata <= { ll_reg_valid, ll_reg_we, ll_reg_rerr_r, 7'h0, ll_reg_addr, ll_reg_rdata_r };
  124. 3'h4: wb_rdata <= { 12'h0, ll_gpio_in };
  125. 3'h5: wb_rdata <= { 12'h0, ll_gpio_out };
  126. 3'h6: wb_rdata <= { fpi_r_empty, 15'h0, fpi_r_data };
  127. 3'h7: wb_rdata <= {
  128. fpi_ena, fpi_flush, fpi_w_full, fpi_r_empty, 3'b000, fpi_lvl,
  129. fpo_ena, fpo_flush, fpo_w_full, fpo_r_empty, 3'b000, fpo_lvl
  130. };
  131. default: wb_rdata <= 32'hxxxxxxxx;
  132. endcase
  133. always @(posedge clk)
  134. if (b_rd_rst)
  135. b_re_ll_fifo_data <= 1'b0;
  136. else
  137. b_re_ll_fifo_data <= wb_addr == 4'h6;
  138. // PCM
  139. // ---
  140. // Bus interface
  141. assign fpi_r_ena = b_re_ll_fifo_data & ~wb_rdata[28];
  142. assign fpo_w_data = wb_wdata[15:0];
  143. assign fpo_w_ena = b_we_ll_fifo_data;
  144. always @(posedge clk)
  145. if (rst) begin
  146. fpi_ena <= 1'b0;
  147. fpo_ena <= 1'b0;
  148. end else if (b_we_ll_fifo_csr) begin
  149. fpi_ena <= wb_wdata[31];
  150. fpo_ena <= wb_wdata[15];
  151. end
  152. always @(posedge clk)
  153. if (rst) begin
  154. fpi_flush <= 1'b0;
  155. fpo_flush <= 1'b0;
  156. end else begin
  157. fpi_flush <= (fpi_flush & ~fpi_r_empty) | (b_we_ll_fifo_csr & wb_wdata[30]);
  158. fpo_flush <= (fpo_flush & ~fpo_r_empty) | (b_we_ll_fifo_csr & wb_wdata[14]);
  159. end
  160. // FIFO instances
  161. mc97_fifo fifo_pcm_in_I (
  162. .wr_data (fpi_w_data),
  163. .wr_ena (fpi_w_ena),
  164. .wr_full (fpi_w_full),
  165. .rd_data (fpi_r_data),
  166. .rd_ena (fpi_r_ena),
  167. .rd_empty (fpi_r_empty),
  168. .ctl_lvl (fpi_lvl),
  169. .ctl_flush (fpi_flush),
  170. .clk (clk),
  171. .rst (rst)
  172. );
  173. mc97_fifo fifo_pcm_out_I (
  174. .wr_data (fpo_w_data),
  175. .wr_ena (fpo_w_ena),
  176. .wr_full (fpo_w_full),
  177. .rd_data (fpo_r_data),
  178. .rd_ena (fpo_r_ena),
  179. .rd_empty (fpo_r_empty),
  180. .ctl_lvl (fpo_lvl),
  181. .ctl_flush (fpo_flush),
  182. .clk (clk),
  183. .rst (rst)
  184. );
  185. // Low-Level interface
  186. assign fpi_w_data = ll_pcm_in_data;
  187. assign fpi_w_ena = ll_pcm_in_stb & fpi_ena;
  188. assign ll_pcm_out_data = fpo_r_data;
  189. assign fpo_r_ena = ll_pcm_out_ack & fpo_ena;
  190. // GPIO
  191. // ----
  192. always @(posedge clk or posedge rst)
  193. if (rst)
  194. ll_gpio_out <= 20'h00000;
  195. else if (b_we_ll_gpio_out)
  196. ll_gpio_out <= wb_wdata[19:0];
  197. always @(posedge clk or posedge rst)
  198. if (rst)
  199. ll_gpio_ena <= 1'b0;
  200. else if (b_we_csr)
  201. ll_gpio_ena <= wb_wdata[2];
  202. // Register access
  203. // ---------------
  204. always @(posedge clk)
  205. ll_reg_valid <= (ll_reg_valid | b_we_ll_reg) & ~ll_reg_ack;
  206. always @(posedge clk)
  207. if (b_we_ll_reg) begin
  208. ll_reg_we <= wb_wdata[30];
  209. ll_reg_addr <= wb_wdata[21:16];
  210. ll_reg_wdata <= wb_wdata[15:0];
  211. end
  212. always @(posedge clk)
  213. if (ll_reg_ack & ~ll_reg_we) begin
  214. ll_reg_rdata_r <= ll_reg_rdata;
  215. ll_reg_rerr_r <= ll_reg_rerr;
  216. end
  217. // Misc
  218. // ----
  219. always @(posedge clk or posedge rst)
  220. if (rst) begin
  221. mc97_reset_n <= 1'b1;
  222. ll_run <= 1'b0;
  223. end else if (b_we_csr) begin
  224. mc97_reset_n <= wb_wdata[1];
  225. ll_run <= wb_wdata[0];
  226. end
  227. assign ll_stat_clr = b_we_ll_stat;
  228. // Low-level MC97
  229. // --------------
  230. mc97 ll_I (
  231. .mc97_sdata_out (mc97_sdata_out),
  232. .mc97_sdata_in (mc97_sdata_in),
  233. .mc97_sync (mc97_sync),
  234. .mc97_bitclk (mc97_bitclk),
  235. .pcm_out_data (ll_pcm_out_data),
  236. .pcm_out_ack (ll_pcm_out_ack),
  237. .pcm_in_data (ll_pcm_in_data),
  238. .pcm_in_stb (ll_pcm_in_stb),
  239. .gpio_in (ll_gpio_in),
  240. .gpio_out (ll_gpio_out),
  241. .gpio_ena (ll_gpio_ena),
  242. .reg_addr (ll_reg_addr),
  243. .reg_wdata (ll_reg_wdata),
  244. .reg_rdata (ll_reg_rdata),
  245. .reg_rerr (ll_reg_rerr),
  246. .reg_valid (ll_reg_valid),
  247. .reg_we (ll_reg_we),
  248. .reg_ack (ll_reg_ack),
  249. .cfg_run (ll_run),
  250. .rfi (ll_rfi),
  251. .stat_codec_ready(ll_stat_codec_ready),
  252. .stat_slot_valid (ll_stat_slot_valid),
  253. .stat_slot_req (ll_stat_slot_req),
  254. .stat_clr (ll_stat_clr),
  255. .clk (clk),
  256. .rst (rst)
  257. );
  258. endmodule // mc97_wb