Next-generation FPGA SoC toolkit
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

124 lines
3.7KB

  1. from nmigen import *
  2. from nmigen.lib.cdc import MultiReg
  3. __all__ = ["RS232RX", "RS232TX"]
  4. class RS232RX(Elaboratable):
  5. def __init__(self, tuning_word):
  6. self.rx = Signal()
  7. self.data = Signal(8)
  8. self.stb = Signal()
  9. self.tuning_word = tuning_word
  10. def elaborate(self, platform):
  11. m = Module()
  12. uart_clk_rxen = Signal()
  13. phase_accumulator_rx = Signal(32)
  14. rx = Signal()
  15. m.submodules += MultiReg(self.rx, rx)
  16. rx_r = Signal()
  17. rx_reg = Signal(8)
  18. rx_bitcount = Signal(4)
  19. rx_busy = Signal()
  20. rx_done = self.stb
  21. rx_data = self.data
  22. m.d.sync += [
  23. rx_done.eq(0),
  24. rx_r.eq(rx)
  25. ]
  26. with m.If(~rx_busy):
  27. with m.If(~rx & rx_r): # look for start bit
  28. m.d.sync += [
  29. rx_busy.eq(1),
  30. rx_bitcount.eq(0)
  31. ]
  32. with m.Else():
  33. with m.If(uart_clk_rxen):
  34. m.d.sync += rx_bitcount.eq(rx_bitcount + 1)
  35. with m.If(rx_bitcount == 0):
  36. with m.If(rx): # verify start bit
  37. m.d.sync += rx_busy.eq(0)
  38. with m.Elif(rx_bitcount == 9):
  39. m.d.sync += rx_busy.eq(0)
  40. with m.If(rx): # verify stop bit
  41. m.d.sync += [
  42. rx_data.eq(rx_reg),
  43. rx_done.eq(1)
  44. ]
  45. with m.Else():
  46. m.d.sync += rx_reg.eq(Cat(rx_reg[1:], rx))
  47. with m.If(rx_busy):
  48. m.d.sync += Cat(phase_accumulator_rx, uart_clk_rxen).eq(phase_accumulator_rx + self.tuning_word)
  49. with m.Else():
  50. m.d.sync += Cat(phase_accumulator_rx, uart_clk_rxen).eq(2**31)
  51. return m
  52. def read(self):
  53. while not (yield self.stb):
  54. yield
  55. value = yield self.data
  56. # clear stb, otherwise multiple calls to this generator keep returning the same value
  57. yield
  58. return value
  59. class RS232TX(Elaboratable):
  60. def __init__(self, tuning_word):
  61. self.tx = Signal(reset=1)
  62. self.data = Signal(8)
  63. self.stb = Signal()
  64. self.ack = Signal()
  65. self.tuning_word = tuning_word
  66. def elaborate(self, platform):
  67. m = Module()
  68. uart_clk_txen = Signal()
  69. phase_accumulator_tx = Signal(32)
  70. tx_reg = Signal(8)
  71. tx_bitcount = Signal(4)
  72. tx_busy = Signal()
  73. m.d.sync += self.ack.eq(0)
  74. with m.If(self.stb & ~tx_busy & ~self.ack):
  75. m.d.sync += [
  76. tx_reg.eq(self.data),
  77. tx_bitcount.eq(0),
  78. tx_busy.eq(1),
  79. self.tx.eq(0)
  80. ]
  81. with m.Elif(uart_clk_txen & tx_busy):
  82. m.d.sync += tx_bitcount.eq(tx_bitcount + 1)
  83. with m.If(tx_bitcount == 8):
  84. m.d.sync += self.tx.eq(1)
  85. with m.Elif(tx_bitcount == 9):
  86. m.d.sync += [
  87. self.tx.eq(1),
  88. tx_busy.eq(0),
  89. self.ack.eq(1)
  90. ]
  91. with m.Else():
  92. m.d.sync += [
  93. self.tx.eq(tx_reg[0]),
  94. tx_reg.eq(Cat(tx_reg[1:], 0))
  95. ]
  96. with m.If(tx_busy):
  97. m.d.sync += Cat(phase_accumulator_tx, uart_clk_txen).eq(phase_accumulator_tx + self.tuning_word)
  98. with m.Else():
  99. m.d.sync += Cat(phase_accumulator_tx, uart_clk_txen).eq(0)
  100. return m
  101. def write(self, data):
  102. yield self.stb.eq(1)
  103. yield self.data.eq(data)
  104. yield
  105. while not (yield self.ack):
  106. yield
  107. yield self.stb.eq(0)