コード例 #1
0
    def __init__(self, soc, platform, tosbus_fifo, fromsbus_fifo, fromsbus_req_fifo, dram_dma_writer, dram_dma_reader, mem_size=256, burst_size = 8, do_checksum = False):
        #self.wishbone_r_slave = wishbone.Interface(data_width=soc.bus.data_width)
        #self.wishbone_w_slave = wishbone.Interface(data_width=soc.bus.data_width)
        self.tosbus_fifo = tosbus_fifo
        self.fromsbus_fifo = fromsbus_fifo
        self.fromsbus_req_fifo = fromsbus_req_fifo
        self.dram_dma_writer = dram_dma_writer
        self.dram_dma_reader = dram_dma_reader

        tosbus_fifo_din = Record(soc.tosbus_layout)
        self.comb += self.tosbus_fifo.din.eq(tosbus_fifo_din.raw_bits())
        fromsbus_req_fifo_din = Record(soc.fromsbus_req_layout)
        self.comb += self.fromsbus_req_fifo.din.eq(fromsbus_req_fifo_din.raw_bits())
        fromsbus_fifo_dout = Record(soc.fromsbus_layout)
        self.comb += fromsbus_fifo_dout.raw_bits().eq(self.fromsbus_fifo.dout)

        print(f"Configuring the SDRAM for {mem_size} MiB\n")

        data_width = burst_size * 4
        data_width_bits = burst_size * 32
        blk_addr_width = 32 - log2_int(data_width) # 27 for burst_size == 8

        assert(len(self.dram_dma_writer.sink.data) == data_width_bits)
        assert(len(self.dram_dma_reader.source.data) == data_width_bits)
        
        #self.wishbone_r_master = wishbone.Interface(data_width=data_width_bits)
        #self.wishbone_w_master = wishbone.Interface(data_width=data_width_bits)

        #self.submodules += wishbone.Converter(self.wishbone_r_master, self.wishbone_r_slave)
        #self.submodules += wishbone.Converter(self.wishbone_w_master, self.wishbone_w_slave)

        print("ExchangeWithMem: data_width = {}, data_width_bits = {}, blk_addr_width = {}\n".format(data_width, data_width_bits, blk_addr_width))
        print("ExchangeWithMem: tosbus_fifo width = {}, fromsbus_fifo width = {}, fromsbus_req_fifo width = {}\n".format(len(tosbus_fifo.din), len(fromsbus_fifo.dout), len(fromsbus_req_fifo.din)))
        
        local_r_addr = Signal(blk_addr_width)
        dma_r_addr = Signal(32)
        #local_r_widx = Signal(log2_int(burst_size)) # so width is 3 for burst_size == 8
        #local_r_buffer = Signal(data_width_bits)
        
        local_w_addr = Signal(blk_addr_width)
        dma_w_addr = Signal(32)
        #local_w_widx = Signal(log2_int(burst_size)) # so width is 3 for burst_size == 8
        #local_w_buffer = Signal(data_width_bits)

        max_block_bits=16

        # CSRConstant do not seem to appear in the CSR Map, but they need to be accessible to the OS driver
        #self.blk_size = CSRConstant(value=data_width) # report the block size to the SW layer
        #self.blk_base = CSRConstant(value=soc.wb_mem_map["main_ram"] >> log2_int(data_width)) # report where the blk starts
        self.blk_size = CSRStatus(32) # report the block size to the SW layer
        self.blk_base = CSRStatus(32) # report where the blk starts
        self.mem_size = CSRStatus(32) # report how much memory we have
        self.comb += self.blk_size.status.eq(data_width)
        self.comb += self.blk_base.status.eq(soc.wb_mem_map["main_ram"] >> log2_int(data_width))
        self.comb += self.mem_size.status.eq((mem_size * 1024 * 1024) >> log2_int(data_width))

        self.irqctrl = CSRStorage(write_from_dev=True, fields = [CSRField("irq_enable", 1, description = "Enable interrupt"),
                                                                 CSRField("irq_clear", 1, description = "Clear interrupt"),
                                                                 CSRField("reserved", 30, description = "Reserved"),
        ])
        self.blk_addr =   CSRStorage(32, description = "SDRAM Block address to read/write from Wishbone memory (block of size {})".format(data_width))
        self.dma_addr =   CSRStorage(32, description = "Host Base address where to write/read data (i.e. SPARC Virtual addr)")
        #self.blk_cnt =    CSRStorage(32, write_from_dev=True, description = "How many blk to read/write (max 2^{}-1); bit 31 is RD".format(max_block_bits), reset = 0)
        self.blk_cnt = CSRStorage(write_from_dev=True, fields = [CSRField("blk_cnt", max_block_bits, description = "How many blk to read/write (max 2^{}-1)".format(max_block_bits)),
                                                                 CSRField("rsvd", 32 - (max_block_bits + 1), description = "Reserved"),
                                                                 CSRField("rd_wr", 1, description = "Read/Write selector"),
        ])
        self.last_blk =   CSRStatus(32, description = "Last Blk addr finished on WB side")
        self.last_dma =   CSRStatus(32, description = "Last DMA addr finished on WB side")
        self.dma_wrdone = CSRStatus(32, description = "DMA Block written to SDRAM", reset = 0)
        self.blk_rem =    CSRStatus(32, description = "How many block remaining; bit 31 is RD", reset = 0)
        self.dma_status = CSRStatus(fields = [CSRField("rd_fsm_busy", 1, description = "Read FSM is doing some work"),
                                              CSRField("wr_fsm_busy", 1, description = "Write FSM is doing some work"),
                                              CSRField("has_wr_data", 1, description = "Data available to write to SDRAM"),
                                              CSRField("has_requests", 1, description = "There's outstanding requests to the SBus"),
                                              CSRField("has_rd_data", 1, description = "Data available to write to SBus"),
        ])
        self.wr_tosdram = CSRStatus(32, description = "Last address written to SDRAM")
        
        #if (do_checksum):
        self.checksum = CSRStorage(data_width_bits, write_from_dev=True, description = "checksum (XOR)");

        self.submodules.req_r_fsm = req_r_fsm = FSM(reset_state="Reset")
        self.submodules.req_w_fsm = req_w_fsm = FSM(reset_state="Reset")

        self.comb += self.dma_status.fields.rd_fsm_busy.eq(~req_r_fsm.ongoing("Idle")) # Read FSM Busy
        self.comb += self.dma_status.fields.wr_fsm_busy.eq(~req_w_fsm.ongoing("Idle")) # Write FSM Busy
        self.comb += self.dma_status.fields.has_wr_data.eq(self.fromsbus_fifo.readable) # Some data available to write to memory
        
        # The next two status bits reflect stats in the SBus clock domain
        self.submodules.fromsbus_req_fifo_readable_sync = BusSynchronizer(width = 1, idomain = "sbus", odomain = "sys")
        fromsbus_req_fifo_readable_in_sys = Signal()
        self.comb += self.fromsbus_req_fifo_readable_sync.i.eq(self.fromsbus_req_fifo.readable)
        self.comb += fromsbus_req_fifo_readable_in_sys.eq(self.fromsbus_req_fifo_readable_sync.o)

        # w/o this extra delay, the driver sees an outdated checksum for some reason...
        # there's probably a more fundamental issue :-(
        # note: replaced PulseSynchronizer with BusSynchronizer, should I retry w/o this ?
        fromsbus_req_fifo_readable_in_sys_cnt = Signal(5)
        self.sync += If(fromsbus_req_fifo_readable_in_sys,
                        fromsbus_req_fifo_readable_in_sys_cnt.eq(0x1F)
                     ).Else(
                         If(fromsbus_req_fifo_readable_in_sys_cnt > 0,
                            fromsbus_req_fifo_readable_in_sys_cnt.eq(fromsbus_req_fifo_readable_in_sys_cnt - 1)
                         )
                     )
        #self.comb += self.dma_status.fields.has_requests.eq(fromsbus_req_fifo_readable_in_sys) # we still have outstanding requests
        self.comb += self.dma_status.fields.has_requests.eq(fromsbus_req_fifo_readable_in_sys | (fromsbus_req_fifo_readable_in_sys_cnt != 0)) # we still have outstanding requests, or had recently
        
        self.submodules.tosbus_fifo_readable_sync = BusSynchronizer(width = 1, idomain = "sbus", odomain = "sys")
        tosbus_fifo_readable_in_sys = Signal()
        self.comb += self.tosbus_fifo_readable_sync.i.eq(self.tosbus_fifo.readable)
        self.comb += tosbus_fifo_readable_in_sys.eq(self.tosbus_fifo_readable_sync.o)
        self.comb += self.dma_status.fields.has_rd_data.eq(tosbus_fifo_readable_in_sys)  # there's still data to be sent to memory; this will drop before the last SBus Master Cycle is finished, but then the SBus is busy so the host won't be able to read the status before the cycle is finished so we're good

        ongoing_m1 = Signal()
        ongoing = Signal()
        temp_irq = Signal()
        self.irq = Signal()

        self.sync += ongoing_m1.eq(ongoing)
        self.sync += ongoing.eq(self.dma_status.fields.rd_fsm_busy  |
                                self.dma_status.fields.wr_fsm_busy  |
                                self.dma_status.fields.has_wr_data  |
                                self.dma_status.fields.has_requests |
                                self.dma_status.fields.has_rd_data  |
                                (self.blk_cnt.fields.blk_cnt != 0))
        
        self.sync += temp_irq.eq((ongoing_m1 & ~ongoing) | # irq on falling edge of ongoing
                                 (temp_irq & ~self.irqctrl.fields.irq_clear & ~(~ongoing_m1 & ongoing))) # keep irq until cleared or rising edge of ongoing
        
        self.comb += self.irq.eq(temp_irq & self.irqctrl.fields.irq_enable)
        
        self.sync += If(self.irqctrl.fields.irq_clear, ## auto-reset irq_clear
                        self.irqctrl.we.eq(1),
                        self.irqctrl.dat_w.eq(self.irqctrl.storage & 0xFFFFFFFD)).Else(
                            self.irqctrl.we.eq(0),
                        )
        
        #pad_SBUS_DATA_OE_LED = platform.request("SBUS_DATA_OE_LED")
        #self.comb += pad_SBUS_DATA_OE_LED.eq(self.irq)
        
        #self.comb += self.dma_status.status[16:17].eq(self.wishbone_w_master.cyc) # show the WB iface status (W)
        #self.comb += self.dma_status.status[17:18].eq(self.wishbone_w_master.stb)
        #self.comb += self.dma_status.status[18:19].eq(self.wishbone_w_master.we)
        #self.comb += self.dma_status.status[19:20].eq(self.wishbone_w_master.ack)
        #self.comb += self.dma_status.status[20:21].eq(self.wishbone_w_master.err)
        
        #self.comb += self.dma_status.status[24:25].eq(self.wishbone_r_master.cyc) # show the WB iface status (R)
        #self.comb += self.dma_status.status[25:26].eq(self.wishbone_r_master.stb)
        #self.comb += self.dma_status.status[26:27].eq(self.wishbone_r_master.we)
        #self.comb += self.dma_status.status[27:28].eq(self.wishbone_r_master.ack)
        #self.comb += self.dma_status.status[28:29].eq(self.wishbone_r_master.err)
        
        req_r_fsm.act("Reset",
                    NextState("Idle")
        )
        req_r_fsm.act("Idle",
                    If(((self.blk_cnt.fields.blk_cnt != 0) & # checking self.blk_cnt.re might be too transient ? -> need to auto-reset
                        (~self.blk_cnt.fields.rd_wr)), # !read -> write
                       NextValue(local_r_addr, self.blk_addr.storage),
                       NextValue(dma_r_addr, self.dma_addr.storage),
                       NextValue(self.blk_rem.status, Cat(self.blk_cnt.fields.blk_cnt, Signal(32-max_block_bits, reset = 0))),
                       NextState("ReqFromMemory")
                    ).Elif(((self.blk_cnt.fields.blk_cnt != 0) & # checking self.blk_cnt.re might be too transient ? -> need to auto-reset
                            (self.blk_cnt.fields.rd_wr)), # read
                           NextValue(local_r_addr, self.blk_addr.storage),
                           NextValue(dma_r_addr, self.dma_addr.storage),
                           NextValue(self.blk_rem.status, Cat(self.blk_cnt.fields.blk_cnt, Signal(32-max_block_bits, reset = 0))),
                           NextState("QueueReqToMemory")
                    )
        )
        req_r_fsm.act("ReqFromMemory",
                      self.dram_dma_reader.sink.address.eq(local_r_addr),
                      self.dram_dma_reader.sink.valid.eq(1),
                      If(self.dram_dma_reader.sink.ready,
                         NextState("WaitForData")
                      )
        )
        req_r_fsm.act("WaitForData",
                      If(self.dram_dma_reader.source.valid & self.tosbus_fifo.writable,
                         self.tosbus_fifo.we.eq(1),
                         tosbus_fifo_din.address.eq(dma_r_addr),
                         tosbus_fifo_din.data.eq(self.dram_dma_reader.source.data),
                         If(do_checksum,
                            self.checksum.we.eq(1),
                            self.checksum.dat_w.eq(self.checksum.storage ^ self.dram_dma_reader.source.data),
                         ),
                         self.dram_dma_reader.source.ready.eq(1),
                         NextValue(self.last_blk.status, local_r_addr),
                         NextValue(self.last_dma.status, dma_r_addr),
                         NextValue(self.blk_rem.status, self.blk_rem.status - 1),
                         If(self.blk_rem.status[0:max_block_bits] <= 1,
                            self.blk_cnt.we.eq(1), ## auto-reset
                            self.blk_cnt.dat_w.eq(0),
                            NextState("Idle"),
                         ).Else(
                             NextValue(local_r_addr, local_r_addr + 1),
                             NextValue(dma_r_addr, dma_r_addr + data_width),
                             NextState("ReqFromMemory"),
                         )
                      )
        )
        req_r_fsm.act("QueueReqToMemory",
                      If(self.fromsbus_req_fifo.writable,
                         self.fromsbus_req_fifo.we.eq(1),
                         fromsbus_req_fifo_din.blkaddress.eq(local_r_addr),
                         fromsbus_req_fifo_din.dmaaddress.eq(dma_r_addr),
                         NextValue(self.last_blk.status, local_r_addr),
                         NextValue(self.last_dma.status, dma_r_addr),
                         NextValue(self.blk_rem.status, self.blk_rem.status - 1),
                         If(self.blk_rem.status[0:max_block_bits] <= 1,
                            self.blk_cnt.we.eq(1), ## auto-reset
                            self.blk_cnt.dat_w.eq(0),
                            NextState("Idle"),
                         ).Else(
                             NextValue(local_r_addr, local_r_addr + 1),
                             NextValue(dma_r_addr, dma_r_addr + data_width),
                             NextValue(self.blk_rem.status, self.blk_rem.status - 1),
                             NextState("QueueReqToMemory"), #redundant
                         )
                      )
        )

        
#        req_w_fsm.act("Reset",
#                    NextState("Idle")
#        )
#        req_w_fsm.act("Idle",
#                    If(self.fromsbus_fifo.readable &
#                       ~self.wishbone_w_master.ack,
#                       self.fromsbus_fifo.re.eq(1),
#                       NextValue(self.wishbone_w_master.cyc, 1),
#                       NextValue(self.wishbone_w_master.stb, 1),
#                       NextValue(self.wishbone_w_master.sel, 2**len(self.wishbone_w_master.sel)-1),
#                       NextValue(self.wishbone_w_master.we, 1),
#                       NextValue(self.wishbone_w_master.adr, self.fromsbus_fifo.dout[0:blk_addr_width]),
#                       NextValue(self.wishbone_w_master.dat_w, self.fromsbus_fifo.dout[blk_addr_width:(blk_addr_width + data_width_bits)]),
#                       NextValue(self.wr_tosdram.status, self.fromsbus_fifo.dout[0:blk_addr_width]),
#                       NextState("WaitForAck")
#                    )
#        )
#        req_w_fsm.act("WaitForAck",
#                    If(self.wishbone_w_master.ack,
#                       NextValue(self.wishbone_w_master.cyc, 0),
#                       NextValue(self.wishbone_w_master.stb, 0),
#                       NextState("Idle"),
#                    )
#        )

        req_w_fsm.act("Reset",
                    NextState("Idle")
        )
        req_w_fsm.act("Idle",
                      If(self.fromsbus_fifo.readable,
                         self.dram_dma_writer.sink.address.eq(fromsbus_fifo_dout.blkaddress),
                         self.dram_dma_writer.sink.data.eq(fromsbus_fifo_dout.data),
                         self.dram_dma_writer.sink.valid.eq(1),
                         NextValue(self.wr_tosdram.status, fromsbus_fifo_dout.blkaddress),
                         If(self.dram_dma_writer.sink.ready,
                            self.fromsbus_fifo.re.eq(1),
                            NextValue(self.dma_wrdone.status, self.dma_wrdone.status + 1),
                            If(do_checksum,
                               self.checksum.we.eq(1),
                               self.checksum.dat_w.eq(self.checksum.storage ^ fromsbus_fifo_dout.data),
                            )
                         )
                      )
        )
コード例 #2
0
    def __init__(self, dram_port, fifo_depth=512, genlock_stream=None):
        self.sink = sink = stream.Endpoint(
            frame_dma_layout)  # "inputs" are the DMA frame parameters
        self.source = source = stream.Endpoint([
            ("data", dram_port.dw)
        ])  # "output" is the data stream

        # # #

        self.submodules.dma = LiteDRAMDMAReader(dram_port, fifo_depth, True)
        self.submodules.fsm = fsm = FSM(reset_state="IDLE")

        shift = log2_int(dram_port.dw // 8)
        base = Signal(dram_port.aw)
        length = Signal(dram_port.aw)
        offset = Signal(dram_port.aw)
        self.delay_base = CSRStorage(32)
        delay_base = Signal(32)
        self.line_align = CSRStorage(16)
        line_align = Signal(16)
        self.line_skip = CSRStorage(32)
        line_skip = Signal(32)
        self.hres_out = CSRStorage(16)
        self.vres_out = CSRStorage(16)
        self.comb += [
            base.eq(
                sink.base[shift:]
            ),  # ignore the lower bits of the base + length to match the DMA's expectations
            length.eq(
                sink.length[shift:]
            ),  # need to noodle on what that expectation is, exactly...
        ]
        hres = Signal(16)
        vres = Signal(16)
        self.comb += [
            hres.eq(self.hres_out.storage),
            vres.eq(self.vres_out.storage),
        ]
        hcount = Signal(16)
        vcount = Signal(16)
        linecount = Signal(16)
        self.field = Signal()
        vsyncpos = Signal(16)
        even_loc = Signal(16)
        odd_loc = Signal(16)
        self.even_pos = CSRStatus(16)
        self.odd_pos = CSRStatus(16)
        self.comb += [
            self.even_pos.status.eq(even_loc),
            self.odd_pos.status.eq(odd_loc),
        ]
        self.field_pos = CSRStorage(16)
        self.interlace = CSRStorage(
            2)  # bit 0 is enable, bit 1 is even/odd priority
        field_pos = Signal(16)
        interlace = Signal(2)
        self.submodules.sync_field_pos = BusSynchronizer(
            self.field_pos.size, "sys", "pix_o")
        self.submodules.sync_interlace = BusSynchronizer(
            self.interlace.size, "sys", "pix_o")
        self.submodules.sync_delay_base = BusSynchronizer(
            self.delay_base.size, "sys", "pix_o")
        self.submodules.sync_line_skip = BusSynchronizer(
            self.line_skip.size, "sys", "pix_o")
        self.submodules.sync_line_align = BusSynchronizer(
            self.line_align.size, "sys", "pix_o")
        self.comb += [
            self.sync_field_pos.i.eq(self.field_pos.storage),
            self.sync_interlace.i.eq(self.interlace.storage),
            self.sync_delay_base.i.eq(self.delay_base.storage),
            self.sync_line_skip.i.eq(self.line_skip.storage),
            self.sync_line_align.i.eq(self.line_align.storage),
            field_pos.eq(self.sync_field_pos.o),
            interlace.eq(self.sync_interlace.o),
            delay_base.eq(self.sync_delay_base.o),
            line_skip.eq(self.sync_line_skip.o),
            line_align.eq(self.sync_line_align.o),
        ]
        squash = Signal()

        if genlock_stream != None:
            self.v = Signal()
            self.v_r = Signal()
            self.sof = Signal()
            self.sync += [
                self.v.eq(genlock_stream.vsync),
                self.v_r.eq(self.v),
                self.sof.eq(self.v & ~self.v_r),
            ]
            self.h = Signal()
            self.h_r = Signal()
            self.sol = Signal()
            self.sync += [
                self.h.eq(genlock_stream.hsync),
                self.h_r.eq(self.h),
                self.sol.eq(self.h & ~self.h_r),
            ]
            self.sync += [
                If(self.sol, vsyncpos.eq(0)).Else(vsyncpos.eq(vsyncpos + 1)),
                If(
                    self.sof,
                    self.field.eq(~self.field),
                    If(
                        self.field,
                        odd_loc.eq(vsyncpos),
                    ).Else(even_loc.eq(vsyncpos), ),
                ),
            ]

        if genlock_stream == None:
            fsm.act(
                "IDLE",
                NextValue(offset, 0),
                If(
                    sink.valid,  # if our parameters are valid, start reading
                    NextState("READ")).Else(dram_port.flush.eq(1), ))
            fsm.act(
                "READ",
                self.dma.sink.valid.eq(
                    1
                ),  # tell the DMA reader that we've got a valid address for it
                If(
                    self.dma.sink.
                    ready,  # if the LiteDRAMDMAReader shows it's ready for an address (e.g. taken the current address)
                    NextValue(offset, offset + 1),  # increment the offset
                    If(
                        offset == (length - 1),  # at the end...
                        self.sink.ready.eq(
                            1),  # indicate we're ready for more parameters
                        NextState("IDLE"))))
        else:
            fsm.act(
                "IDLE",
                NextValue(linecount, 0),
                If(
                    self.interlace.storage[0],
                    # interlace
                    If(
                        self.field ^ interlace[1] ^ (
                            odd_loc < vsyncpos
                        ),  # xor against actual odd_loc vs vsyncpos in case we caught the wrong field polarity
                        NextValue(offset, delay_base),
                        NextValue(hcount, 0),
                        NextValue(vcount, 0),
                    ).Else(
                        NextValue(offset, delay_base + hres + 1),
                        NextValue(hcount, 0),
                        NextValue(vcount, 1),
                    )).Else(
                        # non-interlace
                        NextValue(offset, delay_base),
                        NextValue(hcount, 0),
                        NextValue(vcount, 0),
                    ),
                If(
                    sink.valid,  # if our parameters are valid, start reading
                    If(
                        line_align == 0,
                        NextState("READ"),
                    ).Else(NextState("WAIT_LINE"), )).Else(
                        dram_port.flush.eq(1), ))
            fsm.act(
                "WAIT_LINE",  # insert dummy waits until wait_line is done
                squash.eq(1),
                self.dma.sink.valid.eq(
                    1
                ),  # tell the DMA reader that we've got a valid address for it
                If(
                    self.dma.sink.
                    ready,  # if the LiteDRAMDMAReader shows it's ready for an address (e.g. taken the current address)
                    If(
                        linecount < line_align,
                        NextValue(linecount, linecount + 1),
                    ).Else(NextState("READ"), )))
            fsm.act(
                "READ",
                self.dma.sink.valid.eq(
                    1
                ),  # tell the DMA reader that we've got a valid address for it
                If(
                    self.dma.sink.
                    ready,  # if the LiteDRAMDMAReader shows it's ready for an address (e.g. taken the current address)
                    NextValue(hcount, hcount + 1),
                    If(
                        hcount >= hres,
                        If(
                            interlace[0],
                            # interlaced
                            NextValue(offset,
                                      offset + line_skip + 1 + hres + 1),
                            NextValue(hcount, 0),
                            NextValue(vcount, vcount + 2),
                        ).Else(
                            # not interlaced
                            NextValue(offset, offset + line_skip + 1),
                            NextValue(hcount, 0),
                            NextValue(vcount, vcount + 1),
                        )).Else(
                            NextValue(offset,
                                      offset + 1),  # increment the offset
                        ),
                    If(
                        (offset >=
                         (length - 1)) | vcount >= vres,  # at the end...
                        self.sink.ready.eq(
                            1),  # indicate we're ready for more parameters
                        NextState("WAIT_SOF"))))
            fsm.act(
                "WAIT_SOF",  # wait till vsync/start of frame
                If(self.sof, NextState("IDLE")))

        self.comb += [
            self.dma.sink.address.eq(
                base +
                offset),  # input to the DMA is an address of base + offset
            self.dma.source.connect(
                self.source
            )  # connect the DMA's output to the output of this module
        ]
コード例 #3
0
    def __init__(self, soc, sbus_bus):
        self.stat_ctrl = CSRStorage(fields = [CSRField("update", 1, description = "update")])
        self.submodules.sync_update = BusSynchronizer(width = 1, idomain="sys", odomain="sbus")
        self.comb += self.sync_update.i.eq(self.stat_ctrl.fields.update)
        self.comb += sbus_bus.stat_update.eq(self.sync_update.o)
        
        self.live_stat_cycle_counter = CSRStatus(32, description="live_stat_cycle_counter")
        self.stat_cycle_counter = CSRStatus(32, description="stat_cycle_counter")
        self.stat_slave_start_counter = CSRStatus(32, description="stat_slave_start_counter")
        self.stat_slave_done_counter = CSRStatus(32, description="stat_slave_done_counter")
        self.stat_slave_rerun_counter = CSRStatus(32, description="stat_slave_rerun_counter")
        #self.stat_slave_rerun_last_pa = CSRStatus(32, description="stat_slave_rerun_last_pa")
        #self.stat_slave_rerun_last_state = CSRStatus(32, description="stat_slave_rerun_last_state")
        self.stat_slave_early_error_counter = CSRStatus(32, description="stat_slave_early_error_counter")
        self.stat_master_start_counter = CSRStatus(32, description="stat_master_start_counter")
        self.stat_master_done_counter = CSRStatus(32, description="stat_master_done_counter")
        self.stat_master_error_counter = CSRStatus(32, description="stat_master_error_counter")
        self.stat_master_rerun_counter = CSRStatus(32, description="stat_master_rerun_counter")
        self.sbus_master_error_virtual = CSRStatus(32, description="sbus_master_error_virtual")
 
        self.submodules.sync_live_stat_cycle_counter = BusSynchronizer(width = 32, idomain="sbus", odomain="sys")
        self.comb += self.sync_live_stat_cycle_counter.i.eq(sbus_bus.stat_cycle_counter)
        self.comb += self.live_stat_cycle_counter.status.eq(self.sync_live_stat_cycle_counter.o)
 
        self.submodules.sync_stat_cycle_counter = BusSynchronizer(width = 32, idomain="sbus", odomain="sys")
        self.comb += self.sync_stat_cycle_counter.i.eq(sbus_bus.buf_stat_cycle_counter)
        self.comb += self.stat_cycle_counter.status.eq(self.sync_stat_cycle_counter.o)
        
        self.submodules.sync_stat_slave_start_counter = BusSynchronizer(width = 32, idomain="sbus", odomain="sys");
        self.comb += self.sync_stat_slave_start_counter.i.eq(sbus_bus.buf_stat_slave_start_counter)
        self.comb += self.stat_slave_start_counter.status.eq(self.sync_stat_slave_start_counter.o)
        self.submodules.sync_stat_slave_done_counter = BusSynchronizer(width = 32, idomain="sbus", odomain="sys");
        self.comb += self.sync_stat_slave_done_counter.i.eq(sbus_bus.buf_stat_slave_done_counter)
        self.comb += self.stat_slave_done_counter.status.eq(self.sync_stat_slave_done_counter.o)
        self.submodules.sync_stat_slave_rerun_counter = BusSynchronizer(width = 32, idomain="sbus", odomain="sys");
        self.comb += self.sync_stat_slave_rerun_counter.i.eq(sbus_bus.buf_stat_slave_rerun_counter)
        self.comb += self.stat_slave_rerun_counter.status.eq(self.sync_stat_slave_rerun_counter.o)
        #self.submodules.sync_stat_slave_rerun_last_pa = BusSynchronizer(width = 32, idomain="sbus", odomain="sys");
        #self.comb += self.sync_stat_slave_rerun_last_pa.i.eq(sbus_bus.stat_slave_rerun_last_pa) # no 'buf_'
        #self.comb += self.stat_slave_rerun_last_pa.status.eq(self.sync_stat_slave_rerun_last_pa.o)
        #self.submodules.sync_stat_slave_rerun_last_state = BusSynchronizer(width = 32, idomain="sbus", odomain="sys");
        #self.comb += self.sync_stat_slave_rerun_last_state.i.eq(sbus_bus.stat_slave_rerun_last_state) # no 'buf_'
        #self.comb += self.stat_slave_rerun_last_state.status.eq(self.sync_stat_slave_rerun_last_state.o)
        
        self.submodules.sync_stat_slave_early_error_counter = BusSynchronizer(width = 32, idomain="sbus", odomain="sys");
        self.comb += self.sync_stat_slave_early_error_counter.i.eq(sbus_bus.buf_stat_slave_early_error_counter)
        self.comb += self.stat_slave_early_error_counter.status.eq(self.sync_stat_slave_early_error_counter.o)
        self.submodules.sync_stat_master_start_counter = BusSynchronizer(width = 32, idomain="sbus", odomain="sys");
        self.comb += self.sync_stat_master_start_counter.i.eq(sbus_bus.buf_stat_master_start_counter)
        self.comb += self.stat_master_start_counter.status.eq(self.sync_stat_master_start_counter.o)
        self.submodules.sync_stat_master_done_counter = BusSynchronizer(width = 32, idomain="sbus", odomain="sys");
        self.comb += self.sync_stat_master_done_counter.i.eq(sbus_bus.buf_stat_master_done_counter)
        self.comb += self.stat_master_done_counter.status.eq(self.sync_stat_master_done_counter.o)
        self.submodules.sync_stat_master_error_counter = BusSynchronizer(width = 32, idomain="sbus", odomain="sys");
        self.comb += self.sync_stat_master_error_counter.i.eq(sbus_bus.buf_stat_master_error_counter)
        self.comb += self.stat_master_error_counter.status.eq(self.sync_stat_master_error_counter.o)
        self.submodules.sync_stat_master_rerun_counter = BusSynchronizer(width = 32, idomain="sbus", odomain="sys");
        self.comb += self.sync_stat_master_rerun_counter.i.eq(sbus_bus.buf_stat_master_rerun_counter)
        self.comb += self.stat_master_rerun_counter.status.eq(self.sync_stat_master_rerun_counter.o)
        self.submodules.sync_sbus_master_error_virtual = BusSynchronizer(width = 32, idomain="sbus", odomain="sys");
        self.comb += self.sync_sbus_master_error_virtual.i.eq(sbus_bus.buf_sbus_master_error_virtual)
        self.comb += self.sbus_master_error_virtual.status.eq(self.sync_sbus_master_error_virtual.o)
コード例 #4
0
    def __init__(self, dram_port):
        ashift, awidth = get_ashift_awidth(dram_port)
        self.reset = CSR()
        self.start = CSR()
        self.done = CSRStatus()
        self.run = CSRStorage(reset=1)
        self.ready = CSRStatus()
        self.base = CSRStorage(awidth)
        self.end = CSRStorage(awidth)
        self.length = CSRStorage(awidth)
        self.random = CSRStorage(fields=[
            CSRField("data", size=1),
            CSRField("addr", size=1),
        ])
        self.ticks = CSRStatus(32)
        self.errors = CSRStatus(32)

        # # #

        clock_domain = dram_port.clock_domain

        core = _LiteDRAMBISTChecker(dram_port)
        core = ClockDomainsRenamer(clock_domain)(core)
        self.submodules += core

        if clock_domain != "sys":
            reset_sync = PulseSynchronizer("sys", clock_domain)
            start_sync = PulseSynchronizer("sys", clock_domain)
            self.submodules += reset_sync, start_sync
            self.comb += [
                reset_sync.i.eq(self.reset.re),
                core.reset.eq(reset_sync.o),
                start_sync.i.eq(self.start.re),
                core.start.eq(start_sync.o)
            ]

            done_sync = BusSynchronizer(1, clock_domain, "sys")
            self.submodules += done_sync
            self.comb += [
                done_sync.i.eq(core.done),
                self.done.status.eq(done_sync.o)
            ]

            run_sync = BusSynchronizer(1, clock_domain, "sys")
            ready_sync = BusSynchronizer(1, clock_domain, "sys")
            self.submodules += run_sync, ready_sync
            self.comb += [
                run_sync.i.eq(self.run.storage),
                core.run.eq(run_sync.o),
                ready_sync.i.eq(core.ready),
                self.ready.status.eq(ready_sync.o),
            ]

            base_sync = BusSynchronizer(awidth, "sys", clock_domain)
            end_sync = BusSynchronizer(awidth, "sys", clock_domain)
            length_sync = BusSynchronizer(awidth, "sys", clock_domain)
            self.submodules += base_sync, end_sync, length_sync
            self.comb += [
                base_sync.i.eq(self.base.storage),
                core.base.eq(base_sync.o),
                end_sync.i.eq(self.end.storage),
                core.end.eq(end_sync.o),
                length_sync.i.eq(self.length.storage),
                core.length.eq(length_sync.o)
            ]

            self.specials += [
                MultiReg(self.random.fields.data, core.random_data,
                         clock_domain),
                MultiReg(self.random.fields.addr, core.random_addr,
                         clock_domain),
            ]

            ticks_sync = BusSynchronizer(32, clock_domain, "sys")
            self.submodules += ticks_sync
            self.comb += [
                ticks_sync.i.eq(core.ticks),
                self.ticks.status.eq(ticks_sync.o)
            ]

            errors_sync = BusSynchronizer(32, clock_domain, "sys")
            self.submodules += errors_sync
            self.comb += [
                errors_sync.i.eq(core.errors),
                self.errors.status.eq(errors_sync.o)
            ]
        else:
            self.comb += [
                core.reset.eq(self.reset.re),
                core.start.eq(self.start.re),
                self.done.status.eq(core.done),
                core.run.eq(self.run.storage),
                self.ready.status.eq(core.ready),
                core.base.eq(self.base.storage),
                core.end.eq(self.end.storage),
                core.length.eq(self.length.storage),
                core.random_data.eq(self.random.fields.data),
                core.random_addr.eq(self.random.fields.addr),
                self.ticks.status.eq(core.ticks),
                self.errors.status.eq(core.errors)
            ]
コード例 #5
0
ファイル: fpdrecv.py プロジェクト: tmbinc/fpdlink
    def __init__(self, lvds_in, _debug, sim = False):
        self._adjust = CSRStorage(16, atomic_write=True)
        self._adjust_direction = CSRStorage(1)
        
        self._adjptotal = CSRStatus(32)
        self._adjmtotal = CSRStatus(32)
        
        self._lock = CSRStatus(1)
        
        self._invert = CSRStorage(1)
        self._update_counter = CSRStorage(1)
        
        self._debug_mux = CSRStorage(8)
        
        self.submodules.adjptotal_sync = BusSynchronizer(32, "pix1x", "sys")
        self.submodules.adjmtotal_sync = BusSynchronizer(32, "pix1x", "sys")
    
        # IBUFDS        	
        lvds_se = Signal()
        if not sim:
            self.specials += Instance("IBUFDS", i_I=lvds_in[0], i_IB=lvds_in[1], o_O=lvds_se)

        debug = Signal(len(_debug))
        self.comb += _debug.eq(debug)
        
        d0 = Signal()
        self.sync.pix1x += [
            d0.eq(~d0)
        ]
        
        # SERDES
        self.i = Signal(8)
        
        self.comb += debug[0].eq(lvds_se)

        pd_valid = Signal()
        pd_incdec = Signal()
        pd_edge = Signal()
        pd_cascade = Signal()
        self.serdesstrobe = Signal()
        if not sim:
            self.specials += Instance("ISERDES2",
                                      p_SERDES_MODE="MASTER",
                                      p_BITSLIP_ENABLE="FALSE", p_DATA_RATE="SDR", p_DATA_WIDTH=8,
                                      p_INTERFACE_TYPE="RETIMED",

                                      i_D=lvds_se,
                                      o_Q4=self.i[7], o_Q3=self.i[6], o_Q2=self.i[5], o_Q1=self.i[4],

                                      i_BITSLIP=0, i_CE0=1, i_RST=0,
                                      i_CLK0=ClockSignal("pix8x"), i_CLKDIV=ClockSignal("pix1x"),
                                      i_IOCE=self.serdesstrobe,

                                      o_VALID=pd_valid, o_INCDEC=pd_incdec,
                                      i_SHIFTIN=pd_edge, o_SHIFTOUT=pd_cascade)
            self.specials += Instance("ISERDES2",
                                      p_SERDES_MODE="SLAVE",
                                      p_BITSLIP_ENABLE="FALSE", p_DATA_RATE="SDR", p_DATA_WIDTH=8,
                                      p_INTERFACE_TYPE="RETIMED",

                                      i_D=lvds_se,
                                      o_Q4=self.i[3], o_Q3=self.i[2], o_Q2=self.i[1], o_Q1=self.i[0],

                                      i_BITSLIP=0, i_CE0=1, i_RST=0,
                                      i_CLK0=ClockSignal("pix8x"), i_CLKDIV=ClockSignal("pix1x"),
                                      i_IOCE=self.serdesstrobe,
                                      i_SHIFTIN=pd_cascade, o_SHIFTOUT=pd_edge)

        self.lock = Signal()        
        self.submodules.sampler = ClockDomainsRenamer({"sys": "pix1x"})(Sampler())

        fifo = AsyncFIFO(28, 64)
        self.submodules.fifo = ClockDomainsRenamer(
            {"write":"pix1x", "read":"sys"})(fifo)

        self.submodules.slip = PulseSynchronizer(idomain = "sys", odomain = "pix1x")

        self.submodules.decoder = Decoder()
        
        # CDC for adjust set
        self.submodules.adjust_sync = BusSynchronizer(1 + 16, "sys", "pix1x")
        self.comb += [
            self.adjust_sync.i[-1].eq(self._adjust_direction.storage),
            self.adjust_sync.i[:16].eq(self._adjust.storage),
            self.sampler.adjust_direction.eq(self.adjust_sync.o[-1]),
            self.sampler.adjust_inc.eq(self.adjust_sync.o[:16]),
        ]
        
        self.comb += [
            # SERDES -> sampler
#            If(self._invert.storage,
#              self.sampler.i.eq(self.i[::-1]))
#            .Else(
#              self.sampler.i.eq(~self.i[::-1])),
            self.sampler.i.eq(self.i[::-1]),
            
            # sampler -> fifo
            self.fifo.din.eq(self.sampler.q),
            self.fifo.we.eq(self.sampler.s),
            self.fifo.re.eq(1),
            
            # fifo -> decoder
            self.decoder.i.eq(self.fifo.dout[::-1]),
            self.decoder.s.eq(self.fifo.readable),
            
            # decoder slip request -> pulse sync -> sampler slip
            self.slip.i.eq(self.decoder.slip),
            self.sampler.slip.eq(self.slip.o),

#            self.source.stb.eq(self.decoder.qs),
#            self.source.d.eq(self.decoder.q[24:32]),
            self.lock.eq(self.decoder.lock),
        ]
        
        # capture decoder output on decoder.qs
        self.decoder_q = Signal(32)
        self.sync += [
            If(self.decoder.qs,
              self.decoder_q.eq(self.decoder.q)
            )
        ]

#        self.comb += debug[11].eq(self.source.stb)
#        self.comb += debug[9].eq(self.lock)
        self.samplerq = Signal(28)
        self.submodules.samplerq_sync = BusSynchronizer(idomain = "pix1x", odomain = "sys", width=len(self.samplerq))
        self.comb += [
          self.samplerq_sync.i.eq(self.sampler.q),
          self.samplerq.eq(self.samplerq_sync.o)
        ]
        
        self.comb += [ 
          If(self._debug_mux.storage == 0,
              debug[1:9].eq(self.sampler.edge)).
          Elif(self._debug_mux.storage == 1,
            debug[1:9].eq(self.decoder.i[0:8])).
          Elif(self._debug_mux.storage == 2,
            debug[1:9].eq(self.decoder.i[8:16])).
          Elif(self._debug_mux.storage == 3,
            debug[1:9].eq(self.decoder.i[16:24])).
          Elif(self._debug_mux.storage == 4,
            debug[1:9].eq(self.decoder.i[24:28])).
          Elif(self._debug_mux.storage == 5,
            debug[1:9].eq(self.samplerq[0:8])).
          Elif(self._debug_mux.storage == 6,
            debug[1:9].eq(self.samplerq[8:16])).
          Elif(self._debug_mux.storage == 7,
            debug[1:9].eq(self.samplerq[16:24])).
          Elif(self._debug_mux.storage == 8,
            debug[1:9].eq(self.samplerq[24:28])).
          Elif(self._debug_mux.storage == 9,
            debug[1:9].eq(self.sampler.sr))
          ]
#        self.comb += debug[2].eq(self.sampler.numbits[0])
        self.comb += debug[0].eq(d0)

#        self.comb += debug[6].eq(self.i[0])
#        self.comb += debug[8].eq(self.sampler.s)
        self.comb += debug[10].eq(self.fifo.readable)
        self.comb += debug[11].eq(self.decoder.lock)
        self.comb += debug[12].eq(self.decoder.qs)

#        self.comb += debug[10].eq(self.sampler.phase[0])
#        self.comb += debug[11].eq(self.sampler.phase[1])
#        self.comb += debug[12].eq(self.sampler.phase[2])
        
        self.comb += self._lock.status.eq(self.decoder.lock)

        # status (via synchronizer)
        self.comb += [
            self.adjptotal_sync.i.eq(self.sampler.adjptotal),
            self.adjmtotal_sync.i.eq(self.sampler.adjmtotal),
        ]
        
        self.sync += [
            If(self._update_counter.storage, 
                self._adjptotal.status.eq(self.adjptotal_sync.o),
                self._adjmtotal.status.eq(self.adjmtotal_sync.o),
            )
        ]

        # output
        self.source = Endpoint([('d', 8)])
        
        self.submodules.fifo_read_fsm = FSM()
        self.fifo_read_fsm.act("B0",
            If (self.source.ack & self.decoder.qs & self.decoder.lock,
                NextState("B1")
            ),
            self.source.stb.eq(self.decoder.qs & self.decoder.lock,),
            self.source.payload.d.eq(Cat(self.decoder.q[8:14], self.decoder.q[15:17]))
        )

        self.fifo_read_fsm.act("B1",
            If (self.source.ack,
                NextState("B0")
            ),
            self.source.stb.eq(1),
            self.source.payload.d.eq(self.decoder_q[0:8])
        )
コード例 #6
0
    def __init__(self, phy, csr_data_width=32):
        self.sink = stream.Endpoint([("data", 32)])
        self.source = stream.Endpoint([("data", 32)])

        self.argument = CSRStorage(32)
        self.command = CSRStorage(32)
        if csr_data_width == 8:
            self.issue_cmd = CSRStorage(1)

        self.response = CSRStatus(120)

        self.cmdevt = CSRStatus(32)
        self.dataevt = CSRStatus(32)

        self.blocksize = CSRStorage(16)
        self.blockcount = CSRStorage(32)

        self.datatimeout = CSRStorage(32, reset=2**16)
        self.cmdtimeout = CSRStorage(32, reset=2**16)

        self.datawcrcclear = CSRStorage()
        self.datawcrcvalids = CSRStatus(32)
        self.datawcrcerrors = CSRStatus(32)

        # # #

        argument = Signal(32)
        command = Signal(32)
        response = Signal(120)
        cmdevt = Signal(32)
        dataevt = Signal(32)
        blocksize = Signal(16)
        blockcount = Signal(32)
        datatimeout = Signal(32)
        cmdtimeout = Signal(32)

        # sys to sd cdc
        self.specials += [
            MultiReg(self.argument.storage, argument, "sd"),
            MultiReg(self.command.storage, command, "sd"),
            MultiReg(self.blocksize.storage, blocksize, "sd"),
            MultiReg(self.blockcount.storage, blockcount, "sd"),
            MultiReg(self.datatimeout.storage, datatimeout, "sd"),
            MultiReg(self.cmdtimeout.storage, cmdtimeout, "sd")
        ]

        # sd to sys cdc
        response_cdc = BusSynchronizer(120, "sd", "sys")
        cmdevt_cdc = BusSynchronizer(32, "sd", "sys")
        dataevt_cdc = BusSynchronizer(32, "sd", "sys")
        self.submodules += response_cdc, cmdevt_cdc, dataevt_cdc
        self.comb += [
            response_cdc.i.eq(response),
            self.response.status.eq(response_cdc.o),
            cmdevt_cdc.i.eq(cmdevt),
            self.cmdevt.status.eq(cmdevt_cdc.o),
            dataevt_cdc.i.eq(dataevt),
            self.dataevt.status.eq(dataevt_cdc.o)
        ]

        self.submodules.new_command = PulseSynchronizer("sys", "sd")
        if csr_data_width == 8:
            self.comb += self.new_command.i.eq(self.issue_cmd.re)
        else:
            self.comb += self.new_command.i.eq(self.command.re)

        self.comb += [
            phy.cfg.blocksize.eq(blocksize),
            phy.cfg.datatimeout.eq(datatimeout),
            phy.cfg.cmdtimeout.eq(cmdtimeout),
            phy.dataw.crc_clear.eq(self.datawcrcclear.storage),
            self.datawcrcvalids.status.eq(phy.dataw.crc_valids),
            self.datawcrcerrors.status.eq(phy.dataw.crc_errors)
        ]

        self.submodules.crc7inserter = ClockDomainsRenamer("sd")(CRC(9, 7, 40))
        self.submodules.crc7checker = ClockDomainsRenamer("sd")(CRCChecker(
            9, 7, 120))
        self.submodules.crc16inserter = ClockDomainsRenamer("sd")(
            CRCUpstreamInserter())
        self.submodules.crc16checker = ClockDomainsRenamer("sd")(
            CRCDownstreamChecker())

        self.submodules.upstream_cdc = ClockDomainsRenamer({
            "write": "sys",
            "read": "sd"
        })(stream.AsyncFIFO(self.sink.description, 4))
        self.submodules.downstream_cdc = ClockDomainsRenamer({
            "write": "sd",
            "read": "sys"
        })(stream.AsyncFIFO(self.source.description, 4))

        self.submodules.upstream_converter = ClockDomainsRenamer("sd")(
            stream.StrideConverter([('data', 32)], [('data', 8)],
                                   reverse=True))
        self.submodules.downstream_converter = ClockDomainsRenamer("sd")(
            stream.StrideConverter([('data', 8)], [('data', 32)],
                                   reverse=True))

        self.comb += [
            self.sink.connect(self.upstream_cdc.sink),
            self.upstream_cdc.source.connect(self.upstream_converter.sink),
            self.upstream_converter.source.connect(self.crc16inserter.sink),
            self.crc16checker.source.connect(self.downstream_converter.sink),
            self.downstream_converter.source.connect(self.downstream_cdc.sink),
            self.downstream_cdc.source.connect(self.source)
        ]

        self.submodules.fsm = fsm = ClockDomainsRenamer("sd")(FSM())

        csel = Signal(max=6)
        waitresp = Signal(2)
        dataxfer = Signal(2)
        cmddone = Signal(reset=1)
        datadone = Signal(reset=1)
        blkcnt = Signal(32)
        pos = Signal(2)

        cerrtimeout = Signal()
        cerrcrc_en = Signal()
        derrtimeout = Signal()
        derrwrite = Signal()
        derrread_en = Signal()

        self.comb += [
            waitresp.eq(command[0:2]),
            dataxfer.eq(command[5:7]),
            cmdevt.eq(
                Cat(cmddone, C(0, 1), cerrtimeout,
                    cerrcrc_en & ~self.crc7checker.valid)),
            dataevt.eq(
                Cat(datadone, derrwrite, derrtimeout,
                    derrread_en & ~self.crc16checker.valid)),
            self.crc7inserter.val.eq(Cat(argument, command[8:14], 1, 0)),
            self.crc7inserter.clr.eq(1),
            self.crc7inserter.enable.eq(1),
            self.crc7checker.val.eq(response)
        ]

        ccases = {}  # To send command and CRC
        ccases[0] = phy.sink.data.eq(Cat(command[8:14], 1, 0))
        for i in range(4):
            ccases[i + 1] = phy.sink.data.eq(argument[24 - 8 * i:32 - 8 * i])
        ccases[5] = [
            phy.sink.data.eq(Cat(1, self.crc7inserter.crc)),
            phy.sink.last.eq(waitresp == SDCARD_CTRL_RESPONSE_NONE)
        ]

        fsm.act(
            "IDLE", NextValue(pos, 0),
            If(self.new_command.o, NextValue(cmddone, 0),
               NextValue(cerrtimeout, 0), NextValue(cerrcrc_en, 0),
               NextValue(datadone, 0), NextValue(derrtimeout, 0),
               NextValue(derrwrite, 0), NextValue(derrread_en, 0),
               NextValue(response, 0), NextState("SEND_CMD")))

        fsm.act(
            "SEND_CMD", phy.sink.valid.eq(1), phy.sink.cmd_data_n.eq(1),
            phy.sink.rd_wr_n.eq(0), Case(csel, ccases),
            If(
                phy.sink.valid & phy.sink.ready,
                If(csel < 5, NextValue(csel, csel + 1)).Else(
                    NextValue(csel, 0),
                    If(waitresp == SDCARD_CTRL_RESPONSE_NONE,
                       NextValue(cmddone, 1),
                       NextState("IDLE")).Else(NextValue(cerrcrc_en, 1),
                                               NextState("RECV_RESP")))))

        fsm.act(
            "RECV_RESP",
            phy.sink.valid.eq(1),
            phy.sink.cmd_data_n.eq(1),
            phy.sink.rd_wr_n.eq(1),
            phy.sink.last.eq(dataxfer == SDCARD_CTRL_DATA_TRANSFER_NONE),
            If(
                waitresp == SDCARD_CTRL_RESPONSE_SHORT,
                phy.sink.data.eq(5)  # (5+1)*8 == 48bits
            ).Elif(
                waitresp == SDCARD_CTRL_RESPONSE_LONG,
                phy.sink.data.eq(16)  # (16+1)*8 == 136bits
            ),
            If(
                phy.source.valid,  # Wait for resp or timeout coming from phy
                phy.source.ready.eq(1),
                If(phy.source.status == SDCARD_STREAM_STATUS_TIMEOUT,
                   NextValue(cerrtimeout, 1), NextValue(cmddone, 1),
                   NextValue(datadone, 1), NextState("IDLE")).Elif(
                       phy.source.last,
                       # Check response CRC
                       NextValue(self.crc7checker.check, phy.source.data[1:8]),
                       NextValue(cmddone, 1),
                       If(dataxfer == SDCARD_CTRL_DATA_TRANSFER_READ,
                          NextValue(derrread_en, 1),
                          NextState("RECV_DATA")).Elif(
                              dataxfer == SDCARD_CTRL_DATA_TRANSFER_WRITE,
                              NextState("SEND_DATA")).Else(
                                  NextValue(datadone, 1), NextState("IDLE")),
                   ).Else(
                       NextValue(response, Cat(phy.source.data,
                                               response[0:112])))))

        fsm.act(
            "RECV_DATA",
            phy.sink.valid.eq(1),
            phy.sink.cmd_data_n.eq(0),
            phy.sink.rd_wr_n.eq(1),
            phy.sink.last.eq(blkcnt == (blockcount - 1)),
            phy.sink.data.eq(0),  # Read 1 block
            If(
                phy.source.valid,
                phy.source.ready.eq(1),
                If(
                    phy.source.status == SDCARD_STREAM_STATUS_OK,
                    self.crc16checker.sink.data.eq(
                        phy.source.data),  # Manual connect streams except ctrl
                    self.crc16checker.sink.valid.eq(phy.source.valid),
                    self.crc16checker.sink.last.eq(phy.source.last),
                    phy.source.ready.eq(self.crc16checker.sink.ready),
                    If(
                        phy.source.last & phy.source.ready,  # End of block
                        If(blkcnt < (blockcount - 1),
                           NextValue(blkcnt,
                                     blkcnt + 1), NextState("RECV_DATA")).Else(
                                         NextValue(blkcnt, 0),
                                         NextValue(datadone, 1),
                                         NextState("IDLE")))).Elif(
                                             phy.source.status ==
                                             SDCARD_STREAM_STATUS_TIMEOUT,
                                             NextValue(derrtimeout, 1),
                                             NextValue(blkcnt, 0),
                                             NextValue(datadone, 1),
                                             phy.source.ready.eq(1),
                                             NextState("IDLE"))))

        fsm.act(
            "SEND_DATA", phy.sink.valid.eq(self.crc16inserter.source.valid),
            phy.sink.cmd_data_n.eq(0), phy.sink.rd_wr_n.eq(0),
            phy.sink.last.eq(self.crc16inserter.source.last),
            phy.sink.data.eq(self.crc16inserter.source.data),
            self.crc16inserter.source.ready.eq(phy.sink.ready),
            If(
                self.crc16inserter.source.valid
                & self.crc16inserter.source.last
                & self.crc16inserter.source.ready,
                If(blkcnt < (blockcount - 1),
                   NextValue(blkcnt, blkcnt + 1)).Else(NextValue(blkcnt, 0),
                                                       NextValue(datadone, 1),
                                                       NextState("IDLE"))),
            If(
                phy.source.valid, phy.source.ready.eq(1),
                If(phy.source.status != SDCARD_STREAM_STATUS_DATAACCEPTED,
                   NextValue(derrwrite, 1))))
コード例 #7
0
    def __init__(self, platform):
        default_period = 325000000
        self.intro = ModuleDoc("""Watch Dog Timer
A watchdog timer for Betrusted. Once enabled, it cannot be disabled, and
it must have the reset_wdt bit written periodically to avoid a watchdog reset event.

If this does not happen, the WDT will attempt to toggle reset of the full chip via GSR.

The timeout period is specified in 'approximately 65MHz' (15.38ns) periods by the period register.
According to Xilinx, 'approximately' is +/-50%.

The register cannot be updated once the WDT is running.
        """)
        self.gsr = Signal()  # wire to the GSR line for the FPGA
        self.cfgmclk = Signal(
        )  # wire to FPGA's CFGMCLK ring oscillator, a "typical" 65MHz clock
        self.clock_domains.cd_wdt = ClockDomain()
        self.specials += Instance("BUFG",
                                  i_I=self.cfgmclk,
                                  o_O=self.cd_wdt.clk)
        platform.add_platform_command(
            "create_clock -name wdt -period 10.256 [get_nets {net}]",
            net=self.cd_wdt.clk)  # 65MHz + 50% tolerance

        ### WATCHDOG RESET, uses the extcomm_div divider to save on gates
        self.watchdog = CSRStorage(fields=[
            CSRField("reset_wdt",
                     size=1,
                     description=
                     "Write to this register to reset the watchdog timer",
                     pulse=True),
            CSRField(
                "enable",
                description=
                "Enable the watchdog timer. Cannot be disabled once enabled, except with a reset. Notably, a watchdog reset will disable the watchdog.",
                reset=0),
        ])
        reset_wdt = Signal()
        w_stretch = Signal(3)
        reset_wdt_sys = Signal()
        self.sync += [
            If(self.watchdog.fields.reset_wdt,
               w_stretch.eq(7)).Elif(w_stretch > 0,
                                     w_stretch.eq(w_stretch - 1)),
            reset_wdt_sys.eq(w_stretch != 0),
        ]
        self.submodules.reset_sync = BlindTransfer("sys", "wdt")
        self.comb += [
            self.reset_sync.i.eq(reset_wdt_sys),
            reset_wdt.eq(self.reset_sync.o),
        ]
        self.period = CSRStorage(
            32,
            fields=[
                CSRField(
                    "period",
                    size=32,
                    description=
                    "Number of 'approximately 65MHz' CFGMCLK cycles before each reset_code must be entered. Defaults to a range of {:0.2f}-{:0.2f} seconds"
                    .format((default_period * 10.256e-9) * 0.5,
                            (default_period * 10.256e-9) * 1.5),
                    reset=default_period)
            ])

        self.state = CSRStatus(
            4,
            fields=[
                CSRField("enabled", size=1,
                         description="WDT has been enabled"),
                CSRField("armed1",
                         size=1,
                         description="WDT in the armed1 state"),
                CSRField("armed2",
                         size=1,
                         description="WDT in the armed2 state"),
                CSRField("disarmed",
                         size=1,
                         description="WDT in the disarmed state"),
            ])
        armed1 = Signal()
        armed2 = Signal()
        disarmed = Signal()
        self.specials += MultiReg(armed1, self.state.fields.armed1)
        self.specials += MultiReg(armed2, self.state.fields.armed2)
        self.specials += MultiReg(disarmed, self.state.fields.disarmed)

        wdog_enable_wdt = Signal()
        self.specials += MultiReg(self.watchdog.fields.enable,
                                  wdog_enable_wdt,
                                  odomain="wdt")
        wdog_enabled = Signal(reset=0)
        wdog_enabled_r = Signal(reset=0)
        self.sync.wdt += [
            If(wdog_enable_wdt,
               wdog_enabled.eq(1)).Else(wdog_enabled.eq(wdog_enabled)),
            wdog_enabled_r.eq(wdog_enabled)
        ]
        self.specials += MultiReg(wdog_enabled, self.state.fields.enabled)

        self.submodules.period_sync = BusSynchronizer(32, "sys", "wdt")
        wdt_count = Signal(32)
        self.comb += [
            self.period_sync.i.eq(self.period.fields.period),
            wdt_count.eq(self.period_sync.o)
        ]
        wdt_count_lock = Signal(32)
        wdt_start = Signal()
        self.sync.wdt += [
            wdt_start.eq(~wdog_enabled_r & wdog_enabled),
            If(~wdog_enabled_r & wdog_enabled,
               wdt_count_lock.eq(wdt_count)).Else(
                   wdt_count_lock.eq(wdt_count_lock), )
        ]
        wdog_counter = Signal(32, reset=default_period)
        wdog_cycle = Signal()
        self.sync.wdt += [
            If(
                wdt_start,
                wdog_counter.eq(wdt_count_lock),
            ).Else(
                If(
                    wdog_enabled,
                    If(wdog_counter == 0, wdog_cycle.eq(1),
                       wdog_counter.eq(wdt_count_lock)).Else(
                           wdog_counter.eq(wdog_counter - 1),
                           wdog_cycle.eq(0),
                       )))
        ]
        do_reset = Signal()
        wdog = ClockDomainsRenamer("wdt")(FSM(reset_state="IDLE"))
        self.submodules += wdog
        wdog.act("IDLE", If(wdog_enabled, NextState("DISARMED")))
        wdog.act(
            "ARMED_HOT",
            armed2.eq(1),
            If(reset_wdt, NextState("DISARMED")).Elif(
                wdog_cycle,
                do_reset.eq(1),
            ),
        )
        # double-interlock: not having responded to the watchdog code immediately
        # is not cause for a reset: this could just be the wdog_cycle hitting at an
        # inopportune time relative to the watchdog reset routine.
        # instead, escalate to the ARMED_HOT state so that
        # the watchdog next period, if no action was taken, we do a reset
        wdog.act(
            "ARMED", armed1.eq(1),
            If(reset_wdt, NextState("DISARMED")).Elif(wdog_cycle,
                                                      NextState("ARMED_HOT")))
        wdog.act("DISARMED", disarmed.eq(1), If(wdog_cycle,
                                                NextState("ARMED")))
        do_reset_sys = Signal()
        reset_stretch = Signal(5, reset=0)
        self.submodules.do_res_sync = BlindTransfer("wdt", "sys")
        self.comb += [
            self.do_res_sync.i.eq(do_reset),
            do_reset_sys.eq(self.do_res_sync.o),
        ]
        self.sync += [
            If(
                do_reset_sys,
                reset_stretch.eq(31),
                self.gsr.eq(0),
            ).Elif(
                reset_stretch != 0,
                self.gsr.eq(1),
                reset_stretch.eq(reset_stretch - 1),
            ).Else(
                reset_stretch.eq(0),
                self.gsr.eq(0),
            )
        ]
コード例 #8
0
ファイル: jesd204_tools.py プロジェクト: spomjaksilp/artiq
    def __init__(self, input_pads, rtio_clk_freq=150e6):
        N = 64
        self.reset = CSRStorage(reset=1)
        self.locked = CSRStatus()
        self.dt = CSRStatus(N.bit_length())

        # # #

        self.clock_domains.cd_helper = ClockDomain(reset_less=True)
        helper_locked = Signal()
        helper_fb = Signal()
        helper_output = Signal()

        input_se = Signal()
        beat1 = Signal()
        beat2 = Signal()
        self.specials += [
            Instance("MMCME2_BASE",
                p_CLKIN1_PERIOD=1e9/rtio_clk_freq,
                i_CLKIN1=ClockSignal("rtio"),
                i_RST=self.reset.storage,
                o_LOCKED=helper_locked,

                # VCO at 1200MHz with 150MHz RTIO frequency
                p_CLKFBOUT_MULT_F=8.0,
                p_DIVCLK_DIVIDE=1,

                o_CLKFBOUT=helper_fb, i_CLKFBIN=helper_fb,

                # helper PLL ratio: 64/65 (N=64)
                p_CLKOUT0_DIVIDE_F=8.125,
                o_CLKOUT0=helper_output,
            ),
            MultiReg(helper_locked, self.locked.status),
            Instance("BUFG", i_I=helper_output, o_O=self.cd_helper.clk),
            Instance("IBUFDS", i_I=input_pads.p, i_IB=input_pads.n, o_O=input_se),
            Instance("FD", i_C=self.cd_helper.clk, i_D=input_se, o_Q=beat1, attr={("IOB", "TRUE")}),
            Instance("FD", i_C=self.cd_helper.clk, i_D=ClockSignal("rtio"), o_Q=beat2),
        ]

        ed1 = DDMTDEdgeDetector(beat1)
        ed2 = DDMTDEdgeDetector(beat2)
        self.submodules += ed1, ed2

        counting = Signal()
        counter = Signal(N.bit_length())
        result = Signal.like(counter)
        self.sync.helper += [
            If(counting,
                counter.eq(counter + 1)
            ).Else(
                result.eq(counter)
            ),

            If(ed1.rising, counting.eq(1), counter.eq(0)),
            If(ed2.rising, counting.eq(0))
        ]

        bsync = BusSynchronizer(len(result), "helper", "sys")
        self.submodules += bsync
        self.comb += [
            bsync.i.eq(result),
            self.dt.status.eq(bsync.o)
        ]
コード例 #9
0
    def __init__(self, clkspertick, clkfreq, bits=64):
        self.clkspertick = int(clkfreq / clkspertick)

        self.intro = ModuleDoc("""TickTimer: A practical systick timer.

        TIMER0 in the system gives a high-resolution, sysclk-speed timer which overflows
        very quickly and requires OS overhead to convert it into a practically usable time source
        which counts off in systicks, instead of sysclks.

        The hardware parameter to the block is the divisor of sysclk, and sysclk. So if
        the divisor is 1000, then the increment for a tick is 1ms. If the divisor is 2000,
        the increment for a tick is 0.5ms. 
        
        Note to self: substantial area savings could be hand by being smarter about the
        synchronization between the always-on and the TickTimer domains. Right now about 1.8%
        of the chip is eaten up by ~1100 synchronization registers to cross the 64-bit values
        between the clock domains. Since the values move rarely, a slightly smarter method
        would be to create a lock-out around a read pulse and then create some false_path
        rules around the datapaths to keep the place/route from getting distracted by the
        cross-domain clocks.
        """)

        resolution_in_ms = 1000 * (self.clkspertick / clkfreq)
        self.note = ModuleDoc(
            title="Configuration",
            body=
            "This timer was configured with {} bits, which rolls over in {:.2f} years, with each bit giving {}ms resolution"
            .format(bits, (2**bits / (60 * 60 * 24 * 365)) *
                    (self.clkspertick / clkfreq), resolution_in_ms))

        prescaler = Signal(max=self.clkspertick, reset=self.clkspertick)
        timer = Signal(bits)

        # cross-process domain signals. Broken out to a different CSR so it can be on a different virtual memory page.
        self.pause = Signal()
        pause = Signal()
        self.specials += MultiReg(self.pause, pause, "always_on")

        self.load = Signal()
        self.submodules.load_xfer = BlindTransfer("sys", "always_on")
        self.comb += self.load_xfer.i.eq(self.load)

        self.paused = Signal()
        paused = Signal()
        self.specials += MultiReg(paused, self.paused)

        self.timer = Signal(bits)
        self.submodules.timer_sync = BusSynchronizer(bits, "always_on", "sys")
        self.comb += [
            self.timer_sync.i.eq(timer),
            self.timer.eq(self.timer_sync.o)
        ]
        self.resume_time = Signal(bits)
        self.submodules.resume_sync = BusSynchronizer(bits, "sys", "always_on")
        self.comb += [self.resume_sync.i.eq(self.resume_time)]

        self.control = CSRStorage(fields=[
            CSRField(
                "reset",
                description=
                "Write a `1` to this bit to reset the count to 0. This bit has priority over all other requests.",
                pulse=True),
        ])
        self.time = CSRStatus(bits,
                              name="time",
                              description="""Elapsed time in systicks""")
        self.comb += self.time.status.eq(self.timer_sync.o)

        self.submodules.reset_xfer = BlindTransfer("sys", "always_on")
        self.comb += [
            self.reset_xfer.i.eq(self.control.fields.reset),
        ]

        self.sync.always_on += [
            If(
                self.reset_xfer.o,
                timer.eq(0),
                prescaler.eq(self.clkspertick),
            ).Elif(
                self.load_xfer.o,
                prescaler.eq(self.clkspertick),
                timer.eq(self.resume_sync.o),
            ).Else(
                If(
                    prescaler == 0, prescaler.eq(self.clkspertick),
                    If(pause == 0, timer.eq(timer + 1),
                       paused.eq(0)).Else(timer.eq(timer), paused.eq(1))).Else(
                           prescaler.eq(prescaler - 1), ))
        ]

        self.msleep = ModuleDoc("""msleep extension
        
        The msleep extension is a Xous-specific add-on to aid the implementation of the msleep server.
        
        msleep fires an interrupt when the requested time is less than or equal to the current elapsed time in
        systicks. The interrupt remains active until a new target is set, or masked. 
        
        There is a slight slip in time (~200ns) from when the msleep timer is set before it can take effect.
        This is because it takes many CPU clock cycles to transfer this data into the always-on clock
        domain, which runs at a much slower rate than the CPU clock.
        """)
        self.msleep_target = CSRStorage(
            size=bits,
            description="Target time in {}ms ticks".format(resolution_in_ms))
        self.submodules.ev = EventManager()
        self.ev.alarm = EventSourceLevel()
        # sys-domain alarm is computed using sys-domain time view, so that the trigger condition
        # corresponds tightly to the setting of the target time
        alarm_trigger = Signal()
        self.comb += self.ev.alarm.trigger.eq(alarm_trigger)

        # always_on domain gets a delayed copy of msleep_target
        # thus its output may not match that of the sys-domain alarm
        # in particular, it takes time for msleep_target update to propagate through
        # the bus synchronizers; however, the "trigger" enable for the system is handled
        # in the sys-domain, and can be set *before* the bus synchronizers have passed the
        # data through. This causes the alarm to glitch prematurely.

        # if we seem to be errantly aborting WFI's that are entered shortly after
        # setting an msleep target, this race condition is likely the culprit.

        # the circuit below locks out alarms for the duration of time that it takes for
        # msleep_target to propagate to its target, and back again
        self.submodules.ping = BlindTransfer("sys", "always_on")
        self.comb += self.ping.i.eq(self.msleep_target.re)
        self.submodules.pong = BlindTransfer("always_on", "sys")
        self.comb += self.pong.i.eq(self.ping.o)
        lockout_alarm = Signal()
        self.comb += [
            If(lockout_alarm, alarm_trigger.eq(0)).Else(
                alarm_trigger.eq(
                    self.msleep_target.storage <= self.timer_sync.o))
        ]
        self.sync += [
            If(self.msleep_target.re, lockout_alarm.eq(1)).Elif(
                self.pong.o,
                lockout_alarm.eq(0)).Else(lockout_alarm.eq(lockout_alarm))
        ]

        # re-compute the alarm signal in the "always on" domain -- so that this can trigger even when the CPU clock is stopped
        alarm = Signal()
        self.submodules.target_xfer = BusSynchronizer(bits, "sys", "always_on")
        self.comb += self.target_xfer.i.eq(self.msleep_target.storage)
        self.sync.always_on += alarm.eq(self.target_xfer.o <= timer)

        self.alarm_always_on = Signal()
        self.comb += self.alarm_always_on.eq(alarm)
コード例 #10
0
ファイル: bist.py プロジェクト: JohnSully/litedram
    def __init__(self, dram_port):
        ashift, awidth = get_ashift_awidth(dram_port)
        self.reset = CSR()
        self.start = CSR()
        self.done = CSRStatus()
        self.base = CSRStorage(awidth)
        self.length = CSRStorage(awidth)
        self.random = CSRStorage()
        self.ticks = CSRStatus(32)
        self.errors = CSRStatus(32)

        # # #

        clock_domain = dram_port.clock_domain

        core = _LiteDRAMBISTChecker(dram_port)
        core = ClockDomainsRenamer(clock_domain)(core)
        self.submodules += core

        if clock_domain != "sys":
            reset_sync = PulseSynchronizer("sys", clock_domain)
            start_sync = PulseSynchronizer("sys", clock_domain)
            self.submodules += reset_sync, start_sync
            self.comb += [
                reset_sync.i.eq(self.reset.re),
                core.reset.eq(reset_sync.o),
                start_sync.i.eq(self.start.re),
                core.start.eq(start_sync.o)
            ]

            done_sync = BusSynchronizer(1, clock_domain, "sys")
            self.submodules += done_sync
            self.comb += [
                done_sync.i.eq(core.done),
                self.done.status.eq(done_sync.o)
            ]

            base_sync = BusSynchronizer(awidth, "sys", clock_domain)
            length_sync = BusSynchronizer(awidth, "sys", clock_domain)
            self.submodules += base_sync, length_sync
            self.comb += [
                base_sync.i.eq(self.base.storage),
                core.base.eq(base_sync.o),
                length_sync.i.eq(self.length.storage),
                core.length.eq(length_sync.o)
            ]

            self.specials += MultiReg(self.random.storage, core.random,
                                      clock_domain)

            ticks_sync = BusSynchronizer(32, clock_domain, "sys")
            self.submodules += ticks_sync
            self.comb += [
                ticks_sync.i.eq(core.ticks),
                self.ticks.status.eq(ticks_sync.o)
            ]

            errors_sync = BusSynchronizer(32, clock_domain, "sys")
            self.submodules += errors_sync
            self.comb += [
                errors_sync.i.eq(core.errors),
                self.errors.status.eq(errors_sync.o)
            ]
        else:
            self.comb += [
                core.reset.eq(self.reset.re),
                core.start.eq(self.start.re),
                self.done.status.eq(core.done),
                core.base.eq(self.base.storage),
                core.length.eq(self.length.storage),
                core.random.eq(self.random.storage),
                self.ticks.status.eq(core.ticks),
                self.errors.status.eq(core.errors)
            ]