I am writing my Very First Verilog Program Ever: I'm trying to capture intervals between incoming pulses. I have a sample clock, an asynchronous pulse source, and the output is a registered 8-bit byte and an interrupt line; every time a pulse arrives, I assert the interval in the range 0x00-0x7f on the output and twiddle the interrupt, and a microcontroller DMAs it into memory. (The context.)
That bit works fine. The complication is that if a pulse doesn't arrive by the time my internal counter rolls over, I emit a 0x80 byte. The intention is that long intervals are to be represented as multiple bytes.
What I am finding is that intervals in the 0x00-0x7f range work fine, but longer intervals emit complete garbage. The logic looks very simple to me, so there's obviously something I'm not getting in the way Verilog works. Anything here look obviously wrong?
My constraints are:
the input signal is not aligned with the sample clock, and each signal may span multiple clock ticks. I only care about the rising edge.
interrupts are edge-triggered but there's a delay between the interrupt and the DMA read. I do appear to need the latch on
result
to ensure the result remains asserted.I know there's no reset, I'll do that later.
this is on a Cypress PSoC5LP development kit, which uses a cut-down version of Warp Verilog. I did try to use EDA Playground to simulate it, and it all seems to work there, but it doesn't work in real life.
in real life, my sample clock is 12MHz and an input pulse can be anything from 150ns to 500ns.
there may actually be nothing wrong and I'm hitting hardware constraints in my pulse generator. Which isn't confusing at all.
Update: my hardware can't generate pulses closer together than about 750ns, which is about nine sample clocks, so I don't think I need to worry about pulses coming in in successive clocks. Update update: no, that's rubbish. Pulses 0x81 ticks apart will need to generate two bytes, 0x80 and 0x01, one sample clock apart.
module Sampler (
output reg interrupt, // a pulse has been detected
output reg [7:0] result, // output data byte
input clock, // sample clock
input sample // incoming signal
);
reg [6:0] counter; // monotonically increasing counter
reg last_sample; // for sample edge detection
always @(posedge clock)
begin
if (counter == 0)
begin
// Rollover.
result = 8'h80;
interrupt = 1;
counter = 1;
end
else if (sample && !last_sample)
begin
// A sample happened since the last clock.
result[6:0] = counter;
result[7] = 0;
interrupt = 1;
counter = 1;
end
else
begin
counter = counter + 1;
interrupt = 0;
end
last_sample = sample;
end
```
sample
through a synchronizer first? Any state machine needs to have its inputs synchronized to its own clock. Second, if you have intervals that are just a little longer than 0x80 counts, you'll get two interrupts essentially back-to-back. Can your CPU deal with this correctly? You might need a small FIFO to buffer these events. \$\endgroup\$