mc97_wb.v 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310
  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_stat_codec_ready;
  83. wire [12:0] ll_stat_slot_valid;
  84. wire [12:0] ll_stat_slot_req;
  85. wire ll_stat_clr;
  86. // Bus Interface
  87. // -------------
  88. // Ack
  89. always @(posedge clk)
  90. b_ack <= wb_cyc & ~b_ack;
  91. assign wb_ack = b_ack;
  92. // Pre-control
  93. assign b_wr_rst = ~wb_cyc | b_ack | ~wb_we;
  94. assign b_rd_rst = ~wb_cyc | b_ack | wb_we;
  95. // Write
  96. always @(posedge clk)
  97. begin
  98. if (b_wr_rst) begin
  99. b_we_csr <= 1'b0;
  100. b_we_ll_stat <= 1'b0;
  101. b_we_ll_reg <= 1'b0;
  102. b_we_ll_gpio_out <= 1'b0;
  103. b_we_ll_fifo_data <= 1'b0;
  104. b_we_ll_fifo_csr <= 1'b0;
  105. end else begin
  106. b_we_csr <= wb_addr == 4'h0;
  107. b_we_ll_stat <= wb_addr == 4'h1;
  108. b_we_ll_reg <= wb_addr == 4'h2;
  109. b_we_ll_gpio_out <= wb_addr == 4'h5;
  110. b_we_ll_fifo_data <= wb_addr == 4'h6;
  111. b_we_ll_fifo_csr <= wb_addr == 4'h7;
  112. end
  113. end
  114. // Read mux
  115. always @(posedge clk)
  116. if (b_rd_rst)
  117. wb_rdata <= 32'h00000000;
  118. else
  119. casez (wb_addr[2:0])
  120. 3'h0: wb_rdata <= { 29'h0, ll_gpio_ena, mc97_reset_n, ll_run };
  121. 3'h1: wb_rdata <= { ll_stat_codec_ready, 2'h0, ll_stat_slot_req, 3'h0, ll_stat_slot_valid };
  122. 3'h2: wb_rdata <= { ll_reg_valid, ll_reg_we, ll_reg_rerr_r, 7'h0, ll_reg_addr, ll_reg_rdata_r };
  123. 3'h4: wb_rdata <= { 12'h0, ll_gpio_in };
  124. 3'h5: wb_rdata <= { 12'h0, ll_gpio_out };
  125. 3'h6: wb_rdata <= { fpi_r_empty, 15'h0, fpi_r_data };
  126. 3'h7: wb_rdata <= {
  127. fpi_ena, fpi_flush, fpi_w_full, fpi_r_empty, 3'b000, fpi_lvl,
  128. fpo_ena, fpo_flush, fpo_w_full, fpo_r_empty, 3'b000, fpo_lvl
  129. };
  130. default: wb_rdata <= 32'hxxxxxxxx;
  131. endcase
  132. always @(posedge clk)
  133. if (b_rd_rst)
  134. b_re_ll_fifo_data <= 1'b0;
  135. else
  136. b_re_ll_fifo_data <= wb_addr == 4'h6;
  137. // PCM
  138. // ---
  139. // Bus interface
  140. assign fpi_r_ena = b_re_ll_fifo_data & ~wb_rdata[28];
  141. assign fpo_w_data = wb_wdata[15:0];
  142. assign fpo_w_ena = b_we_ll_fifo_data;
  143. always @(posedge clk)
  144. if (rst) begin
  145. fpi_ena <= 1'b0;
  146. fpo_ena <= 1'b0;
  147. end else if (b_we_ll_fifo_csr) begin
  148. fpi_ena <= wb_wdata[31];
  149. fpo_ena <= wb_wdata[15];
  150. end
  151. always @(posedge clk)
  152. if (rst) begin
  153. fpi_flush <= 1'b0;
  154. fpo_flush <= 1'b0;
  155. end else begin
  156. fpi_flush <= (fpi_flush & ~fpi_r_empty) | (b_we_ll_fifo_csr & wb_wdata[30]);
  157. fpo_flush <= (fpo_flush & ~fpo_r_empty) | (b_we_ll_fifo_csr & wb_wdata[14]);
  158. end
  159. // FIFO instances
  160. mc97_fifo fifo_pcm_in_I (
  161. .wr_data (fpi_w_data),
  162. .wr_ena (fpi_w_ena),
  163. .wr_full (fpi_w_full),
  164. .rd_data (fpi_r_data),
  165. .rd_ena (fpi_r_ena),
  166. .rd_empty (fpi_r_empty),
  167. .ctl_lvl (fpi_lvl),
  168. .ctl_flush (fpi_flush),
  169. .clk (clk),
  170. .rst (rst)
  171. );
  172. mc97_fifo fifo_pcm_out_I (
  173. .wr_data (fpo_w_data),
  174. .wr_ena (fpo_w_ena),
  175. .wr_full (fpo_w_full),
  176. .rd_data (fpo_r_data),
  177. .rd_ena (fpo_r_ena),
  178. .rd_empty (fpo_r_empty),
  179. .ctl_lvl (fpo_lvl),
  180. .ctl_flush (fpo_flush),
  181. .clk (clk),
  182. .rst (rst)
  183. );
  184. // Low-Level interface
  185. assign fpi_w_data = ll_pcm_in_data;
  186. assign fpi_w_ena = ll_pcm_in_stb & fpi_ena;
  187. assign ll_pcm_out_data = fpo_r_data;
  188. assign fpo_r_ena = ll_pcm_out_ack & fpo_ena;
  189. // GPIO
  190. // ----
  191. always @(posedge clk or posedge rst)
  192. if (rst)
  193. ll_gpio_out <= 20'h00000;
  194. else if (b_we_ll_gpio_out)
  195. ll_gpio_out <= wb_wdata[19:0];
  196. always @(posedge clk or posedge rst)
  197. if (rst)
  198. ll_gpio_ena <= 1'b0;
  199. else if (b_we_csr)
  200. ll_gpio_ena <= wb_wdata[2];
  201. // Register access
  202. // ---------------
  203. always @(posedge clk)
  204. ll_reg_valid <= (ll_reg_valid | b_we_ll_reg) & ~ll_reg_ack;
  205. always @(posedge clk)
  206. if (b_we_ll_reg) begin
  207. ll_reg_we <= wb_wdata[30];
  208. ll_reg_addr <= wb_wdata[21:16];
  209. ll_reg_wdata <= wb_wdata[15:0];
  210. end
  211. always @(posedge clk)
  212. if (ll_reg_ack & ~ll_reg_we) begin
  213. ll_reg_rdata_r <= ll_reg_rdata;
  214. ll_reg_rerr_r <= ll_reg_rerr;
  215. end
  216. // Misc
  217. // ----
  218. always @(posedge clk or posedge rst)
  219. if (rst) begin
  220. mc97_reset_n <= 1'b1;
  221. ll_run <= 1'b0;
  222. end else if (b_we_csr) begin
  223. mc97_reset_n <= wb_wdata[1];
  224. ll_run <= wb_wdata[0];
  225. end
  226. assign ll_stat_clr = b_we_ll_stat;
  227. // Low-level MC97
  228. // --------------
  229. mc97 ll_I (
  230. .mc97_sdata_out (mc97_sdata_out),
  231. .mc97_sdata_in (mc97_sdata_in),
  232. .mc97_sync (mc97_sync),
  233. .mc97_bitclk (mc97_bitclk),
  234. .pcm_out_data (ll_pcm_out_data),
  235. .pcm_out_ack (ll_pcm_out_ack),
  236. .pcm_in_data (ll_pcm_in_data),
  237. .pcm_in_stb (ll_pcm_in_stb),
  238. .gpio_in (ll_gpio_in),
  239. .gpio_out (ll_gpio_out),
  240. .gpio_ena (ll_gpio_ena),
  241. .reg_addr (ll_reg_addr),
  242. .reg_wdata (ll_reg_wdata),
  243. .reg_rdata (ll_reg_rdata),
  244. .reg_rerr (ll_reg_rerr),
  245. .reg_valid (ll_reg_valid),
  246. .reg_we (ll_reg_we),
  247. .reg_ack (ll_reg_ack),
  248. .cfg_run (ll_run),
  249. .stat_codec_ready(ll_stat_codec_ready),
  250. .stat_slot_valid (ll_stat_slot_valid),
  251. .stat_slot_req (ll_stat_slot_req),
  252. .stat_clr (ll_stat_clr),
  253. .clk (clk),
  254. .rst (rst)
  255. );
  256. endmodule // mc97_wb