uart_wb.v 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230
  1. /*
  2. * uart_wb.v
  3. *
  4. * vim: ts=4 sw=4
  5. *
  6. * Copyright (C) 2019 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 uart_wb #(
  35. parameter integer DIV_WIDTH = 8,
  36. parameter integer DW = 16
  37. )(
  38. // UART
  39. output wire uart_tx,
  40. input wire uart_rx,
  41. // Bus interface
  42. input wire [1:0] bus_addr,
  43. input wire [DW-1:0] bus_wdata,
  44. output wire [DW-1:0] bus_rdata,
  45. input wire bus_cyc,
  46. output wire bus_ack,
  47. input wire bus_we,
  48. // Clock / Reset
  49. input wire clk,
  50. input wire rst
  51. );
  52. // Signals
  53. // -------
  54. // RX fifo
  55. wire [ 7:0] urf_wdata;
  56. wire urf_wren;
  57. wire urf_full;
  58. wire [ 7:0] urf_rdata;
  59. wire urf_rden;
  60. wire urf_empty;
  61. reg urf_overflow;
  62. wire urf_overflow_clr;
  63. // TX fifo
  64. wire [ 7:0] utf_wdata;
  65. wire utf_wren;
  66. wire utf_full;
  67. wire [ 7:0] utf_rdata;
  68. wire utf_rden;
  69. wire utf_empty;
  70. // TX core
  71. wire [ 7:0] uart_tx_data;
  72. wire uart_tx_valid;
  73. wire uart_tx_ack;
  74. // RX core
  75. wire [ 7:0] uart_rx_data;
  76. wire uart_rx_stb;
  77. // CSR
  78. reg [DIV_WIDTH-1:0] uart_div;
  79. // Bus IF
  80. wire ub_rdata_rst;
  81. reg [DW-1:0] ub_rdata;
  82. reg ub_rd_data;
  83. reg ub_rd_ctrl;
  84. reg ub_wr_data;
  85. reg ub_wr_div;
  86. reg ub_ack;
  87. // TX Core
  88. // -------
  89. uart_tx #(
  90. .DIV_WIDTH(DIV_WIDTH)
  91. ) uart_tx_I (
  92. .data(uart_tx_data),
  93. .valid(uart_tx_valid),
  94. .ack(uart_tx_ack),
  95. .tx(uart_tx),
  96. .div(uart_div),
  97. .clk(clk),
  98. .rst(rst)
  99. );
  100. // TX FIFO
  101. // -------
  102. fifo_sync_ram #(
  103. .DEPTH(512),
  104. .WIDTH(8)
  105. ) uart_tx_fifo_I (
  106. .wr_data(utf_wdata),
  107. .wr_ena(utf_wren),
  108. .wr_full(utf_full),
  109. .rd_data(utf_rdata),
  110. .rd_ena(utf_rden),
  111. .rd_empty(utf_empty),
  112. .clk(clk),
  113. .rst(rst)
  114. );
  115. // TX glue
  116. assign uart_tx_data = utf_rdata;
  117. assign uart_tx_valid = ~utf_empty;
  118. assign utf_rden = uart_tx_ack;
  119. // RX Core
  120. // -------
  121. uart_rx #(
  122. .DIV_WIDTH(DIV_WIDTH),
  123. .GLITCH_FILTER(2)
  124. ) uart_rx_I (
  125. .rx(uart_rx),
  126. .data(uart_rx_data),
  127. .stb(uart_rx_stb),
  128. .div(uart_div),
  129. .clk(clk),
  130. .rst(rst)
  131. );
  132. // RX FIFO
  133. // -------
  134. fifo_sync_ram #(
  135. .DEPTH(512),
  136. .WIDTH(8)
  137. ) uart_rx_fifo_I (
  138. .wr_data(urf_wdata),
  139. .wr_ena(urf_wren),
  140. .wr_full(urf_full),
  141. .rd_data(urf_rdata),
  142. .rd_ena(urf_rden),
  143. .rd_empty(urf_empty),
  144. .clk(clk),
  145. .rst(rst)
  146. );
  147. // RX glue
  148. assign urf_wdata = uart_rx_data;
  149. assign urf_wren = uart_rx_stb & ~urf_full;
  150. // Overflow
  151. always @(posedge clk or posedge rst)
  152. if (rst)
  153. urf_overflow <= 1'b0;
  154. else
  155. urf_overflow <= (urf_overflow & ~urf_overflow_clr) | (uart_rx_stb & urf_full);
  156. // Bus interface
  157. // -------------
  158. always @(posedge clk)
  159. if (ub_ack) begin
  160. ub_rd_data <= 1'b0;
  161. ub_rd_ctrl <= 1'b0;
  162. ub_wr_data <= 1'b0;
  163. ub_wr_div <= 1'b0;
  164. end else begin
  165. ub_rd_data <= ~bus_we & bus_cyc & (bus_addr == 2'b00);
  166. ub_rd_ctrl <= ~bus_we & bus_cyc & (bus_addr == 2'b01);
  167. ub_wr_data <= bus_we & bus_cyc & (bus_addr == 2'b00) & ~utf_full;
  168. ub_wr_div <= bus_we & bus_cyc & (bus_addr == 2'b01);
  169. end
  170. always @(posedge clk)
  171. if (ub_ack)
  172. ub_ack <= 1'b0;
  173. else
  174. ub_ack <= bus_cyc & (~bus_we | (bus_addr == 2'b01) | ~utf_full);
  175. assign ub_rdata_rst = ub_ack | bus_we | ~bus_cyc;
  176. always @(posedge clk)
  177. if (ub_rdata_rst)
  178. ub_rdata <= { DW{1'b0} };
  179. else
  180. ub_rdata <= bus_addr[0] ?
  181. { urf_empty, urf_overflow, utf_empty, utf_full, { (DW-DIV_WIDTH-4){1'b0} }, uart_div } :
  182. { urf_empty, { (DW-9){1'b0} }, urf_rdata };
  183. always @(posedge clk)
  184. if (ub_wr_div)
  185. uart_div <= bus_wdata[DIV_WIDTH-1:0];
  186. assign utf_wdata = bus_wdata[7:0];
  187. assign utf_wren = ub_wr_data;
  188. assign urf_rden = ub_rd_data & ~ub_rdata[DW-1];
  189. assign urf_overflow_clr = ub_rd_ctrl & ub_rdata[DW-2];
  190. assign bus_rdata = ub_rdata;
  191. assign bus_ack = ub_ack;
  192. endmodule // uart_wb