ucb-bar / chisel2-deprecated

chisel.eecs.berkeley.edu
388 stars 90 forks source link

Clock dividers / multiclock support #667

Open shunshou opened 8 years ago

shunshou commented 8 years ago

So... as far as I understand it, not many people have actually played around with multiple clock domains and it only works when clocks are integer multiples of each other... (?)

Is there any plan to support generating clock dividers directly in Chisel? Currently, my "solution" to having 1 fast clock and 1 derived slow clock is to use register enables when I expect the rising edge of the slow clock to occur... But this doesn't really help with relaxing timing constraints for the data path using the slow clock...

I can generate my own effective divided down clock with counters, but there's no way to specify that this divided down clock (= Bool) is actually a clock, rather than just some data, so I wouldn't even be able to use it as the clock pin to registers.

Is there some way to do a type conversion from Bool to Clock?

I really feel like something like this should be baked into Chisel rather than hacked together externally to interface with Chisel code...

jwright6323 commented 8 years ago

@palmer-dabbelt and I had a very similar discussion a few days ago. We could really use this on our projects that actually see silicon. I don't think there's currently any way to wire an IO to a clock (even if you could convert Bool to/from Clock) because IOs have to be "Data"s.

It would be nice to be able to have a BlackBox output Clock objects that you could then wire directly to module clk inputs. The PLLs, clock dividers, etc. could just use this and set some integer divide-by or multiply-by within the Chisel module (which seems to already be a feature).

palmer-dabbelt commented 8 years ago

After the Hurricane tapeout we're going to have to just go and do a multiclock Chisel design and fix things until they work -- I'm sick of dealing with the Raven Verilog post-processing we do.

shunshou commented 8 years ago

Yeah, I tried using clock as an IO without first checking if it was supported and Chisel barfed. Haha... It's a problem when Clock doesn't extend data... I'm ok restricting clocks to only come from the output of registers (but that wouldn't really work if you wanted a clock mux), so would it be possible to add a clock-like trait to register outputs (i.e. extends Data with trait Clock-like, which might be clunky...) that would then allow some kind of out.toClock function / IO support? That'd maybe initially restrict the problem to make it doable? Idk if there is anything within Chisel that would break if you allow any Bool to be out.toClock-able...

On that note, I don't think it needs to necessarily be a black box, since, for a typical counter-based freq. divider, you'd have to write up the Verilog anyways, and logically speaking, you should be able to do that just fine in Chisel (and have the divider be parameterizable !!)... You would need to black box a more complicated PLL though, and that's reasonable...

Also, on the note of integer divide-by or multiply-by with clocks, I need to go back through Module, but I think you can add a clock to a module. It doesn't go through IO, but will create an additional clock port with some clock name you specify for each module... I'm not sure if that clock port will get propagated to the top module if it's only used in some child module, but I assume that's what happens or what should have happened... In that case, you'd just then need to do Verilog post-processing to add in your desired PLL or w/e... (similar complexity to how vlsi_mem_gen works, which I guess isn't too bad?... although I'd also like that to support more options...).

But yeah, I'm pretty concerned about power... 1) for memory access, I really ideally would like to have a clock mux going into SRAM b/c in one operation phase, I need to operate at 2x frequency, in another, I don't. 2) A good chunk of my registers only need to operate at the slow clock rate... I think that using an enable (even if it gets converted into clock gating) is still worse than being able to just use the slow clock to begin with...

So if you could save a huge chunk of power by doing a better job of supporting multiple clock domains, you really should be doing it... Esp. since these cases just require clocks to be integer multiples of each other...

And for supporting ASIC, I think getting this feature in should be a top priority, since we need to be competitive on power...


On a completely separate topic (which prob deserves its own post), I've had to hack the Chisel Verilog backend to add an INITN to the memory port declaration... It's really annoying that memory isn't considered a module, so the global reset (or I heard Raven people wanted to use another reset that wasn't global reset) isn't propagated to it... (and from reading SRAM datasheets, an N ns reset is required for them to operate properly).

In general, there should be better templating to support different flavors of memory.

sdtwigg commented 8 years ago

In generally, allowing any Bool signal to be converted into a clock (that then ultimately drives registers) will likely end up (thoroughly) breaking the C++ backend and general combinational loop check. (Since, really, you can start describing logic that is no longer really 'synchronous.')

Restricting to only allowing outputs of registers to be convertible reduces the breakage (and I think makes fixing the C++ backend more feasible). (Note, there is still the chance for weird errors that you may want to try to catch like a register whose clock is transitively dependent on its own output.)

shunshou commented 8 years ago

Anyone want to work on this? ^_~