Add uart2csr
authorFlorent Kermarrec <florent@enjoy-digital.fr>
Mon, 18 Mar 2013 20:45:07 +0000 (21:45 +0100)
committerFlorent Kermarrec <florent@enjoy-digital.fr>
Mon, 18 Mar 2013 20:45:07 +0000 (21:45 +0100)
examples/de0_nano/build.py
examples/de0_nano/top.sdc [deleted file]
examples/de1/top.sdc [deleted file]
miscope/bridges/spi2csr/__init__.py
miscope/bridges/uart2csr/__init__.py [new file with mode: 0644]
miscope/bridges/uart2csr/uart.py [new file with mode: 0644]
miscope/miio.py

index b32cf7504acee008def60b8889b0dbdd2a616acf..cf9bb84ef93c702ad42cb6d685022d94aac8c0a8 100644 (file)
@@ -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 (file)
index 91a1cba..0000000
+++ /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 (file)
index 91a1cba..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-#
-# Clocks
-#
-create_clock -period 50MHz  [get_ports clk50]
\ No newline at end of file
index f327762ceb8e3790c33a64a222a7f9431e892d38..d396fa6873f69e8d3175e73594971b3dad4346c8 100644 (file)
@@ -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 (file)
index 0000000..6f46ced
--- /dev/null
@@ -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 (file)
index 0000000..f344e1a
--- /dev/null
@@ -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))
+                                               )
+                                       )
+                               )
+                       )
+               ]
index a65f6fb6d257ab728b0af4dc5170b3b7ef3deee8..ea3769e78e9e1fa1c34b25e1218ae764cc290292 100644 (file)
@@ -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