<d1b2>
<garbile> I'm having trouble with clock domains and I would appreciate any examples someone can link to. I want to asynchronously count something, so I made a self-incrementer clocked by this clock domain, which is clocked by a fast async signal. This seems to work fine, but I can't seem to find a way to reset the counter from the main sync domain.
<d1b2>
<garbile> I can start and stop the async signal, so I can ensure the counter doesn't count while I'm resetting it to zero
<d1b2>
<garbile> This was my clever solution but it doesn't behave as expected py m.d += ClockDomain("count_me",async_reset=True)#, reset_less=True) m.d.comb += ClockSignal("count_me").eq(input_value) reset_mask = Cat(~self.reset * self.width) m.d.count_me += self.counter.eq((self.counter + 1) & reset_mask)
<d1b2>
<garbile> And this was my first attempt, but I get the yosys error "Multiple edge sensitive events found for this signal" py with m.If(self.reset): m.d.count_me += self.counter.eq(0) with m.Else(): m.d.count_me += self.counter.eq(self.counter + 1)
<d1b2>
<Herr Brain> First, I would recommend using a gray code counter. They tend to be more error tolerant. In terms of examples, I don't have anything Amaranth specific, but Cliff Cummings has some excellent articles on both clock domain crossings and reset techniques. http://www.sunburst-design.com/papers/
<d1b2>
<Herr Brain> Yes, the example code is in Verilog. No, it doesn't make a significant difference.
<d1b2>
<Herr Brain> (Check the asynchronous FIFO article for an excellent gray code counter design)
<d1b2>
<Herr Brain> (Note: you only need a gray code counter if you are planning to send the count itself across the clock domain crossing)
<d1b2>
<garbile> My FSM is like this: 1. reset counter 2. enable repeating async signal that I want to count 3. disable async signal 4. copy the count into the main clock domain 5. wait The only tight and consistent timing I need is between 2 and 3, so I can easily add a big timing buffer between 3 and 4 to hopefully prevent any domain crossing issues. I'll look into using a gray code counter, but it seems like there should be an easy way to do what I
<d1b2>
want...
<d1b2>
<Herr Brain> A gray code counter will definitely simplify copying between domains. As far as enabling/disabling the async signal is concerned: is there a reason you are gating the input signal as opposed to using a clock enable on the counter?
<d1b2>
<garbile> No, it doesn't matter either way. I'm trying to measure the speed of a ring oscillator, so I can either start and stop it, or I can start and stop the counter
<d1b2>
<Herr Brain> If this is in an FPGA, it will likely be faster to implement using clock enables, since it will almost certainly map directly to the internal hardware. Gating the input signal may add another LUT stage, and increase the likelihood of a runt pulse/glitch.
<d1b2>
<garbile> Yeah, it's an iCE40. Alright, so you're suggesting: ring oscillator drives clock domain, grey code counter counts clock pulses in this domain, counter has a clock enable signal that I can use to start and stop it from the main clock domain?
<d1b2>
<dragonmux> beware of LUT jitter from your ring oscillator, but yes.. that'd work
<d1b2>
<dragonmux> don't forget to include a reset for the counter too
<d1b2>
<Herr Brain> As a general rule, FPGAs really don't like connecting clock to data. It's possible, but as dmux said LUTs can introduce jitter. There's also potentially a chance that the entire oscillator will go metastable, generating excess heat and possibly damaging the fabric.