uart_regs.v 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
  1. module uart_regs #(parameter CNT = 5, DATA_WIDTH = 8) (
  2. input apb_clock,
  3. input apb_resetn,
  4. input apb_psel,
  5. input apb_penable,
  6. input apb_pwrite,
  7. input [11:0] apb_paddr,
  8. input [31:0] apb_pwdata,
  9. output reg [31:0] apb_prdata,
  10. output reg apb_pready,
  11. output reg uart_en,
  12. output reg [15:0] ibrd,
  13. output reg [5:0] fbrd,
  14. output reg [CNT-1:0] tx_write,
  15. output reg [CNT-1:0] rx_read,
  16. input [DATA_WIDTH*CNT-1:0] rx_data,
  17. input [CNT-1:0] tx_full,
  18. input [CNT-1:0] tx_empty,
  19. input [CNT-1:0] tx_busy,
  20. input [CNT-1:0] tx_complete,
  21. input [CNT-1:0] rx_full,
  22. input [CNT-1:0] rx_empty,
  23. input [CNT-1:0] rx_idle,
  24. input [CNT-1:0] framing_error,
  25. input [CNT-1:0] parity_error,
  26. input [CNT-1:0] break_error,
  27. input [CNT-1:0] overrun_error,
  28. output [CNT-1:0] clear_flags,
  29. output reg lcr_sps, // Stick parity select
  30. output reg lcr_stp2, // 2 stop bits select
  31. output reg lcr_eps, // Even parity select
  32. output reg lcr_pen, // Parity enable
  33. output reg [CNT-1:0] rx_dma_en,
  34. output reg [CNT-1:0] tx_dma_en,
  35. output reg [CNT-1:0] interrupts
  36. );
  37. parameter ADDR_DR = (8'h00 >> 2); // Data
  38. parameter ADDR_SR = (8'h04 >> 2); // Status register/error clear register
  39. parameter ADDR_FR = (8'h18 >> 2); // Flag register
  40. parameter ADDR_IBRD = (8'h24 >> 2); // Integer baud rate divisor
  41. parameter ADDR_FBRD = (8'h28 >> 2); // Fractional baud rate divisor
  42. parameter ADDR_LCR = (8'h2c >> 2); // Line control
  43. parameter ADDR_CR = (8'h30 >> 2); // Control
  44. parameter ADDR_IE = (8'h38 >> 2); // Interrupt enable
  45. parameter ADDR_IC = (8'h44 >> 2); // Interrupt clear
  46. parameter ADDR_DMACR = (8'h48 >> 2); // DMA control register
  47. parameter CNT_BITS = $clog2(CNT);
  48. reg [CNT-1:0] rx_not_empty_ie;
  49. reg [CNT-1:0] tx_not_full_ie;
  50. reg [CNT-1:0] tx_complete_ie;
  51. reg [CNT-1:0] rx_idle_ie;
  52. reg [CNT-1:0] framing_error_ie;
  53. reg [CNT-1:0] parity_error_ie;
  54. reg [CNT-1:0] break_error_ie;
  55. reg [CNT-1:0] overrun_error_ie;
  56. reg [DATA_WIDTH-1:0] rx_reg;
  57. reg [4:0] status_reg;
  58. wire [5:0] reg_addr = apb_paddr[7:2];
  59. wire [CNT_BITS-1:0] uart_idx = apb_paddr[8+:CNT_BITS];
  60. wire apb_write = (apb_psel && !apb_penable && apb_pwrite);
  61. wire apb_read0 = (apb_psel && !apb_penable && !apb_pwrite);
  62. wire apb_read1 = (apb_psel && apb_penable && !apb_pwrite);
  63. always @(posedge apb_clock or negedge apb_resetn) begin
  64. if (!apb_resetn) begin
  65. apb_pready <= 1'b1;
  66. end else begin
  67. apb_pready <= !apb_read0;
  68. end
  69. end
  70. always @(posedge apb_clock or negedge apb_resetn) begin
  71. if (!apb_resetn) begin
  72. ibrd <= 16'h0;
  73. end else if (apb_write && reg_addr == ADDR_IBRD) begin
  74. ibrd <= apb_pwdata[15:0];
  75. end
  76. end
  77. always @(posedge apb_clock or negedge apb_resetn) begin
  78. if (!apb_resetn) begin
  79. fbrd <= 16'h0;
  80. end else if (apb_write && reg_addr == ADDR_FBRD) begin
  81. fbrd <= apb_pwdata[5:0];
  82. end
  83. end
  84. always @(posedge apb_clock or negedge apb_resetn) begin
  85. if (!apb_resetn) begin
  86. tx_write <= {CNT{1'b0}};
  87. end else if (apb_write && reg_addr == ADDR_DR) begin
  88. tx_write <= (1'b1 << uart_idx);
  89. end else begin
  90. tx_write <= {CNT{1'b0}};
  91. end
  92. end
  93. always @(posedge apb_clock or negedge apb_resetn) begin
  94. if (!apb_resetn) begin
  95. rx_read <= {CNT{1'b0}};
  96. end else if (apb_read0 && reg_addr == ADDR_DR) begin
  97. rx_read <= (1'b1 << uart_idx);
  98. end else begin
  99. rx_read <= {CNT{1'b0}};
  100. end
  101. end
  102. always @(posedge apb_clock or negedge apb_resetn) begin
  103. if (!apb_resetn) begin
  104. lcr_sps <= 1'b0;
  105. lcr_stp2 <= 1'b0;
  106. lcr_eps <= 1'b0;
  107. lcr_pen <= 1'b0;
  108. end else if (apb_write && reg_addr == ADDR_LCR) begin
  109. lcr_sps <= apb_pwdata[7];
  110. lcr_stp2 <= apb_pwdata[3];
  111. lcr_eps <= apb_pwdata[2];
  112. lcr_pen <= apb_pwdata[1];
  113. end
  114. end
  115. always @(posedge apb_clock or negedge apb_resetn) begin
  116. if (!apb_resetn) begin
  117. uart_en <= 1'b0;
  118. end else if (apb_write && reg_addr == ADDR_CR) begin
  119. uart_en <= apb_pwdata[0];
  120. end
  121. end
  122. always @(posedge apb_clock or negedge apb_resetn) begin
  123. if (!apb_resetn) begin
  124. rx_not_empty_ie <= 0;
  125. tx_not_full_ie <= 0;
  126. tx_complete_ie <= 0;
  127. rx_idle_ie <= 0;
  128. framing_error_ie <= 0;
  129. parity_error_ie <= 0;
  130. break_error_ie <= 0;
  131. overrun_error_ie <= 0;
  132. end else if (apb_write && reg_addr == ADDR_IE) begin
  133. rx_not_empty_ie [uart_idx] <= apb_pwdata[4];
  134. tx_not_full_ie [uart_idx] <= apb_pwdata[5];
  135. framing_error_ie[uart_idx] <= apb_pwdata[7];
  136. parity_error_ie [uart_idx] <= apb_pwdata[8];
  137. break_error_ie [uart_idx] <= apb_pwdata[9];
  138. overrun_error_ie[uart_idx] <= apb_pwdata[10];
  139. rx_idle_ie [uart_idx] <= apb_pwdata[11];
  140. tx_complete_ie [uart_idx] <= apb_pwdata[12];
  141. end
  142. end
  143. always @(posedge apb_clock or negedge apb_resetn) begin
  144. if (!apb_resetn) begin
  145. rx_dma_en <= 0;
  146. tx_dma_en <= 0;
  147. end else if (apb_write && reg_addr == ADDR_DMACR) begin
  148. rx_dma_en[uart_idx] <= apb_pwdata[0];
  149. tx_dma_en[uart_idx] <= apb_pwdata[1];
  150. end
  151. end
  152. always @(posedge apb_clock or negedge apb_resetn) begin
  153. if (!apb_resetn) begin
  154. interrupts <= {CNT{1'b0}};
  155. end else begin
  156. interrupts <=
  157. (rx_not_empty_ie & (~rx_empty) ) |
  158. (tx_not_full_ie & (~tx_full) ) |
  159. (framing_error_ie & framing_error ) |
  160. (parity_error_ie & parity_error ) |
  161. (break_error_ie & break_error ) |
  162. (overrun_error_ie & overrun_error ) |
  163. (rx_idle_ie & rx_idle ) |
  164. (tx_complete_ie & tx_complete );
  165. end
  166. end
  167. always @(posedge apb_clock) begin
  168. rx_reg <= rx_data[uart_idx*DATA_WIDTH+:DATA_WIDTH];
  169. status_reg <= { tx_empty[uart_idx], rx_full[uart_idx], tx_full[uart_idx], rx_empty[uart_idx], tx_busy[uart_idx] };
  170. end
  171. always @(posedge apb_clock or negedge apb_resetn) begin
  172. if (!apb_resetn) begin
  173. apb_prdata <= 0;
  174. end else if (apb_read1) begin
  175. case (reg_addr)
  176. ADDR_DR: apb_prdata <= { {32-DATA_WIDTH{1'b0}}, rx_reg };
  177. ADDR_SR: apb_prdata <= { 26'h0, tx_complete[uart_idx], rx_idle[uart_idx], overrun_error[uart_idx], break_error[uart_idx], parity_error[uart_idx], framing_error[uart_idx] };
  178. ADDR_FR: apb_prdata <= { 24'h0, status_reg, 3'b0 };
  179. ADDR_IBRD: apb_prdata <= { 16'h0, ibrd };
  180. ADDR_FBRD: apb_prdata <= { 26'h0, fbrd };
  181. ADDR_LCR: apb_prdata <= { 24'b0, lcr_sps, 3'b0, lcr_stp2, lcr_eps, lcr_pen, 1'b0 };
  182. ADDR_CR: apb_prdata <= { 31'b0, uart_en };
  183. ADDR_IE: apb_prdata <= { 19'h0, tx_complete_ie[uart_idx], rx_idle_ie[uart_idx], overrun_error_ie[uart_idx], break_error_ie[uart_idx], parity_error_ie[uart_idx], framing_error_ie[uart_idx], 1'b0, tx_not_full_ie[uart_idx], rx_not_empty_ie[uart_idx], 4'h0 };
  184. ADDR_DMACR: apb_prdata <= { 30'h0, tx_dma_en[uart_idx], rx_dma_en[uart_idx] };
  185. default: apb_prdata <= 32'h0;
  186. endcase
  187. end
  188. end
  189. // A simplified approach. Any write to either SR or IC will clear all the errors and interrupts.
  190. assign clear_flags = (apb_write && (reg_addr == ADDR_SR || reg_addr == ADDR_IC)) ? (1'b1 << uart_idx) : 0;
  191. endmodule