From 180026c72f0e1d3ef365b2214288d4a543a238dd Mon Sep 17 00:00:00 2001 From: Luke Kenneth Casson Leighton Date: Thu, 10 Mar 2022 12:33:15 +0000 Subject: [PATCH] tidyup on gramWishbone class, add comments --- gram/core/multiplexer.py | 4 +- gram/frontend/wishbone.py | 54 ++++++++++++++---------- gram/phy/ecp5ddrphy.py | 55 ++++++++++++++----------- gram/simulation/icarusecpix5platform.py | 2 +- gram/simulation/simsoctb.v | 6 ++- 5 files changed, 70 insertions(+), 51 deletions(-) diff --git a/gram/core/multiplexer.py b/gram/core/multiplexer.py index 69d9fb4..9e9b40d 100644 --- a/gram/core/multiplexer.py +++ b/gram/core/multiplexer.py @@ -173,9 +173,9 @@ class _Steerer(Elaboratable): with m.If(sel == STEER_REFRESH): m.d.sync += phase.cs_n.eq(0) with m.Else(): - m.d.sync += phase.cs_n.eq(rank_decoder.o) + m.d.sync += phase.cs_n.eq(~rank_decoder.o) else: - m.d.sync += phase.cs_n.eq(rank_decoder.o) + m.d.sync += phase.cs_n.eq(~rank_decoder.o) m.d.sync += phase.bank.eq(Array(cmd.ba[:-rankbits] for cmd in self.commands)[sel]) else: m.d.sync += [ diff --git a/gram/frontend/wishbone.py b/gram/frontend/wishbone.py index 0b04444..984eb71 100644 --- a/gram/frontend/wishbone.py +++ b/gram/frontend/wishbone.py @@ -48,61 +48,71 @@ class gramWishbone(Peripheral, Elaboratable): def elaborate(self, platform): m = Module() + comb = m.d.comb cmd = self.native_port.cmd wdata = self.native_port.wdata rdata = self.native_port.rdata + bus = self.bus # Write datapath - m.d.comb += wdata.valid.eq(self.bus.cyc & self.bus.stb & self.bus.we) + comb += wdata.valid.eq(bus.cyc & bus.stb & bus.we) ratio_bitmask = Repl(1, log2_int(self.ratio)) - sel = Signal.like(self.bus.sel) - with m.If(self.bus.sel == 0): - m.d.comb += sel.eq(Repl(1, sel.width)) + # XXX? sel is zero being compensated-for as all 1s does not seem right + sel = Signal.like(bus.sel) + with m.If(bus.sel == 0): + comb += sel.eq(-1) # all 1s with m.Else(): - m.d.comb += sel.eq(self.bus.sel) + comb += sel.eq(bus.sel) - with m.Switch(self.bus.adr & ratio_bitmask): + with m.Switch(bus.adr & ratio_bitmask): # XXX adr changes (WB4-pipe) for i in range(self.ratio): with m.Case(i): - m.d.comb += wdata.we.eq(Repl(sel, self.bus.granularity//8) << (self.ratio*i)) - - with m.Switch(self.bus.adr & ratio_bitmask): - for i in range(self.ratio): - with m.Case(i): - m.d.comb += wdata.data.eq(self.bus.dat_w << (self.bus.data_width*i)) + # write-enable + we = Repl(sel, bus.granularity//8) << (self.ratio*i) + comb += wdata.we.eq(we) + # write-data + data = bus.dat_w << (bus.data_width*i) + comb += wdata.data.eq(data) # Read datapath - m.d.comb += rdata.ready.eq(1) + comb += rdata.ready.eq(1) - with m.Switch(self.bus.adr & ratio_bitmask): + with m.Switch(bus.adr & ratio_bitmask): # XXX adr changes (WB4-pipe) for i in range(self.ratio): with m.Case(i): - m.d.comb += self.bus.dat_r.eq(rdata.data >> (self.bus.data_width*i)) + data = rdata.data >> (bus.data_width*i) + comb += bus.dat_r.eq(data) + # Command FSM with m.FSM(): + # raise a command when WB has a request with m.State("Send-Cmd"): - m.d.comb += [ - cmd.valid.eq(self.bus.cyc & self.bus.stb), - cmd.we.eq(self.bus.we), - cmd.addr.eq(self.bus.adr >> log2_int(self.bus.data_width//self.bus.granularity)), + # XXX this logic is only WB 3.0 classic compatible! + comb += [ + cmd.valid.eq(bus.cyc & bus.stb), + cmd.we.eq(bus.we), + cmd.addr.eq(bus.adr >> self.dsize), ] + # when cmd is accepted, move to either read or write FSM with m.If(cmd.valid & cmd.ready): - with m.If(self.bus.we): + with m.If(bus.we): m.next = "Wait-Write" with m.Else(): m.next = "Wait-Read" + # read-wait: when read valid, ack the WB bus, return idle with m.State("Wait-Read"): with m.If(rdata.valid): - m.d.comb += self.bus.ack.eq(1) + comb += bus.ack.eq(1) m.next = "Send-Cmd" + # write-wait: when write valid, ack the WB bus, return idle with m.State("Wait-Write"): with m.If(wdata.ready): - m.d.comb += self.bus.ack.eq(1) + comb += bus.ack.eq(1) m.next = "Send-Cmd" return m diff --git a/gram/phy/ecp5ddrphy.py b/gram/phy/ecp5ddrphy.py index ce13c99..a31dfb3 100644 --- a/gram/phy/ecp5ddrphy.py +++ b/gram/phy/ecp5ddrphy.py @@ -174,6 +174,7 @@ class ECP5DDRPHY(Peripheral, Elaboratable): def elaborate(self, platform): m = Module() + comb, sync = m.d.comb, m.d.sync m.submodules.bridge = self._bridge @@ -405,12 +406,12 @@ class ECP5DDRPHY(Peripheral, Elaboratable): ] for j in range(8*i, 8*(i+1)): - dq_o = Signal() - dq_i = Signal() - dq_oe_n = Signal() - dq_i_delayed = Signal() - dq_i_data = Signal(4) - dq_o_data = Signal(8) + dq_o = Signal(name="dq_o_%d" % j) + dq_i = Signal(name="dq_i_%d" % j) + dq_oe_n = Signal(name="dq_oe_n_%d" % j) + dq_i_delayed = Signal(name="dq_i_delayed_%d" % j) + dq_i_data = Signal(4, name="dq_i_data_%d" % j) + dq_o_data = Signal(8, name="dq_o_data_%d" % j) dq_o_data_d = Signal(8, reset_less=True) dq_o_data_muxed = Signal(4, reset_less=True) m.d.comb += dq_o_data.eq(Cat( @@ -478,20 +479,28 @@ class ECP5DDRPHY(Peripheral, Elaboratable): o_O=dq_i, io_B=self.pads.dq.io[j]) ] - with m.If(~datavalid_prev & datavalid): - m.d.sync += [ - dfi.phases[0].rddata[0*databits+j].eq(dq_i_data[0]), - dfi.phases[0].rddata[1*databits+j].eq(dq_i_data[1]), - dfi.phases[0].rddata[2*databits+j].eq(dq_i_data[2]), - dfi.phases[0].rddata[3*databits+j].eq(dq_i_data[3]), - ] - with m.Elif(datavalid): - m.d.sync += [ - dfi.phases[1].rddata[0*databits+j].eq(dq_i_data[0]), - dfi.phases[1].rddata[1*databits+j].eq(dq_i_data[1]), - dfi.phases[1].rddata[2*databits+j].eq(dq_i_data[2]), - dfi.phases[1].rddata[3*databits+j].eq(dq_i_data[3]), - ] + # shift-register delay on the incoming read data + dq_i_bs = BitSlip(4, Const(0), Const(0), cycles=1) + m.submodules['dq_i_bitslip_%d' % j] = dq_i_bs + dq_i_bs_o = Signal(4, name="dq_i_bs_o_%d" % j) + dq_i_bs_o_d = Signal(4, name="dq_i_bs_o_d_%d" % j) + comb += dq_i_bs.i.eq(dq_i_data) + comb += dq_i_bs_o.eq(dq_i_bs.o) + sync += dq_i_bs_o_d.eq(dq_i_bs_o) # delay by 1 clock + #with m.If(~datavalid_prev & datavalid): + comb += [ + dfi.phases[0].rddata[0*databits+j].eq(dq_i_bs_o_d[0]), + dfi.phases[0].rddata[1*databits+j].eq(dq_i_bs_o_d[1]), + dfi.phases[0].rddata[2*databits+j].eq(dq_i_bs_o_d[2]), + dfi.phases[0].rddata[3*databits+j].eq(dq_i_bs_o_d[3]), + ] + #with m.Elif(datavalid): + comb += [ + dfi.phases[1].rddata[0*databits+j].eq(dq_i_bs_o[0]), + dfi.phases[1].rddata[1*databits+j].eq(dq_i_bs_o[1]), + dfi.phases[1].rddata[2*databits+j].eq(dq_i_bs_o[2]), + dfi.phases[1].rddata[3*databits+j].eq(dq_i_bs_o[3]), + ] # Read Control Path ------------------------------------------------------------------------ # Creates a shift register of read commands coming from the DFI interface. This shift register @@ -507,12 +516,10 @@ class ECP5DDRPHY(Peripheral, Elaboratable): rddata_en_last = Signal.like(rddata_en) m.d.comb += rddata_en.eq(Cat(dfi.phases[self.settings.rdphase].rddata_en, rddata_en_last)) m.d.sync += rddata_en_last.eq(rddata_en) + for phase in dfi.phases: + m.d.sync += phase.rddata_valid.eq(rddata_en[-1]) m.d.comb += dqs_re.eq(rddata_en[cl_sys_latency + 1] | rddata_en[cl_sys_latency + 2]) - rddata_valid = Signal() - m.d.sync += rddata_valid.eq(datavalid_prev & ~datavalid) - for phase in dfi.phases: - m.d.comb += phase.rddata_valid.eq(rddata_valid) # Write Control Path ----------------------------------------------------------------------- # Creates a shift register of write commands coming from the DFI interface. This shift register diff --git a/gram/simulation/icarusecpix5platform.py b/gram/simulation/icarusecpix5platform.py index b3b5a1b..7b4b601 100644 --- a/gram/simulation/icarusecpix5platform.py +++ b/gram/simulation/icarusecpix5platform.py @@ -27,7 +27,7 @@ class IcarusECPIX5Platform(LatticeECP5Platform): ), Resource("ddr3", 0, - Subsignal("rst", Pins("fake", dir="o")), # for sim + Subsignal("rst", PinsN("fake", dir="o")), # for sim #Subsignal("clk", Pins("H3", dir="o")), Subsignal("clk", DiffPairs("H3", "J3", dir="o"), Attrs(IO_TYPE="SSTL135D_I")), Subsignal("clk_en", Pins("P1", dir="o")), diff --git a/gram/simulation/simsoctb.v b/gram/simulation/simsoctb.v index 54c76e4..5afa17f 100644 --- a/gram/simulation/simsoctb.v +++ b/gram/simulation/simsoctb.v @@ -43,10 +43,12 @@ module simsoctb; wire [1:0] dram_tdqs_n; wire dram_rst; + // anything here with "_n" has to be inverted. nmigen platforms + // sort that out by inverting (with PinsN) ddr3 #( .check_strict_timing(0) ) ram_chip ( - .rst_n(dram_rst), + .rst_n(~dram_rst), .ck(dram_ck), .ck_n(~dram_ck), .cke(dram_cke), @@ -82,7 +84,7 @@ module simsoctb; .ddr3_0__rst__io(dram_rst), .ddr3_0__dq__io(dram_dq), .ddr3_0__dqs__p(dram_dqs), - .ddr3_0__clk__io(dram_ck), + .ddr3_0__clk__p(dram_ck), .ddr3_0__clk_en__io(dram_cke), .ddr3_0__we__io(dram_we_n), .ddr3_0__cs__io(dram_cs_n), -- 2.30.2