aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorDonggyu2016-08-18 18:03:18 -0700
committerAdam Izraelevitz2016-08-18 18:03:18 -0700
commitebd6f893428b16629be8d4d703d553d0fe8cf37c (patch)
tree79d4c8454312d815a79f5189bff45514848ceb63 /src
parentf8fab5bee8f0484a788769d2d4e87c08ccd884e4 (diff)
emit correct enable signals for memories (#242)
Diffstat (limited to 'src')
-rw-r--r--src/main/scala/firrtl/Emitter.scala55
1 files changed, 36 insertions, 19 deletions
diff --git a/src/main/scala/firrtl/Emitter.scala b/src/main/scala/firrtl/Emitter.scala
index 3a6af54e..316a7044 100644
--- a/src/main/scala/firrtl/Emitter.scala
+++ b/src/main/scala/firrtl/Emitter.scala
@@ -437,16 +437,14 @@ class VerilogEmitter extends Emitter {
Seq("$fwrite(32'h80000002,",strx,");")
}
def delay (e:Expression, n:Int, clk:Expression) : Expression = {
- var ex = e
- for (i <- 0 until n) {
+ ((0 until n) foldLeft e){(ex, i) =>
val name = namespace.newTemp
declare("reg",name,tpe(e))
val exx = WRef(name,tpe(e),ExpKind(),UNKNOWNGENDER)
initialize(exx)
update(exx,ex,clk,one)
- ex = exx
+ exx
}
- ex
}
def build_ports () = {
(m.ports,0 until m.ports.size).zipped.foreach{(p,i) => {
@@ -513,12 +511,20 @@ class VerilogEmitter extends Emitter {
declare("wire",LowerTypes.loweredName(data),tpe(data))
declare("wire",LowerTypes.loweredName(addr),tpe(addr))
declare("wire",LowerTypes.loweredName(en),tpe(en))
-
+
//; Read port
assign(addr,netlist(addr)) //;Connects value to m.r.addr
assign(en,netlist(en)) //;Connects value to m.r.en
- val addrx = delay(addr,s.readLatency,clk)
- val enx = delay(en,s.readLatency,clk)
+ val addr_pipe = delay(addr,s.readLatency-1,clk)
+ val en_pipe = if (weq(en,one)) one else delay(en,s.readLatency-1,clk)
+ val addrx = if (s.readLatency > 0) {
+ val name = namespace.newTemp
+ val ref = WRef(name,tpe(addr),ExpKind(),UNKNOWNGENDER)
+ declare("reg",name,tpe(addr))
+ initialize(ref)
+ update(ref,addr_pipe,clk,en_pipe)
+ ref
+ } else addr
val mem_port = WSubAccess(mem,addrx,s.dataType,UNKNOWNGENDER)
val depthValue = UIntLiteral(s.depth, IntWidth(BigInt(s.depth).bitLength))
val garbageGuard = DoPrim(Geq, Seq(addrx, depthValue), Seq(), UnknownType)
@@ -582,25 +588,36 @@ class VerilogEmitter extends Emitter {
assign(wmode,netlist(wmode))
//; Delay new signals by latency
- val raddrx = delay(addr,s.readLatency,clk)
+ val raddrx = if (s.readLatency > 0) delay(addr,s.readLatency - 1,clk) else addr
val waddrx = delay(addr,s.writeLatency - 1,clk)
val enx = delay(en,s.writeLatency - 1,clk)
- val rmodx = delay(wmode,s.writeLatency - 1,clk)
+ val wmodex = delay(wmode,s.writeLatency - 1,clk)
val wdatax = delay(wdata,s.writeLatency - 1,clk)
val wmaskx = delay(wmask,s.writeLatency - 1,clk)
-
- //; Write
-
- val rmem_port = WSubAccess(mem,raddrx,s.dataType,UNKNOWNGENDER)
+
+ val raddrxx = if (s.readLatency > 0) {
+ val name = namespace.newTemp
+ val ref = WRef(name,tpe(raddrx),ExpKind(),UNKNOWNGENDER)
+ declare("reg",name,tpe(raddrx))
+ initialize(ref)
+ ref
+ } else addr
+ val rmem_port = WSubAccess(mem,raddrxx,s.dataType,UNKNOWNGENDER)
assign(rdata,rmem_port)
val wmem_port = WSubAccess(mem,waddrx,s.dataType,UNKNOWNGENDER)
- val tempName = namespace.newTemp
- val tempExp = AND(enx,wmaskx)
- declare("wire", tempName, tpe(tempExp))
- val tempWRef = wref(tempName, tpe(tempExp))
- assign(tempWRef, tempExp)
- update(wmem_port,wdatax,clk,AND(tempWRef,wmode))
+ def declare_and_assign(exp: Expression) = {
+ val name = namespace.newTemp
+ val ref = wref(name, tpe(exp))
+ declare("wire", name, tpe(exp))
+ assign(ref, exp)
+ ref
+ }
+ val ren = declare_and_assign(NOT(wmodex))
+ val wen = declare_and_assign(AND(wmodex, wmaskx))
+ if (s.readLatency > 0)
+ update(raddrxx,raddrx,clk,AND(enx,ren))
+ update(wmem_port,wdatax,clk,AND(enx,wen))
}
}
case (s:Block) => s map (build_streams)