mc97.v 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434
  1. /*
  2. * mc97.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 (
  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. // User interface - Samples
  17. input wire [15:0] pcm_out_data,
  18. output reg pcm_out_ack,
  19. output wire [15:0] pcm_in_data,
  20. output reg pcm_in_stb,
  21. // User interface - GPIO (slot 12)
  22. output reg [19:0] gpio_in,
  23. input wire [19:0] gpio_out,
  24. input wire gpio_ena,
  25. // User interface - Registers
  26. input wire [ 5:0] reg_addr,
  27. input wire [15:0] reg_wdata,
  28. output wire [15:0] reg_rdata,
  29. output reg reg_rerr,
  30. input wire reg_valid,
  31. input wire reg_we,
  32. output reg reg_ack,
  33. // User interface - Misc
  34. input wire cfg_run,
  35. output wire rfi,
  36. output wire stat_codec_ready,
  37. output reg [12:0] stat_slot_valid,
  38. output reg [12:0] stat_slot_req,
  39. input wire stat_clr,
  40. // Clock / Reset
  41. input wire clk,
  42. input wire rst
  43. );
  44. // Signals
  45. // -------
  46. genvar i;
  47. // Sequencer
  48. reg [12:0] seq_wr_slot;
  49. wire [12:0] seq_rd_slot;
  50. // MC97 Frame control
  51. wire [15:0] fc_tag_out;
  52. reg [15:0] fc_tag_in; // Captured input slot 0
  53. reg [19:0] fc_status_addr; // Captured input slot 1
  54. wire [12:0] fc_slotvalid; // Mapped "slot valid" value
  55. wire [12:0] fc_slotreq; // Mapped "slot request" value
  56. // Command FSM
  57. localparam [1:0]
  58. CS_IDLE = 0,
  59. CS_SUBMIT = 1,
  60. CS_WAIT = 2,
  61. CS_CAPTURE = 3;
  62. reg [1:0] cmd_state;
  63. reg [1:0] cmd_state_nxt;
  64. // PCM samples
  65. reg pcm_out_frame;
  66. // GPIO
  67. reg gpio_ena_frame;
  68. // Interface to Shifter Unit
  69. reg [4:0] sui_bitcnt; // user -> amr
  70. reg sui_out_sync; // user -> amr
  71. reg [19:0] sui_out_data; // user -> amr
  72. reg [19:0] sui_in_data; // amr -> user
  73. reg [ 2:0] sui_flip; // amr -> user
  74. reg sui_ack; // user
  75. // Shift Unit
  76. reg [3:0] su_rst;
  77. reg [5:0] su_bitcnt;
  78. reg [2:0] su_trig;
  79. reg [19:0] su_data;
  80. reg [3:0] rst_amr_cnt;
  81. wire clk_amr;
  82. wire rst_amr;
  83. // IOs
  84. wire iob_sdata_in;
  85. wire iob_sdata_out;
  86. reg iob_sync;
  87. // Sequencer
  88. // ---------
  89. always @(posedge clk or posedge rst)
  90. if (rst)
  91. seq_wr_slot <= 13'h0001;
  92. else if (sui_ack)
  93. seq_wr_slot <= { seq_wr_slot[11:0], seq_wr_slot[12] };
  94. assign seq_rd_slot = { seq_wr_slot[1:0], seq_wr_slot[12:2] };
  95. // MC97 Frame control (TAG / SLOTREQ)
  96. // ------------------
  97. // Prepare output TAG value
  98. assign fc_tag_out = {
  99. cfg_run, // [15] Frame valid,
  100. (cmd_state == CS_SUBMIT), // [14] Slot 1 - Command Address
  101. (cmd_state == CS_SUBMIT) & reg_we, // [13] Slot 2 - Command Data
  102. 2'b00, // [12:11] Slot 3-4 - (n/a)
  103. pcm_out_frame, // [10] Slot 5 - Modem Line 1 PCM
  104. 6'd0, // [9:4] Slot 6-11 - (n/a)
  105. gpio_ena_frame, // [3] Slot 12 - GPIO
  106. 1'b0, // [2] Reserved
  107. 2'b00 // [1:0] Codec ID (always primary here)
  108. };
  109. // Capture input TAG value
  110. always @(posedge clk)
  111. if (sui_ack & seq_rd_slot[0])
  112. fc_tag_in <= sui_in_data[15:0];
  113. // Capture input STATUS_ADDR (Slot 1)
  114. always @(posedge clk)
  115. if (sui_ack & seq_rd_slot[1])
  116. fc_status_addr <= sui_in_data[15:0];
  117. // Map those
  118. generate
  119. for (i=1; i<13; i=i+1)
  120. assign fc_slotvalid[i] = fc_tag_in[15-i];
  121. endgenerate
  122. assign fc_slotvalid[0] = 1'b0; // Slot 0 fixed to 0 (special)
  123. generate
  124. for (i=3; i<13; i=i+1)
  125. assign fc_slotreq[i] = fc_status_addr[14-i];
  126. endgenerate
  127. assign fc_slotreq[2:0] = 3'b000; // Slot 0...2 fixed to 0 (special)
  128. // User Side status
  129. // Codec ready flag
  130. assign stat_codec_ready = fc_tag_in[15];
  131. // Slot valid flags
  132. always @(posedge clk)
  133. if (rst)
  134. stat_slot_valid[12:1] <= 1'b0;
  135. else
  136. stat_slot_valid[12:1] <= (stat_slot_valid[12:1] | fc_slotvalid[12:1]) & {12{~stat_clr}};
  137. initial
  138. stat_slot_valid[0] = 1'b0; // Slot 0 fixed to 0 (special)
  139. // Slot request flags
  140. always @(posedge clk)
  141. if (rst)
  142. stat_slot_req[12:3] <= 0;
  143. else
  144. stat_slot_req[12:3] <= (stat_slot_req[12:3] | fc_slotreq[12:3]) & {10{~stat_clr}};
  145. initial
  146. stat_slot_req[2:0] = 3'b000; // Slot 0-2 fixed to 0 (special)
  147. // Command FSM
  148. // -----------
  149. // State register
  150. always @(posedge clk)
  151. if (rst)
  152. cmd_state <= CS_IDLE;
  153. else
  154. cmd_state <= cmd_state_nxt;
  155. // Next-State
  156. always @(*)
  157. begin
  158. // Default is no-change
  159. cmd_state_nxt = cmd_state;
  160. // Transistions
  161. case (cmd_state)
  162. CS_IDLE:
  163. // Start new access for frame beginning
  164. if (sui_ack & seq_wr_slot[12] & reg_valid)
  165. cmd_state_nxt = CS_SUBMIT;
  166. CS_SUBMIT:
  167. // Command has been sent in this frame
  168. if (sui_ack & seq_wr_slot[12])
  169. // If it was a write, we're done.
  170. // For reads, we need to wait for an answer
  171. cmd_state_nxt = reg_we ? CS_IDLE : CS_WAIT;
  172. CS_WAIT:
  173. // No matter what, we move onto capture at the next slot
  174. // But here we check if the read worked or not (see reg_rerr)
  175. if (sui_ack & seq_rd_slot[1])
  176. cmd_state_nxt = CS_CAPTURE;
  177. CS_CAPTURE:
  178. if (sui_ack)
  179. cmd_state_nxt = CS_IDLE;
  180. endcase
  181. end
  182. // Ack
  183. always @(posedge clk)
  184. begin
  185. // Default
  186. reg_ack <= 1'b0;
  187. // Write ack
  188. if ((cmd_state == CS_SUBMIT) & sui_ack & seq_wr_slot[12] & reg_we)
  189. reg_ack <= 1'b1;
  190. // Read ack
  191. if ((cmd_state == CS_CAPTURE) & sui_ack)
  192. reg_ack <= 1'b1;
  193. end
  194. // Read error ?
  195. always @(posedge clk)
  196. if ((cmd_state == CS_WAIT) & sui_ack & seq_rd_slot[1])
  197. reg_rerr <= (sui_in_data[18:13] != reg_addr) | (fc_slotvalid[2:1] != 2'b11);
  198. // Read data
  199. assign reg_rdata = sui_in_data[19:4];
  200. // PCM samples
  201. // -----------
  202. // Output
  203. always @(posedge clk)
  204. if (sui_ack & seq_wr_slot[12])
  205. pcm_out_frame <= ~fc_slotreq[5];
  206. always @(posedge clk)
  207. pcm_out_ack <= sui_ack & seq_wr_slot[5] & pcm_out_frame;
  208. // Input
  209. assign pcm_in_data = sui_in_data[19:4];
  210. always @(posedge clk)
  211. pcm_in_stb <= sui_ack & seq_rd_slot[5] & fc_slotvalid[5];
  212. // Ring Frequency Indicator
  213. // ------------------------
  214. mc97_rfi rfi_I (
  215. .pcm_data (pcm_in_data),
  216. .pcm_stb (pcm_in_stb),
  217. .rfi (rfi),
  218. .clk (clk),
  219. .rst (rst)
  220. );
  221. // GPIO (slot 12)
  222. // ----
  223. // Register enable status for the frame
  224. always @(posedge clk)
  225. if (sui_ack & seq_wr_slot[12])
  226. gpio_ena_frame <= gpio_ena;
  227. // Capture GPIO input
  228. always @(posedge clk)
  229. if (sui_ack & seq_rd_slot[12])
  230. gpio_in <= sui_in_data;
  231. // Shifter control
  232. // ---------------
  233. always @(posedge clk or posedge rst)
  234. if (rst) begin
  235. sui_bitcnt <= 5'd0;
  236. sui_out_sync <= 1'b0;
  237. sui_out_data <= 20'h00000;
  238. end else if (sui_ack) begin
  239. sui_bitcnt <= seq_wr_slot[0] ? 5'd14 : 5'd18;
  240. sui_out_sync <= seq_wr_slot[0];
  241. sui_out_data <= 20'h00000;
  242. (* parallel_case *)
  243. case (1'b1)
  244. seq_wr_slot[ 0]: sui_out_data <= { fc_tag_out, 4'h0 };
  245. seq_wr_slot[ 1]: sui_out_data <= (cmd_state == CS_SUBMIT) ? { ~reg_we, reg_addr, 13'h0000 } : 20'h00000;
  246. seq_wr_slot[ 2]: sui_out_data <= ((cmd_state == CS_SUBMIT) & reg_we) ? { reg_wdata, 4'h0 } : 20'h00000;
  247. seq_wr_slot[ 5]: sui_out_data <= pcm_out_frame ? { pcm_out_data, 4'h0 } : 20'h00000;
  248. seq_wr_slot[12]: sui_out_data <= gpio_ena_frame ? gpio_out : 20'h00000;
  249. endcase
  250. end
  251. // Shifter
  252. // -------
  253. // Clock input
  254. SB_GB_IO #(
  255. .PIN_TYPE(6'b 0000_01),
  256. .PULLUP(1'b0),
  257. .IO_STANDARD("SB_LVCMOS")
  258. ) clk_gb_I (
  259. .PACKAGE_PIN (mc97_bitclk),
  260. .GLOBAL_BUFFER_OUTPUT (clk_amr)
  261. );
  262. // Reset
  263. always @(posedge clk_amr or posedge rst)
  264. if (rst)
  265. rst_amr_cnt <= 4'hf;
  266. else
  267. rst_amr_cnt <= rst_amr_cnt + {4{rst_amr_cnt[3]}};
  268. SB_GB rst_gbuf_I (
  269. .USER_SIGNAL_TO_GLOBAL_BUFFER (rst_amr_cnt[3]),
  270. .GLOBAL_BUFFER_OUTPUT (rst_amr)
  271. );
  272. // Bit Counter
  273. always @(posedge clk_amr or posedge rst_amr)
  274. if (rst_amr)
  275. su_bitcnt <= 6'h3f;
  276. else
  277. su_bitcnt <= su_bitcnt[5] ? (su_bitcnt + {6{su_bitcnt[5]}}) : { 1'b1, sui_bitcnt };
  278. always @(*)
  279. su_trig[0] = ~su_bitcnt[5];
  280. always @(posedge clk_amr)
  281. su_trig[2:1] <= su_trig[1:0];
  282. // Sync signal
  283. always @(posedge clk_amr)
  284. iob_sync <= su_trig[0] ? sui_out_sync : iob_sync;
  285. // Data shift register
  286. always @(posedge clk_amr)
  287. su_data <= su_trig[1] ? { sui_out_data } : { su_data[18:0], iob_sdata_in };
  288. assign iob_sdata_out = su_data[19];
  289. // Data in capture register
  290. always @(posedge clk_amr)
  291. if (su_trig[1])
  292. sui_in_data[19:1] <= { su_data[17:0], iob_sdata_in };
  293. always @(posedge clk_amr)
  294. if (su_trig[2])
  295. sui_in_data[0] <= iob_sdata_in;
  296. // Flip signal
  297. always @(posedge clk_amr)
  298. if (rst_amr)
  299. sui_flip[0] <= 1'b0;
  300. else
  301. sui_flip[0] <= sui_flip[0] ^ su_trig[2];
  302. always @(posedge clk)
  303. begin
  304. if (rst) begin
  305. sui_flip[2:1] <= 2'b00;
  306. sui_ack <= 1'b0;
  307. end else begin
  308. sui_flip[2:1] <= sui_flip[1:0];
  309. sui_ack <= sui_flip[2] ^ sui_flip[1];
  310. end
  311. end
  312. // IOBs
  313. // ----
  314. SB_IO #(
  315. .PIN_TYPE (6'b0101_00),
  316. .PULLUP (1'b0),
  317. .IO_STANDARD ("SB_LVCMOS")
  318. ) iob_sdata_out_I (
  319. .PACKAGE_PIN (mc97_sdata_out),
  320. .OUTPUT_CLK (clk_amr),
  321. .D_OUT_0 (iob_sdata_out)
  322. );
  323. SB_IO #(
  324. .PIN_TYPE (6'b0000_00),
  325. .PULLUP (1'b0),
  326. .IO_STANDARD ("SB_LVCMOS")
  327. ) iob_sdata_in_I (
  328. .PACKAGE_PIN (mc97_sdata_in),
  329. .INPUT_CLK (clk_amr),
  330. .D_IN_1 (iob_sdata_in)
  331. );
  332. SB_IO #(
  333. .PIN_TYPE (6'b0101_00),
  334. .PULLUP (1'b0),
  335. .IO_STANDARD ("SB_LVCMOS")
  336. ) iob_sync_I (
  337. .PACKAGE_PIN (mc97_sync),
  338. .OUTPUT_CLK (clk_amr),
  339. .D_OUT_0 (iob_sync)
  340. );
  341. endmodule // mc97