from migen.fhdl.std import *
-from migen.genlib.cdc import MultiReg
from migen.bank.description import *
from migen.bank.eventmanager import *
from migen.genlib.record import Record
from migen.flow.actor import Sink, Source
-class UARTRX(Module):
- def __init__(self, pads, tuning_word):
- self.source = Source([("d", 8)])
-
- ###
-
- uart_clk_rxen = Signal()
- phase_accumulator_rx = Signal(32)
-
- rx = Signal()
- self.specials += MultiReg(pads.rx, rx)
- rx_r = Signal()
- rx_reg = Signal(8)
- rx_bitcount = Signal(4)
- rx_busy = Signal()
- rx_done = self.source.stb
- rx_data = self.source.d
- self.sync += [
- rx_done.eq(0),
- rx_r.eq(rx),
- If(~rx_busy,
- If(~rx & rx_r, # look for start bit
- rx_busy.eq(1),
- rx_bitcount.eq(0),
- )
- ).Else(
- If(uart_clk_rxen,
- rx_bitcount.eq(rx_bitcount + 1),
- If(rx_bitcount == 0,
- If(rx, # verify start bit
- rx_busy.eq(0)
- )
- ).Elif(rx_bitcount == 9,
- rx_busy.eq(0),
- If(rx, # verify stop bit
- rx_data.eq(rx_reg),
- rx_done.eq(1)
- )
- ).Else(
- rx_reg.eq(Cat(rx_reg[1:], rx))
- )
- )
- )
- ]
- self.sync += \
- If(rx_busy,
- Cat(phase_accumulator_rx, uart_clk_rxen).eq(phase_accumulator_rx + tuning_word)
- ).Else(
- Cat(phase_accumulator_rx, uart_clk_rxen).eq(2**31)
- )
-
-class UARTTX(Module):
- def __init__(self, pads, tuning_word):
- self.sink = Sink([("d", 8)])
-
- ###
-
- uart_clk_txen = Signal()
- phase_accumulator_tx = Signal(32)
-
- pads.tx.reset = 1
-
- tx_reg = Signal(8)
- tx_bitcount = Signal(4)
- tx_busy = Signal()
- self.sync += [
- self.sink.ack.eq(0),
- If(self.sink.stb & ~tx_busy & ~self.sink.ack,
- tx_reg.eq(self.sink.d),
- tx_bitcount.eq(0),
- tx_busy.eq(1),
- pads.tx.eq(0)
- ).Elif(uart_clk_txen & tx_busy,
- tx_bitcount.eq(tx_bitcount + 1),
- If(tx_bitcount == 8,
- pads.tx.eq(1)
- ).Elif(tx_bitcount == 9,
- pads.tx.eq(1),
- tx_busy.eq(0),
- self.sink.ack.eq(1),
- ).Else(
- pads.tx.eq(tx_reg[0]),
- tx_reg.eq(Cat(tx_reg[1:], 0))
- )
- )
- ]
- self.sync += [
- If(tx_busy,
- Cat(phase_accumulator_tx, uart_clk_txen).eq(phase_accumulator_tx + tuning_word)
- ).Else(
- Cat(phase_accumulator_tx, uart_clk_txen).eq(0)
- )
- ]
-
class UART(Module, AutoCSR):
- def __init__(self, pads, clk_freq, baud=115200):
+ def __init__(self, phy):
self._rxtx = CSR(8)
self.submodules.ev = EventManager()
self.ev.tx = EventSourcePulse()
self.ev.rx = EventSourcePulse()
self.ev.finalize()
-
- # Tuning word value
- self._tuning_word = CSRStorage(32, reset=int((baud/clk_freq)*2**32))
- tuning_word = self._tuning_word.storage
-
###
-
- self.submodules.rx = UARTRX(pads, tuning_word)
- self.submodules.tx = UARTTX(pads, tuning_word)
-
self.sync += [
If(self._rxtx.re,
- self.tx.sink.stb.eq(1),
- self.tx.sink.d.eq(self._rxtx.r),
- ).Elif(self.tx.sink.ack,
- self.tx.sink.stb.eq(0)
+ phy.tx.sink.stb.eq(1),
+ phy.tx.sink.d.eq(self._rxtx.r),
+ ).Elif(phy.tx.sink.ack,
+ phy.tx.sink.stb.eq(0)
),
- If(self.rx.source.stb,
- self._rxtx.w.eq(self.rx.source.d)
+ If(phy.rx.source.stb,
+ self._rxtx.w.eq(phy.rx.source.d)
)
]
self.comb += [
- self.ev.tx.trigger.eq(self.tx.sink.stb & self.tx.sink.ack),
- self.ev.rx.trigger.eq(self.rx.source.stb) #self.rx.source.ack supposed to be always 1
+ self.ev.tx.trigger.eq(phy.tx.sink.stb & phy.tx.sink.ack),
+ self.ev.rx.trigger.eq(phy.rx.source.stb) #phy.rx.source.ack supposed to be always 1
]
-
-class UARTTB(Module):
- def __init__(self):
- self.clk_freq = 83333333
- self.baud = 3000000
- self.pads = Record([("rx", 1), ("tx", 1)])
- self.submodules.slave = UART(self.pads, self.clk_freq, self.baud)
-
- def wait_for(self, ns_time):
- freq_in_ghz = self.clk_freq/(10**9)
- period = 1/freq_in_ghz
- num_loops = int(ns_time/period)
- for i in range(num_loops+1):
- yield
-
- def gen_simulation(self, selfp):
- baud_in_ghz = self.baud/(10**9)
- uart_period = int(1/baud_in_ghz)
- half_uart_period = int(1/(2*baud_in_ghz))
-
- # Set TX an RX lines idle
- selfp.pads.tx = 1
- selfp.pads.rx = 1
- yield
-
- # First send a few characters
-
- tx_string = "01234"
- print("Sending string: " + tx_string)
- for c in tx_string:
- selfp.slave._r_rxtx.r = ord(c)
- selfp.slave._r_rxtx.re = 1
- yield
- selfp.slave._r_rxtx.re = 0
-
- yield from self.wait_for(half_uart_period)
-
- if selfp.pads.tx:
- print("FAILURE: no start bit sent")
-
- val = 0
- for i in range(8):
- yield from self.wait_for(uart_period)
- val >>= 1
- if selfp.pads.tx:
- val |= 0x80
-
- yield from self.wait_for(uart_period)
-
- if selfp.pads.tx == 0:
- print("FAILURE: no stop bit sent")
-
- if ord(c) != val:
- print("FAILURE: sent decimal value "+str(val)+" (char "+chr(val)+") instead of "+c)
- else:
- print("SUCCESS: sent "+c)
- while selfp.slave.ev.tx.trigger != 1:
- yield
-
- # Then receive a character
-
- rx_string = '5'
- print("Receiving character "+rx_string)
- rx_value = ord(rx_string)
- for i in range(11):
- if (i == 0):
- # start bit
- selfp.pads.rx = 0
- elif (i == 9):
- # stop bit
- selfp.pads.rx = 1
- elif (i == 10):
- selfp.pads.rx = 1
- break
- else:
- selfp.pads.rx = 1 if (rx_value & 1) else 0
- rx_value >>= 1
- yield from self.wait_for(uart_period)
-
- rx_value = ord(rx_string)
- received_value = selfp.slave._r_rxtx.w
- if (received_value == rx_value):
- print("RX SUCCESS: ")
- else:
- print("RX FAILURE: ")
-
- print("received "+chr(received_value))
-
- while True:
- yield
-
-if __name__ == "__main__":
- from migen.sim.generic import Simulator, TopLevel
- from migen.sim import icarus
- with Simulator(UARTTB(), TopLevel("top.vcd", clk_period=int(1/0.08333333)), icarus.Runner(keep_files=False)) as s:
- s.run(20000)
--- /dev/null
+from migen.fhdl.std import *
+from migen.genlib.cdc import MultiReg
+from migen.bank.description import *
+from migen.flow.actor import Sink, Source
+
+class UARTPHYSerialRX(Module):
+ def __init__(self, pads, tuning_word):
+ self.source = Source([("d", 8)])
+ ###
+ uart_clk_rxen = Signal()
+ phase_accumulator_rx = Signal(32)
+
+ rx = Signal()
+ self.specials += MultiReg(pads.rx, rx)
+ rx_r = Signal()
+ rx_reg = Signal(8)
+ rx_bitcount = Signal(4)
+ rx_busy = Signal()
+ rx_done = self.source.stb
+ rx_data = self.source.d
+ self.sync += [
+ rx_done.eq(0),
+ rx_r.eq(rx),
+ If(~rx_busy,
+ If(~rx & rx_r, # look for start bit
+ rx_busy.eq(1),
+ rx_bitcount.eq(0),
+ )
+ ).Else(
+ If(uart_clk_rxen,
+ rx_bitcount.eq(rx_bitcount + 1),
+ If(rx_bitcount == 0,
+ If(rx, # verify start bit
+ rx_busy.eq(0)
+ )
+ ).Elif(rx_bitcount == 9,
+ rx_busy.eq(0),
+ If(rx, # verify stop bit
+ rx_data.eq(rx_reg),
+ rx_done.eq(1)
+ )
+ ).Else(
+ rx_reg.eq(Cat(rx_reg[1:], rx))
+ )
+ )
+ )
+ ]
+ self.sync += \
+ If(rx_busy,
+ Cat(phase_accumulator_rx, uart_clk_rxen).eq(phase_accumulator_rx + tuning_word)
+ ).Else(
+ Cat(phase_accumulator_rx, uart_clk_rxen).eq(2**31)
+ )
+
+class UARTPHYSerialTX(Module):
+ def __init__(self, pads, tuning_word):
+ self.sink = Sink([("d", 8)])
+ ###
+ uart_clk_txen = Signal()
+ phase_accumulator_tx = Signal(32)
+
+ pads.tx.reset = 1
+
+ tx_reg = Signal(8)
+ tx_bitcount = Signal(4)
+ tx_busy = Signal()
+ self.sync += [
+ self.sink.ack.eq(0),
+ If(self.sink.stb & ~tx_busy & ~self.sink.ack,
+ tx_reg.eq(self.sink.d),
+ tx_bitcount.eq(0),
+ tx_busy.eq(1),
+ pads.tx.eq(0)
+ ).Elif(uart_clk_txen & tx_busy,
+ tx_bitcount.eq(tx_bitcount + 1),
+ If(tx_bitcount == 8,
+ pads.tx.eq(1)
+ ).Elif(tx_bitcount == 9,
+ pads.tx.eq(1),
+ tx_busy.eq(0),
+ self.sink.ack.eq(1),
+ ).Else(
+ pads.tx.eq(tx_reg[0]),
+ tx_reg.eq(Cat(tx_reg[1:], 0))
+ )
+ )
+ ]
+ self.sync += [
+ If(tx_busy,
+ Cat(phase_accumulator_tx, uart_clk_txen).eq(phase_accumulator_tx + tuning_word)
+ ).Else(
+ Cat(phase_accumulator_tx, uart_clk_txen).eq(0)
+ )
+ ]
+
+class UARTPHYSerial(Module, AutoCSR):
+ def __init__(self, pads, clk_freq, baudrate=115200):
+ self._tuning_word = CSRStorage(32, reset=int((baudrate/clk_freq)*2**32))
+ self.submodules.tx = UARTPHYSerialTX(pads, self._tuning_word.storage)
+ self.submodules.rx = UARTPHYSerialRX(pads, self._tuning_word.storage)
+ self.sink, self.source = self.tx.sink, self.rx.source
--- /dev/null
+# XXX Adapt test to new architecture
+class UARTTB(Module):
+ def __init__(self):
+ self.clk_freq = 83333333
+ self.baud = 3000000
+ self.pads = Record([("rx", 1), ("tx", 1)])
+ self.submodules.slave = UART(self.pads, self.clk_freq, self.baud)
+
+ def wait_for(self, ns_time):
+ freq_in_ghz = self.clk_freq/(10**9)
+ period = 1/freq_in_ghz
+ num_loops = int(ns_time/period)
+ for i in range(num_loops+1):
+ yield
+
+ def gen_simulation(self, selfp):
+ baud_in_ghz = self.baud/(10**9)
+ uart_period = int(1/baud_in_ghz)
+ half_uart_period = int(1/(2*baud_in_ghz))
+
+ # Set TX an RX lines idle
+ selfp.pads.tx = 1
+ selfp.pads.rx = 1
+ yield
+
+ # First send a few characters
+
+ tx_string = "01234"
+ print("Sending string: " + tx_string)
+ for c in tx_string:
+ selfp.slave._r_rxtx.r = ord(c)
+ selfp.slave._r_rxtx.re = 1
+ yield
+ selfp.slave._r_rxtx.re = 0
+
+ yield from self.wait_for(half_uart_period)
+
+ if selfp.pads.tx:
+ print("FAILURE: no start bit sent")
+
+ val = 0
+ for i in range(8):
+ yield from self.wait_for(uart_period)
+ val >>= 1
+ if selfp.pads.tx:
+ val |= 0x80
+
+ yield from self.wait_for(uart_period)
+
+ if selfp.pads.tx == 0:
+ print("FAILURE: no stop bit sent")
+
+ if ord(c) != val:
+ print("FAILURE: sent decimal value "+str(val)+" (char "+chr(val)+") instead of "+c)
+ else:
+ print("SUCCESS: sent "+c)
+ while selfp.slave.ev.tx.trigger != 1:
+ yield
+
+ # Then receive a character
+
+ rx_string = '5'
+ print("Receiving character "+rx_string)
+ rx_value = ord(rx_string)
+ for i in range(11):
+ if (i == 0):
+ # start bit
+ selfp.pads.rx = 0
+ elif (i == 9):
+ # stop bit
+ selfp.pads.rx = 1
+ elif (i == 10):
+ selfp.pads.rx = 1
+ break
+ else:
+ selfp.pads.rx = 1 if (rx_value & 1) else 0
+ rx_value >>= 1
+ yield from self.wait_for(uart_period)
+
+ rx_value = ord(rx_string)
+ received_value = selfp.slave._r_rxtx.w
+ if (received_value == rx_value):
+ print("RX SUCCESS: ")
+ else:
+ print("RX FAILURE: ")
+
+ print("received "+chr(received_value))
+
+ while True:
+ yield
+
+if __name__ == "__main__":
+ from migen.sim.generic import Simulator, TopLevel
+ from migen.sim import icarus
+ with Simulator(UARTTB(), TopLevel("top.vcd", clk_period=int(1/0.08333333)), icarus.Runner(keep_files=False)) as s:
+ s.run(20000)
from migen.bank import csrgen
from migen.bus import wishbone, csr, wishbone2csr
+from misoclib.com.uart.phy.serial import UARTPHYSerial
from misoclib.com import uart
from misoclib.cpu import CPU, lm32, mor1kx
from misoclib.cpu.peripherals import identifier, timer
class SoC(Module):
csr_map = {
"crg": 0, # user
- "uart": 1, # provided by default (optional)
- "identifier": 2, # provided by default (optional)
- "timer0": 3, # provided by default (optional)
- "buttons": 4, # user
- "leds": 5, # user
+ "uart_phy": 1, # provided by default (optional)
+ "uart": 2, # provided by default (optional)
+ "identifier": 3, # provided by default (optional)
+ "timer0": 4, # provided by default (optional)
+ "buttons": 5, # user
+ "leds": 6, # user
}
interrupt_map = {
"uart": 0,
self.register_mem("csr", self.mem_map["csr"], self.wishbone2csr.wishbone)
if with_uart:
- self.submodules.uart = uart.UART(platform.request("serial"), clk_freq, baud=uart_baudrate)
+ self.submodules.uart_phy = UARTPHYSerial(platform.request("serial"), clk_freq, uart_baudrate)
+ self.submodules.uart = uart.UART(self.uart_phy)
if with_identifier:
platform_id = 0x554E if not hasattr(platform, "identifier") else platform.identifier
class SDRAMSoC(SoC):
csr_map = {
- "dfii": 6,
- "lasmicon": 7,
- "wishbone2lasmi": 8,
- "memtest_w": 9,
- "memtest_r": 10
+ "dfii": 7,
+ "lasmicon": 8,
+ "wishbone2lasmi": 9,
+ "memtest_w": 10,
+ "memtest_r": 11
}
csr_map.update(SoC.csr_map)