Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: m-labs/misoc
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 2cb7d7387019
Choose a base ref
...
head repository: m-labs/misoc
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 25b3aff6f15c
Choose a head ref
  • 2 commits
  • 2 files changed
  • 2 contributors

Commits on Jul 31, 2014

  1. Better UART baudrate generator, and testbench

    This enables high speed (tested to 4Mbps) operation.
    fallen authored and sbourdeauducq committed Jul 31, 2014
    Copy the full SHA
    32171da View commit details
  2. Copy the full SHA
    25b3aff View commit details
Showing with 185 additions and 59 deletions.
  1. +26 −2 misoclib/sdramphy/initsequence.py
  2. +159 −57 misoclib/uart/__init__.py
28 changes: 26 additions & 2 deletions misoclib/sdramphy/initsequence.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
from migen.fhdl.std import log2_int

def get_sdram_phy_header(sdram_phy):
if sdram_phy.phy_settings.memtype not in ["SDR", "DDR", "LPDDR", "DDR2"]:
raise NotImplementedError("The SDRAM PHY header generator only supports SDR, DDR, LPDDR and DDR2")
if sdram_phy.phy_settings.memtype not in ["SDR", "DDR", "LPDDR", "DDR2", "DDR3"]:
raise NotImplementedError("The SDRAM PHY header generator only supports SDR, DDR, LPDDR, DDR2 and DDR3")

r = "#ifndef __GENERATED_SDRAM_PHY_H\n#define __GENERATED_SDRAM_PHY_H\n"
r += "#include <hw/common.h>\n#include <generated/csr.h>\n#include <hw/flags.h>\n\n"
@@ -136,6 +136,30 @@ def gen_cmd(comment, a, ba, cmd, delay):
("Load Extended Mode Register / OCD Default", emr+ocd, 1, cmds["MODE_REGISTER"], 0),
("Load Extended Mode Register / OCD Exit", emr, 1, cmds["MODE_REGISTER"], 0),
]
elif sdram_phy.phy_settings.memtype == "DDR3":
bl = 2*sdram_phy.phy_settings.nphases
if bl is not 8:
raise NotImplementedError("DDR3 PHY header generator only supports BL of 8")
wr = cl
mr = 0 + ((cl-4) << 4) + ((wr-4) << 9)
emr1 = 6 # Output Drive Strength RZQ/7(34 Ohms) / Rtt_nom RZQ/4
emr2 = 0
emr3 = 0
reset_dll = 1 << 8

init_sequence = [
("Bring CKE high", 0x0000, 0, cmds["CKE"], 2000),
("Precharge All", 0x0400, 0, cmds["PRECHARGE_ALL"], 0),
("Load Extended Mode Register 3", emr3, 3, cmds["MODE_REGISTER"], 0),
("Load Extended Mode Register 2", emr2, 2, cmds["MODE_REGISTER"], 0),
("Load Extended Mode Register 1", emr1, 1, cmds["MODE_REGISTER"], 0),
("Load Mode Register / Reset DLL, CL={0:d}, BL={1:d}".format(cl, bl), mr + reset_dll, 0, cmds["MODE_REGISTER"], 200),
("Precharge All", 0x0400, 0, cmds["PRECHARGE_ALL"], 0),
("Auto Refresh", 0x0, 0, cmds["AUTO_REFRESH"], 4),
("Auto Refresh", 0x0, 0, cmds["AUTO_REFRESH"], 4),
("Load Mode Register / CL={0:d}, BL={1:d}".format(cl, bl), mr, 0, cmds["MODE_REGISTER"], 200),
("ZQ Calibration", 0x0400, 0, "DFII_COMMAND_WE|DFII_COMMAND_CS", 200),
]

for comment, a, ba, cmd, delay in init_sequence:
r += gen_cmd(comment, a, ba, cmd, delay)
216 changes: 159 additions & 57 deletions misoclib/uart/__init__.py
Original file line number Diff line number Diff line change
@@ -2,55 +2,52 @@
from migen.genlib.cdc import MultiReg
from migen.bank.description import *
from migen.bank.eventmanager import *
from migen.genlib.record import Record
from migen.sim.generic import Simulator, TopLevel
from migen.sim import icarus

class UART(Module, AutoCSR):
def __init__(self, pads, clk_freq, baud=115200):
self._rxtx = CSR(8)
self._divisor = CSRStorage(16, reset=int(clk_freq/baud/16))

self._r_rxtx = CSR(8)

self.submodules.ev = EventManager()
self.ev.tx = EventSourceProcess()
self.ev.rx = EventSourcePulse()
self.ev.finalize()


# Tuning word value
tuning_word=int((baud/clk_freq)*2**32)
self._r_tuning_word = CSRStorage(32, reset=tuning_word)

###

uart_clk_rxen = Signal()
uart_clk_txen = Signal()
phase_accumulator_rx = Signal(32)
phase_accumulator_tx = Signal(32)

pads.tx.reset = 1

enable16 = Signal()
enable16_counter = Signal(16)
self.comb += enable16.eq(enable16_counter == 0)
self.sync += [
enable16_counter.eq(enable16_counter - 1),
If(enable16,
enable16_counter.eq(self._divisor.storage - 1))
]

# TX
tx_reg = Signal(8)
tx_bitcount = Signal(4)
tx_count16 = Signal(4)
tx_busy = self.ev.tx.trigger
self.sync += [
If(self._rxtx.re,
tx_reg.eq(self._rxtx.r),
If(self._r_rxtx.re,
tx_reg.eq(self._r_rxtx.r),
tx_bitcount.eq(0),
tx_count16.eq(1),
tx_busy.eq(1),
pads.tx.eq(0)
).Elif(enable16 & tx_busy,
tx_count16.eq(tx_count16 + 1),
If(tx_count16 == 0,
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)
).Else(
pads.tx.eq(tx_reg[0]),
tx_reg.eq(Cat(tx_reg[1:], 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)
).Else(
pads.tx.eq(tx_reg[0]),
tx_reg.eq(Cat(tx_reg[1:], 0))
)
)
]
@@ -61,39 +58,144 @@ def __init__(self, pads, clk_freq, baud=115200):
rx_r = Signal()
rx_reg = Signal(8)
rx_bitcount = Signal(4)
rx_count16 = Signal(4)
rx_busy = Signal()
rx_done = self.ev.rx.trigger
rx_data = self._rxtx.w
rx_data = self._r_rxtx.w
self.sync += [
rx_done.eq(0),
If(enable16,
rx_r.eq(rx),
If(~rx_busy,
If(~rx & rx_r, # look for start bit
rx_busy.eq(1),
rx_count16.eq(7),
rx_bitcount.eq(0)
)
).Else(
rx_count16.eq(rx_count16 + 1),
If(rx_count16 == 0,
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))
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 + self._r_tuning_word.storage)
).Else(
Cat(phase_accumulator_rx, uart_clk_rxen).eq(2**31)
),

If(tx_busy,
Cat(phase_accumulator_tx, uart_clk_txen).eq(phase_accumulator_tx + self._r_tuning_word.storage)
).Else(
Cat(phase_accumulator_tx, uart_clk_txen).eq(0)
)
]

class UARTTB(Module):
def __init__(self):
MHz=1000000
self.clk_freq = 83333333
self.baud = 3*MHz
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:
while selfp.slave.ev.tx.trigger == 1:
yield
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)

# 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__":
with Simulator(UARTTB(), TopLevel("top.vcd", clk_period=int(1/0.08333333)), icarus.Runner(keep_files=False)) as s:
s.run(20000)