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.
 
 
 
 
 

110 lines
3.5 KiB

from nmigen import *
from nmigen.lib.cdc import MultiReg
from nmigen.cli import main
class RS232RX:
def __init__(self, tuning_word):
self.rx = Signal()
self.data = Signal(8)
self.stb = Signal()
self.tuning_word = tuning_word
def elaborate(self, platform):
m = Module()
uart_clk_rxen = Signal()
phase_accumulator_rx = Signal(32)
rx = Signal()
m.submodules += MultiReg(self.rx, rx)
rx_r = Signal()
rx_reg = Signal(8)
rx_bitcount = Signal(4)
rx_busy = Signal()
rx_done = self.stb
rx_data = self.data
m.d.sync += rx_done.eq(0)
m.d.sync += rx_r.eq(rx)
with m.If(~rx_busy):
with m.If(~rx & rx_r): # look for start bit
m.d.sync += rx_busy.eq(1)
m.d.sync += rx_bitcount.eq(0)
with m.Else():
with m.If(uart_clk_rxen):
m.d.sync += rx_bitcount.eq(rx_bitcount + 1)
with m.If(rx_bitcount == 0):
with m.If(rx): # verify start bit
m.d.sync += rx_busy.eq(0)
with m.Elif(rx_bitcount == 9):
m.d.sync += rx_busy.eq(0)
with m.If(rx): # verify stop bit
m.d.sync += rx_data.eq(rx_reg)
m.d.sync += rx_done.eq(1)
with m.Else():
m.d.sync += rx_reg.eq(Cat(rx_reg[1:], rx))
with m.If(rx_busy):
m.d.sync += Cat(phase_accumulator_rx, uart_clk_rxen).eq(phase_accumulator_rx + self.tuning_word)
with m.Else():
m.d.sync += Cat(phase_accumulator_rx, uart_clk_rxen).eq(2**31)
return m
class RS232TX:
def __init__(self, tuning_word):
self.tx = Signal(reset=1)
self.data = Signal(8)
self.stb = Signal()
self.ack = Signal()
self.tuning_word = tuning_word
def elaborate(self, platform):
m = Module()
uart_clk_txen = Signal()
phase_accumulator_tx = Signal(32)
tx_reg = Signal(8)
tx_bitcount = Signal(4)
tx_busy = Signal()
m.d.sync += self.ack.eq(0),
with m.If(self.stb & ~tx_busy & ~self.ack):
m.d.sync += tx_reg.eq(self.data)
m.d.sync += tx_bitcount.eq(0)
m.d.sync += tx_busy.eq(1)
m.d.sync += self.tx.eq(0)
with m.Elif(uart_clk_txen & tx_busy):
m.d.sync += tx_bitcount.eq(tx_bitcount + 1)
with m.If(tx_bitcount == 8):
m.d.sync += self.tx.eq(1)
with m.Elif(tx_bitcount == 9):
m.d.sync += self.tx.eq(1)
m.d.sync += tx_busy.eq(0)
m.d.sync += self.ack.eq(1),
with m.Else():
m.d.sync += self.tx.eq(tx_reg[0])
m.d.sync += tx_reg.eq(Cat(tx_reg[1:], 0))
with m.If(tx_busy):
m.d.sync += Cat(phase_accumulator_tx, uart_clk_txen).eq(phase_accumulator_tx + self.tuning_word)
with m.Else():
m.d.sync += Cat(phase_accumulator_tx, uart_clk_txen).eq(0)
return m
class Loopback:
def elaborate(self, platform):
m = Module()
tuning_word = 2**31
tx = RS232TX(tuning_word)
rx = RS232RX(tuning_word)
m.submodules += tx, rx
m.d.comb += rx.rx.eq(tx.tx)
m.d.comb += tx.data.eq(42)
m.d.comb += tx.stb.eq(1)
return m
if __name__ == "__main__":
uart = Loopback()
main(uart)