From 36f3556028081f485f6014159041fc817eea7115 Mon Sep 17 00:00:00 2001 From: Florent Kermarrec Date: Mon, 18 Mar 2013 21:45:07 +0100 Subject: [PATCH] Add uart2csr --- examples/de0_nano/build.py | 9 +- examples/de0_nano/top.sdc | 4 - examples/de1/top.sdc | 4 - miscope/bridges/spi2csr/__init__.py | 129 ++++++++----------- miscope/bridges/uart2csr/__init__.py | 181 +++++++++++++++++++++++++++ miscope/bridges/uart2csr/uart.py | 103 +++++++++++++++ miscope/miio.py | 16 ++- 7 files changed, 344 insertions(+), 102 deletions(-) delete mode 100644 examples/de0_nano/top.sdc delete mode 100644 examples/de1/top.sdc create mode 100644 miscope/bridges/uart2csr/__init__.py create mode 100644 miscope/bridges/uart2csr/uart.py diff --git a/examples/de0_nano/build.py b/examples/de0_nano/build.py index b32cf7504..cf9bb84ef 100644 --- a/examples/de0_nano/build.py +++ b/examples/de0_nano/build.py @@ -1,6 +1,4 @@ -import os from mibuild.platforms import de0nano -from mibuild.altera_quartus import _add_period_constraint import top def main(): @@ -8,8 +6,6 @@ def main(): soc = top.SoC() # set pin constraints - plat.request("clk50", obj=soc.clk50) - plat.request("key", obj=soc.key) plat.request("led", obj=soc.led) plat.request("gpio_2", obj=soc.gpio_2) @@ -25,10 +21,7 @@ set_global_assignment -name RESERVE_DATA1_AFTER_CONFIGURATION "USE AS REGULAR IO set_global_assignment -name RESERVE_DCLK_AFTER_CONFIGURATION "USE AS REGULAR IO" """) - _add_period_constraint(plat, "sys_clk", 20.0) - cd = dict() - cd["sys"] = soc.cd_sys - plat.build_cmdline(soc.get_fragment(), clock_domains=cd) + plat.build_cmdline(soc.get_fragment()) if __name__ == "__main__": main() \ No newline at end of file diff --git a/examples/de0_nano/top.sdc b/examples/de0_nano/top.sdc deleted file mode 100644 index 91a1cbaf7..000000000 --- a/examples/de0_nano/top.sdc +++ /dev/null @@ -1,4 +0,0 @@ -# -# Clocks -# -create_clock -period 50MHz [get_ports clk50] \ No newline at end of file diff --git a/examples/de1/top.sdc b/examples/de1/top.sdc deleted file mode 100644 index 91a1cbaf7..000000000 --- a/examples/de1/top.sdc +++ /dev/null @@ -1,4 +0,0 @@ -# -# Clocks -# -create_clock -period 50MHz [get_ports clk50] \ No newline at end of file diff --git a/miscope/bridges/spi2csr/__init__.py b/miscope/bridges/spi2csr/__init__.py index f327762ce..d396fa687 100644 --- a/miscope/bridges/spi2csr/__init__.py +++ b/miscope/bridges/spi2csr/__init__.py @@ -1,97 +1,73 @@ from migen.fhdl.structure import * +from migen.genlib.misc import * +from migen.genlib.cdc import * from migen.bus import csr -from migen.bank import description, csrgen -from migen.bank.description import * -class Spi2Csr : - def __init__(self, a_width, d_width, max_burst = 8): - self.a_width = a_width - self.d_width = d_width - self.max_burst = 8 +class Spi2Csr(Module): + def __init__(self, a_w, d_w, burst_length=8): + self.a_w = a_w + self.d_w = d_w + self.burst_length = 8 + # Csr interface - self.csr = csr.Interface(self.a_width, self.d_width) + self.csr = csr.Interface(self.a_w, self.d_w) + # Spi interface self.spi_clk = Signal() self.spi_cs_n = Signal(reset=1) self.spi_mosi = Signal() self.spi_miso = Signal() - self.spi_int_n = Signal(reset=1) - def get_fragment(self): - comb = [] - sync = [] + ### # Resychronisation - spi_clk_d1 = Signal() - spi_clk_d2 = Signal() - spi_clk_d3 = Signal() - - sync += [ - spi_clk_d1.eq(self.spi_clk), - spi_clk_d2.eq(spi_clk_d1), - spi_clk_d3.eq(spi_clk_d2) - ] - - spi_cs_n_d1 = Signal() - spi_cs_n_d2 = Signal() - spi_cs_n_d3 = Signal() - - sync += [ - spi_cs_n_d1.eq(self.spi_cs_n), - spi_cs_n_d2.eq(spi_cs_n_d1), - spi_cs_n_d3.eq(spi_cs_n_d2) - ] - - spi_mosi_d1 = Signal() - spi_mosi_d2 = Signal() - spi_mosi_d3 = Signal() - - sync += [ - spi_mosi_d1.eq(self.spi_mosi), - spi_mosi_d2.eq(spi_mosi_d1), - spi_mosi_d3.eq(spi_mosi_d2) - ] - + clk_synchro = Synchronizer(i=self.spi_clk) + cs_n_synchro = Synchronizer(i=self.spi_cs_n) + mosi_synchro = Synchronizer(i=self.spi_mosi) + + self.specials += {clk_synchro, cs_n_synchro, mosi_synchro} + # Decode spi_clk_rising = Signal() spi_clk_falling = Signal() spi_cs_n_active = Signal() spi_mosi_dat = Signal() - comb += [ - spi_clk_rising.eq(spi_clk_d2 & ~spi_clk_d3), - spi_clk_falling.eq(~spi_clk_d2 & spi_clk_d3), - spi_cs_n_active.eq(~spi_cs_n_d3), - spi_mosi_dat.eq(spi_mosi_d3) + self.specials += RisingEdge(i=clk_synchro.o, o=spi_clk_rising) + self.specials += FallingEdge(i=clk_synchro.o, o=spi_clk_falling) + + self.sync +=[ + spi_cs_n_active.eq(~cs_n_synchro.o), + spi_mosi_dat.eq(~mosi_synchro.o), ] # # Spi --> Csr # - spi_cnt = Signal(bits_for(self.a_width+self.max_burst*self.d_width)) - spi_addr = Signal(self.a_width) - spi_w_dat = Signal(self.d_width) - spi_r_dat = Signal(self.d_width) + spi_cnt = Signal(bits_for(self.a_w + self.burst_length*self.d_w)) + spi_addr = Signal(self.a_w) + spi_w_dat = Signal(self.d_w) + spi_r_dat = Signal(self.d_w) spi_we = Signal() spi_re = Signal() - spi_we_re_done = Signal(reset = 1) + spi_we_re_done = Signal(reset=1) spi_miso_dat = Signal() # Re/We Signals Decoding first_b = Signal() last_b = Signal() - comb +=[ - first_b.eq(spi_cnt[0:bits_for(self.d_width)-1] == 0), - last_b.eq(spi_cnt[0:bits_for(self.d_width)-1] == 2**(bits_for(self.d_width)-1)-1) + self.comb +=[ + first_b.eq(spi_cnt[0:bits_for(self.d_w)-1] == 0), + last_b.eq(spi_cnt[0:bits_for(self.d_w)-1] == 2**(bits_for(self.d_w-1))-1) ] - sync +=[ - If((spi_cnt >= (self.a_width + self.d_width)) & first_b, - spi_we.eq(spi_addr[self.a_width-1] & ~spi_we_re_done), - spi_re.eq(~spi_addr[self.a_width-1] & ~spi_we_re_done), + self.sync +=[ + If((spi_cnt >= (self.a_w + self.d_w)) & first_b, + spi_we.eq(spi_addr[self.a_w-1] & ~spi_we_re_done), + spi_re.eq(~spi_addr[self.a_w-1] & ~spi_we_re_done), spi_we_re_done.eq(1) - ).Elif((spi_cnt >= self.a_width) & first_b, - spi_re.eq(~spi_addr[self.a_width-1] & ~spi_we_re_done), + ).Elif((spi_cnt >= self.a_w) & first_b, + spi_re.eq(~spi_addr[self.a_w-1] & ~spi_we_re_done), spi_we_re_done.eq(1) ).Else( spi_we.eq(0), @@ -101,21 +77,21 @@ class Spi2Csr : ] # Spi Addr / Data Decoding - sync +=[ + self.sync +=[ If(~spi_cs_n_active, spi_cnt.eq(0), ).Elif(spi_clk_rising, # addr - If(spi_cnt < self.a_width, - spi_addr.eq(Cat(spi_mosi_dat,spi_addr[:self.a_width-1])) - ).Elif((spi_cnt >= (self.a_width+self.d_width)) & last_b, + If(spi_cnt < self.a_w, + spi_addr.eq(Cat(spi_mosi_dat,spi_addr[:self.a_w-1])) + ).Elif((spi_cnt >= (self.a_w+self.d_w)) & last_b, spi_addr.eq(spi_addr+1) - ).Elif((spi_cnt >= self.a_width) & last_b & (spi_addr[self.a_width-1] == 0), + ).Elif((spi_cnt >= self.a_w) & last_b & (spi_addr[self.a_w-1] == 0), spi_addr.eq(spi_addr+1) ), # dat - If(spi_cnt >= self.a_width, - spi_w_dat.eq(Cat(spi_mosi_dat,spi_w_dat[:self.d_width-1])) + If(spi_cnt >= self.a_w, + spi_w_dat.eq(Cat(spi_mosi_dat,spi_w_dat[:self.d_w-1])) ), # spi_cnt @@ -126,8 +102,8 @@ class Spi2Csr : # # Csr --> Spi # - spi_r_dat_shift = Signal(self.d_width) - sync +=[ + spi_r_dat_shift = Signal(self.d_w) + self.sync +=[ If(spi_re, spi_r_dat_shift.eq(spi_r_dat) ), @@ -135,16 +111,16 @@ class Spi2Csr : If(~spi_cs_n_active, spi_miso_dat.eq(0) ).Elif(spi_clk_falling, - spi_miso_dat.eq(spi_r_dat_shift[self.d_width-1]), - spi_r_dat_shift.eq(Cat(0,spi_r_dat_shift[:self.d_width-1])) + spi_miso_dat.eq(spi_r_dat_shift[self.d_w-1]), + spi_r_dat_shift.eq(Cat(0,spi_r_dat_shift[:self.d_w-1])) ) - ] + ] # # Csr Interface # - comb += [ + self.comb += [ self.csr.adr.eq(spi_addr), self.csr.dat_w.eq(spi_w_dat), self.csr.we.eq(spi_we) @@ -153,8 +129,7 @@ class Spi2Csr : # # Spi Interface # - comb += [ + self.comb += [ spi_r_dat.eq(self.csr.dat_r), self.spi_miso.eq(spi_miso_dat) - ] - return Fragment(comb=comb,sync=sync) \ No newline at end of file + ] \ No newline at end of file diff --git a/miscope/bridges/uart2csr/__init__.py b/miscope/bridges/uart2csr/__init__.py new file mode 100644 index 000000000..6f46ced78 --- /dev/null +++ b/miscope/bridges/uart2csr/__init__.py @@ -0,0 +1,181 @@ +from migen.fhdl.structure import * +from migen.genlib.misc import * +from migen.genlib.cdc import * +from migen.bus import csr + +from miscope.bridges.uart2csr.uart import * + +WRITE_CMD = 0x01 +READ_CMD = 0x02 +CLOSE_CMD = 0x03 + +class Uart2Csr(Module): + def __init__(self, clk_freq, baud): + # Uart interface + self.rx = Signal() + self.tx = Signal() + + # Csr interface + self.csr = csr.Interface(32, 8) + + ### + + uart = Uart(clk_freq, baud) + self.specials +=uart + + # + # In/Out + # + self.comb +=[ + uart.rx.eq(self.rx), + self.tx.eq(uart.tx) + ] + + cmd = Signal(8) + cnt = Signal(3) + sr = Signal(32) + burst_cnt = Signal(8) + addr = Signal(32) + data = Signal(8) + + # + # Global + # + self.sync +=[ + If(fsm.ongoing(fsm.IDLE), cnt.eq(0) + ).Elif(uart_rx_ev, cnt.eq(cnt + 1)), + + sr.eq(Cat(uart.rx_dat, sr[0:24])) + ] + + # FSM + fsm = FSM("IDLE", + "GET_BL", "GET_ADDR", + "GET_DATA", "WRITE_CSR", + "READ_CSR", "SEND_DATA") + + # State done + get_bl_done = Signal() + get_addr_done = Signal() + get_data_done = Signal() + send_data_done = Signal() + + # + # Idle + # + fsm.act(fsm.IDLE, + If(uart.rx_ev and (uart.rx_dat == WRITE_CMD or uart.rx_dat == READ_CMD), + fsm.next_state(fsm.GET_BL) + ) + ) + + self.sync +=[ + If(fsm.ongoing(fsm.IDLE) and uart_rx_env, + cmd.eq(uart.rx_dat) + ) + + ] + + # + # Get burst length + # + fsm.act(fsm.GET_BL, + If(get_bl_done, + fsm.next_state(fsm.GET_ADDR) + ) + ) + + self.comb += get_bl_done.eq(uart_rx_ev and fsm.ongoing(fsm.GET_BL)) + + self.sync +=[ + If(get_bl_done, + burst_cnt.eq(uart.rx_dat) + ) + ] + + # + # Get address + # + fsm.act(fsm.GET_ADDR, + If(get_addr_done and cmd == WRITE_CMD, + fsm.next_state(fsm.GET_DATA) + ).Elif(get_addr_done and cmd == READ_CMD, + fsm.next_state(fsm.READ_CSR) + ) + ) + + self.comb += get_addr_done.eq(uart_rx_ev and rx_cnt == 4 and fsm.ongoing(fsm.GET_ADDR)) + + self.sync +=[ + If(get_addr_done, + addr.eq(sr) + ).Elif(write_data_done or send_data_done, + addr.eq(addr + 4) + ) + ] + + # + # Get data + # + fsm.act(fsm.GET_DATA, + If(get_data_done, + fsm.next_state(fsm.IDLE) + ) + ) + + self.comb += get_data_done.eq(uart_rx_ev and fsm.ongoing(fsm.GET_DATA)) + + self.sync +=[ + If(get_data_done, + burst_cnt.eq(burst_cnt-1), + data.eq(uart.rx_dat) + ) + ] + + # + # Write Csr + # + fsm.act(fsm.WRITE_CSR, + If((not burst_cnt), + fsm.next_state(fsm.IDLE) + ).Else(fsm.next_state(fsm.GET_DATA)) + ) + + # + # Read Csr + # + fsm.act(fsm.READ_CSR, + fsm.next_state(fsm.SEND_DATA) + ) + + # + # Send Data + # + fsm.act(fsm.SEND_DATA, + If(send_data_done and (not burst_cnt), + fsm.next_state(fsm.IDLE) + ).Elif(send_data_done, + fsm.next_state(fsm.READ_CSR) + ) + ) + + self.comb += [ + uart.tx_dat.eq(csr.dat_r), + uart.we.eq(fsm.entering(fsm.SEND_DATA)), + send_data_done.eq(~uart.we or uart.tx_ev) + ] + + # + # Csr access + # + self.sync +=[ + self.csr.adr.eq(addr), + self.csr.dat_w.eq(data), + If(fsm.ongoing(fsm.WRITE_CSR, + self.csr.we.eq(1) + ).Else( + self.csr.we.eq(0) + ) + ] + + diff --git a/miscope/bridges/uart2csr/uart.py b/miscope/bridges/uart2csr/uart.py new file mode 100644 index 000000000..f344e1a7d --- /dev/null +++ b/miscope/bridges/uart2csr/uart.py @@ -0,0 +1,103 @@ +from migen.fhdl.structure import * +from migen.fhdl.module import Module +from migen.genlib.cdc import MultiReg +from migen.bank.description import * +from migen.bank.eventmanager import * + +class UART(Module): + def __init__(self, clk_freq, baud=115200): + + self.rx_ev = Signal() + self.rx_dat = Signal(8) + + self.tx_we = Signal() + self.tx_ev = Signal() + self.tx_dat = Signal(8) + + self.divisor = Signal(16, reset=int(clk_freq/baud/16)) + + self.tx = Signal(reset=1) + self.rx = Signal() + + ### + + 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 - 1)) + ] + + # TX + tx_reg = Signal(8) + tx_bitcount = Signal(4) + tx_count16 = Signal(4) + tx_busy = self.tx_ev + self.sync += [ + If(self.tx_we, + tx_reg.eq(self.tx_dat), + tx_bitcount.eq(0), + tx_count16.eq(1), + tx_busy.eq(1), + self.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, + self.tx.eq(1) + ).Elif(tx_bitcount == 9, + self.tx.eq(1), + tx_busy.eq(0) + ).Else( + self.tx.eq(tx_reg[0]), + tx_reg.eq(Cat(tx_reg[1:], 0)) + ) + ) + ) + ] + + # RX + rx = Signal() + self.specials += MultiReg(self.rx, "ext", rx, "sys") + rx_r = Signal() + rx_reg = Signal(8) + rx_bitcount = Signal(4) + rx_count16 = Signal(4) + rx_busy = Signal() + rx_done = self.rx_ev + rx_data = self.rx_dat + 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)) + ) + ) + ) + ) + ] diff --git a/miscope/miio.py b/miscope/miio.py index a65f6fb6d..ea3769e78 100644 --- a/miscope/miio.py +++ b/miscope/miio.py @@ -7,22 +7,20 @@ class MiIo: # # Definition # - def __init__(self, address, width, mode = "IO", interface=None): + def __init__(self, address, width, mode="IO", interface=None): self.address = address self.width = width - self.mode = mode + self.mode = mode.upper() self.interface = interface - self.words = int(2**bits_for(width-1)/8) + self.words = int((2**bits_for(width-1))/8) if "I" in self.mode: self.i = Signal(self.width) self.ireg = description.RegisterField("i", self.width, READ_ONLY, WRITE_ONLY) - self.ireg.field.w.name_override = "inputs" if "O" in self.mode: self.o = Signal(self.width) self.oreg = description.RegisterField("o", self.width) - self.oreg.field.r.name_override = "ouptuts" self.bank = csrgen.Bank([self.oreg, self.ireg], address=self.address) @@ -30,18 +28,18 @@ class MiIo: comb = [] if "I" in self.mode: - comb += [self.ireg.field.w.eq(self.i)] + comb += self.ireg.field.w.eq(self.i) if "O" in self.mode: - comb += [self.o.eq(self.oreg.field.r)] + comb += self.o.eq(self.oreg.field.r) return Fragment(comb) + self.bank.get_fragment() # #Driver # def write(self, data): - self.interface.write_n(self.address, data, self.width) + self.interface.write(self.address, data, self.width) def read(self): - r = self.interface.read_n(self.address + self.words, self.width) + r = self.interface.read(self.address + self.words, self.width) return r \ No newline at end of file