1
0

util: Do BlackBox Async Set/Reset Registers more properly (#305)

* util: Do Set/Reset Async Registers more properly

The way BlackBox "init" registers were coded before was
not really kosher verilog for most synthesis tools.
Also, the enable logic wasn't really pushed down into the flop.

This change is more explicit about set/reset flops,
again this is only a 'temporary' problem that would go away
with parameterizable blackboxes (or general async reset support).

* Tabs, not spaces, in Makefiles

* util: Fix typos in Async BB Reg Comments
This commit is contained in:
mwachs5 2016-09-16 13:50:09 -07:00 committed by Yunsup Lee
parent a94b4af92d
commit a031686763
4 changed files with 88 additions and 36 deletions

View File

@ -5,13 +5,17 @@ import Chisel._
import cde.{Parameters} import cde.{Parameters}
/** This black-boxes an Async Reset /** This black-boxes an Async Reset
* Reg. * (or Set)
* Register.
* *
* Because Chisel doesn't support * Because Chisel doesn't support
* parameterized black boxes, * parameterized black boxes,
* we unfortunately have to * we unfortunately have to
* instantiate a number of these. * instantiate a number of these.
* *
* We also have to hard-code the set/
* reset behavior.
*
* Do not confuse an asynchronous * Do not confuse an asynchronous
* reset signal with an asynchronously * reset signal with an asynchronously
* reset reg. You should still * reset reg. You should still
@ -22,29 +26,26 @@ import cde.{Parameters}
* @param q Data Output * @param q Data Output
* @param clk Clock Input * @param clk Clock Input
* @param rst Reset Input * @param rst Reset Input
* @param en Write Enable Input
* *
* @param init Value to write at Reset.
* This is a constant,
* but this construction
* will likely make backend flows
* and lint tools unhappy.
*
*/ */
class AsyncResetReg extends BlackBox { abstract class AbstractBBReg extends BlackBox {
val io = new Bundle { val io = new Bundle {
val d = Bool(INPUT) val d = Bool(INPUT)
val q = Bool(OUTPUT) val q = Bool(OUTPUT)
val en = Bool(INPUT)
val clk = Clock(INPUT) val clk = Clock(INPUT)
val rst = Bool(INPUT) val rst = Bool(INPUT)
val init = Bool(INPUT)
} }
} }
class AsyncResetReg extends AbstractBBReg
class AsyncSetReg extends AbstractBBReg
class SimpleRegIO(val w: Int) extends Bundle{ class SimpleRegIO(val w: Int) extends Bundle{
val d = UInt(INPUT, width = w) val d = UInt(INPUT, width = w)
@ -60,30 +61,38 @@ class AsyncResetRegVec(val w: Int, val init: BigInt) extends Module {
val bb_d = Mux(io.en, io.d, io.q) val bb_d = Mux(io.en, io.d, io.q)
val async_regs = List.fill(w)(Module (new AsyncResetReg)) val async_regs: List[AbstractBBReg] = List.tabulate(w)(
i => Module (
if (((init >> i) % 2) > 0)
new AsyncSetReg
else
new AsyncResetReg)
)
io.q := async_regs.map(_.io.q).asUInt io.q := async_regs.map(_.io.q).asUInt
for ((reg, idx) <- async_regs.zipWithIndex) { for ((reg, idx) <- async_regs.zipWithIndex) {
reg.io.clk := clock reg.io.clk := clock
reg.io.rst := reset reg.io.rst := reset
reg.io.init := Bool(((init >> idx) & 1) == 1) reg.io.d := bb_d(idx)
reg.io.d := bb_d(idx) reg.io.en := io.en
} }
} }
object AsyncResetReg { object AsyncResetReg {
def apply(d: Bool, clk: Clock, rst: Bool, init: Bool): Bool = { def apply(d: Bool, clk: Clock, rst: Bool, init: Boolean): Bool = {
val reg = Module(new AsyncResetReg) val reg: AbstractBBReg =
if (init) Module (new AsyncSetReg)
else Module(new AsyncResetReg)
reg.io.d := d reg.io.d := d
reg.io.clk := clk reg.io.clk := clk
reg.io.rst := rst reg.io.rst := rst
reg.io.init := init reg.io.en := Bool(true)
reg.io.q reg.io.q
} }
def apply(d: Bool, clk: Clock, rst: Bool): Bool = apply(d, clk, rst, Bool(false)) def apply(d: Bool, clk: Clock, rst: Bool): Bool = apply(d, clk, rst, false)
def apply(updateData: UInt, resetData: BigInt, enable: Bool): UInt = { def apply(updateData: UInt, resetData: BigInt, enable: Bool): UInt = {
val w = updateData.getWidth max resetData.bitLength val w = updateData.getWidth max resetData.bitLength
@ -93,9 +102,9 @@ object AsyncResetReg {
reg.io.q reg.io.q
} }
def apply(updateData: UInt, resetData: BigInt): UInt = apply(updateData, resetData, Bool(true)) def apply(updateData: UInt, resetData: BigInt): UInt = apply(updateData, resetData, enable=Bool(true))
def apply(updateData: UInt, enable: Bool): UInt = apply(updateData, BigInt(0), enable) def apply(updateData: UInt, enable: Bool): UInt = apply(updateData, resetData=BigInt(0), enable)
def apply(updateData: UInt): UInt = apply(updateData, BigInt(0), Bool(true)) def apply(updateData: UInt): UInt = apply(updateData, resetData=BigInt(0), enable=Bool(true))
} }

View File

@ -8,10 +8,11 @@ bb_vsrcs = $(base_dir)/vsrc/DebugTransportModuleJtag.v \
$(base_dir)/vsrc/jtag_vpi.v \ $(base_dir)/vsrc/jtag_vpi.v \
$(base_dir)/vsrc/AsyncMailbox.v \ $(base_dir)/vsrc/AsyncMailbox.v \
$(base_dir)/vsrc/AsyncResetReg.v \ $(base_dir)/vsrc/AsyncResetReg.v \
$(base_dir)/vsrc/AsyncSetReg.v \
$(base_dir)/vsrc/ClockDivider.v \ $(base_dir)/vsrc/ClockDivider.v \
$(base_dir)/vsrc/ClockToSignal.v \ $(base_dir)/vsrc/ClockToSignal.v \
$(base_dir)/vsrc/SignalToClock.v \ $(base_dir)/vsrc/SignalToClock.v \
sim_vsrcs = \ sim_vsrcs = \
$(generated_dir)/$(MODEL).$(CONFIG).v \ $(generated_dir)/$(MODEL).$(CONFIG).v \

View File

@ -8,6 +8,8 @@
* we unfortunately have to * we unfortunately have to
* instantiate a number of these. * instantiate a number of these.
* *
* We also have to hard-code the set/reset.
*
* Do not confuse an asynchronous * Do not confuse an asynchronous
* reset signal with an asynchronously * reset signal with an asynchronously
* reset reg. You should still * reset reg. You should still
@ -18,32 +20,25 @@
* @param q Data Output * @param q Data Output
* @param clk Clock Input * @param clk Clock Input
* @param rst Reset Input * @param rst Reset Input
* @param en Write Enable Input
* *
* @param init Value to write at Reset.
* This is a constant,
* but this construction
* will likely make backend flows
* and lint tools unhappy.
*
*/ */
module AsyncResetReg ( module AsyncResetReg (
input d, input d,
output reg q, output reg q,
input en,
input clk, input clk,
input rst, input rst);
input init);
always @(posedge clk or posedge rst) begin always @(posedge clk or posedge rst) begin
if (rst) begin if (rst) begin
q <= init; q <= 1'b0;
end else begin end else if (en) begin
q <= d; q <= d;
end end
end end

47
vsrc/AsyncSetReg.v Normal file
View File

@ -0,0 +1,47 @@
/** This black-boxes an Async Set
* Reg.
*
* Because Chisel doesn't support
* parameterized black boxes,
* we unfortunately have to
* instantiate a number of these.
*
* We also have to hard-code the set/reset.
*
* Do not confuse an asynchronous
* reset signal with an asynchronously
* reset reg. You should still
* properly synchronize your reset
* deassertion.
*
* @param d Data input
* @param q Data Output
* @param clk Clock Input
* @param rst Reset Input
* @param en Write Enable Input
*
*/
module AsyncSetReg (
input d,
output reg q,
input en,
input clk,
input rst);
always @(posedge clk or posedge rst) begin
if (rst) begin
q <= 1'b1;
end else if (en) begin
q <= d;
end
end
endmodule // AsyncSetReg