only use positive logic in the controller(cas/ras/we) and use Record/stream.Endpoint for command requests

This commit is contained in:
Florent Kermarrec 2016-05-02 12:18:56 +02:00
parent cbe9748fa1
commit fb98d12241
8 changed files with 69 additions and 68 deletions

View File

@ -84,20 +84,18 @@ class UserInterface(Record):
Record.__init__(self, layout)
class CommandRequest:
def __init__(self, a, ba):
self.a = Signal(a)
self.ba = Signal(ba)
self.cas_n = Signal(reset=1)
self.ras_n = Signal(reset=1)
self.we_n = Signal(reset=1)
def cmd_request_layout(a, ba):
return [
("a", a),
("ba", ba),
("cas", 1),
("ras", 1),
("we", 1)
]
class CommandRequestRW(CommandRequest):
def __init__(self, a, ba):
CommandRequest.__init__(self, a, ba)
self.valid = Signal()
self.ready = Signal()
self.is_cmd = Signal()
self.is_read = Signal()
self.is_write = Signal()
def cmd_request_rw_layout(a, ba):
return cmd_request_layout(a, ba) + [
("is_cmd", 1),
("is_read", 1),
("is_write", 1)
]

View File

@ -32,7 +32,8 @@ class BankMachine(Module):
self.req = req = Record(cmd_layout(aw))
self.refresh_req = Signal()
self.refresh_gnt = Signal()
self.cmd = CommandRequestRW(geom_settings.addressbits, geom_settings.bankbits)
self.cmd = cmd = stream.Endpoint(cmd_request_rw_layout(geom_settings.addressbits,
geom_settings.bankbits))
# # #
@ -68,19 +69,19 @@ class BankMachine(Module):
# Address generation
s_row_adr = Signal()
self.comb += [
self.cmd.ba.eq(n),
cmd.ba.eq(n),
If(s_row_adr,
self.cmd.a.eq(slicer.row(fifo.source.adr))
cmd.a.eq(slicer.row(fifo.source.adr))
).Else(
self.cmd.a.eq(slicer.col(fifo.source.adr))
cmd.a.eq(slicer.col(fifo.source.adr))
)
]
# Respect write-to-precharge specification
self.submodules.precharge_timer = WaitTimer(2 + timing_settings.tWR - 1 + 1)
self.comb += self.precharge_timer.wait.eq(~(self.cmd.valid &
self.cmd.ready &
self.cmd.is_write))
self.comb += self.precharge_timer.wait.eq(~(cmd.valid &
cmd.ready &
cmd.is_write))
# Control and command generation FSM
self.submodules.fsm = fsm = FSM()
@ -91,16 +92,16 @@ class BankMachine(Module):
If(has_openrow,
If(hit,
# NB: write-to-read specification is enforced by multiplexer
self.cmd.valid.eq(1),
cmd.valid.eq(1),
If(fifo.source.we,
req.dat_w_ack.eq(self.cmd.ready),
self.cmd.is_write.eq(1)
req.dat_w_ack.eq(cmd.ready),
cmd.is_write.eq(1),
cmd.we.eq(1),
).Else(
req.dat_r_ack.eq(self.cmd.ready),
self.cmd.is_read.eq(1)
req.dat_r_ack.eq(cmd.ready),
cmd.is_read.eq(1)
),
self.cmd.cas_n.eq(0),
self.cmd.we_n.eq(~fifo.source.we)
cmd.cas.eq(1)
).Else(
NextState("PRECHARGE")
)
@ -115,31 +116,31 @@ class BankMachine(Module):
# 2. since we always go to the ACTIVATE state, we do not need
# to assert track_close.
If(self.precharge_timer.done,
self.cmd.valid.eq(1),
If(self.cmd.ready,
cmd.valid.eq(1),
If(cmd.ready,
NextState("TRP")
),
self.cmd.ras_n.eq(0),
self.cmd.we_n.eq(0),
self.cmd.is_cmd.eq(1)
cmd.ras.eq(1),
cmd.we.eq(1),
cmd.is_cmd.eq(1)
)
)
fsm.act("ACTIVATE",
s_row_adr.eq(1),
track_open.eq(1),
self.cmd.valid.eq(1),
self.cmd.is_cmd.eq(1),
If(self.cmd.ready,
cmd.valid.eq(1),
cmd.is_cmd.eq(1),
If(cmd.ready,
NextState("TRCD")
),
self.cmd.ras_n.eq(0)
cmd.ras.eq(1)
)
fsm.act("REFRESH",
If(self.precharge_timer.done,
self.refresh_gnt.eq(1),
),
track_close.eq(1),
self.cmd.is_cmd.eq(1),
cmd.is_cmd.eq(1),
If(~self.refresh_req,
NextState("REGULAR")
)

View File

@ -4,6 +4,7 @@ from operator import or_, and_
from litex.gen import *
from litex.gen.genlib.roundrobin import *
from litex.soc.interconnect import stream
from litex.soc.interconnect.csr import AutoCSR
from litedram.common import *
@ -15,8 +16,9 @@ class _CommandChooser(Module):
self.want_reads = Signal()
self.want_writes = Signal()
self.want_cmds = Signal()
# NB: cas_n/ras_n/we_n are 1 when valid is inactive
self.cmd = CommandRequestRW(len(requests[0].a), len(requests[0].ba))
# NB: cas/ras/we are 0 when valid is inactive
self.cmd = cmd = stream.Endpoint(cmd_request_rw_layout(len(requests[0].a),
len(requests[0].ba)))
# # #
@ -32,18 +34,18 @@ class _CommandChooser(Module):
self.comb += valid.eq(Array(req.valid for req in requests)[rr.grant])
for name in ["a", "ba", "is_read", "is_write", "is_cmd"]:
choices = Array(getattr(req, name) for req in requests)
self.comb += getattr(self.cmd, name).eq(choices[rr.grant])
for name in ["cas_n", "ras_n", "we_n"]:
self.comb += getattr(cmd, name).eq(choices[rr.grant])
for name in ["cas", "ras", "we"]:
# we should only assert those signals when valid is 1
choices = Array(getattr(req, name) for req in requests)
self.comb += If(self.cmd.valid, getattr(self.cmd, name).eq(choices[rr.grant]))
self.comb += self.cmd.valid.eq(valid \
& ((self.cmd.is_cmd & self.want_cmds) | ((self.cmd.is_read == self.want_reads) \
& (self.cmd.is_write == self.want_writes))))
self.comb += If(cmd.valid, getattr(cmd, name).eq(choices[rr.grant]))
self.comb += cmd.valid.eq(valid \
& ((cmd.is_cmd & self.want_cmds) | ((cmd.is_read == self.want_reads) \
& (cmd.is_write == self.want_writes))))
self.comb += [If(self.cmd.valid & self.cmd.ready & (rr.grant == i), req.ready.eq(1))
self.comb += [If(cmd.valid & cmd.ready & (rr.grant == i), req.ready.eq(1))
for i, req in enumerate(requests)]
self.comb += rr.ce.eq(self.cmd.ready)
self.comb += rr.ce.eq(cmd.ready)
class _Steerer(Module):
@ -52,7 +54,7 @@ class _Steerer(Module):
nph = len(dfi.phases)
self.sel = [Signal(max=ncmd) for i in range(nph)]
###
# # #
def valid_and(cmd, attr):
if not hasattr(cmd, "valid"):
@ -71,9 +73,9 @@ class _Steerer(Module):
self.sync += [
phase.address.eq(Array(cmd.a for cmd in commands)[sel]),
phase.bank.eq(Array(cmd.ba for cmd in commands)[sel]),
phase.cas_n.eq(Array(cmd.cas_n for cmd in commands)[sel]),
phase.ras_n.eq(Array(cmd.ras_n for cmd in commands)[sel]),
phase.we_n.eq(Array(cmd.we_n for cmd in commands)[sel]),
phase.cas_n.eq(~Array(cmd.cas for cmd in commands)[sel]),
phase.ras_n.eq(~Array(cmd.ras for cmd in commands)[sel]),
phase.we_n.eq(~Array(cmd.we for cmd in commands)[sel]),
phase.rddata_en.eq(Array(valid_and(cmd, "is_read") for cmd in commands)[sel]),
phase.wrdata_en.eq(Array(valid_and(cmd, "is_write") for cmd in commands)[sel])
]
@ -100,7 +102,7 @@ class Multiplexer(Module, AutoCSR):
]
# Command steering
nop = CommandRequest(geom_settings.addressbits, geom_settings.bankbits)
nop = Record(cmd_request_layout(geom_settings.addressbits, geom_settings.bankbits))
commands = [nop, choose_cmd.cmd, choose_req.cmd, refresher.cmd] # nop must be 1st
(STEER_NOP, STEER_CMD, STEER_REQ, STEER_REFRESH) = range(4)
steerer = _Steerer(commands, dfi)

View File

@ -8,7 +8,7 @@ class Refresher(Module):
def __init__(self, a, ba, tRP, tREFI, tRFC, enable):
self.req = Signal()
self.ack = Signal() # 1st command 1 cycle after assertion of ack
self.cmd = cmd = CommandRequest(a, ba)
self.cmd = cmd = Record(cmd_request_layout(a, ba))
# # #
@ -19,19 +19,19 @@ class Refresher(Module):
self.sync += [
cmd.a.eq(2**10),
cmd.ba.eq(0),
cmd.cas_n.eq(1),
cmd.ras_n.eq(1),
cmd.we_n.eq(1),
cmd.cas.eq(0),
cmd.ras.eq(0),
cmd.we.eq(0),
seq_done.eq(0)
]
self.sync += timeline(seq_start, [
(1, [
cmd.ras_n.eq(0),
cmd.we_n.eq(0)
cmd.ras.eq(1),
cmd.we.eq(1)
]),
(1+tRP, [
cmd.cas_n.eq(0),
cmd.ras_n.eq(0)
cmd.cas.eq(1),
cmd.ras.eq(1)
]),
(1+tRP+tRFC, [
seq_done.eq(1)

View File

@ -13,7 +13,7 @@ class PhaseInjector(Module, AutoCSR):
self._wrdata = CSRStorage(len(phase.wrdata))
self._rddata = CSRStatus(len(phase.rddata))
###
# # #
self.comb += [
If(self._command_issue.re,
@ -48,7 +48,7 @@ class DFIInjector(Module, AutoCSR):
for n, phase in enumerate(inti.phases):
setattr(self.submodules, "pi" + str(n), PhaseInjector(phase))
###
# # #
self.comb += If(self._control.storage[0],
self.slave.connect(self.master)

View File

@ -50,7 +50,7 @@ class GENSDRPHY(Module):
self.dfi = Interface(addressbits, bankbits, databits)
###
# # #
#
# Command/address

View File

@ -43,7 +43,7 @@ class K7DDRPHY(Module, AutoCSR):
self.dfi = Interface(addressbits, bankbits, 2*databits, nphases)
###
# # #
# Clock
sd_clk_se = Signal()

View File

@ -68,7 +68,7 @@ class S6HalfRateDDRPHY(Module):
self.clk4x_wr_strb = Signal()
self.clk4x_rd_strb = Signal()
###
# # #
# sys_clk : system clk, used for dfi interface
# sdram_half_clk : half rate sdram clk