10-01-2016 09:11 PM
I am having some trouble with getting a counter variable to work across two different always blocks. This code is part of a much bigger picture. Basically I am trying to keep track of the number of bytes which need to be written from external RAM to external sd card (from volatile to non-volatile memory). In one always block new bytes are marked in a 'dirt table', indicating that these bytes have changed and need to be updated. In the other always block I transverse the dirt table, if a byte is marked I then updated the sdcard with the corresponding byte from my external RAM, I then decrement the byte counter.
With my current implementation I need to transverse the entire RAM dirt table to check which bytes need to be updated. My solution works well but I want to speed up the process. So, I would like to keep track of how many bytes need to be updated. If i do this then I can terminate the dirt table search whenever I have written all of the dirty bytes to RAM instead of blindly transverse the entire table even after all of the dirty bytes have been updated.
I have tried the implementation below (it is sudo code), however my count variable doesn't seem to be accurate. Is there a better way of keeping track of a variable between two always blocks?
input setEdge; input newbyte; reg [15:0] numbytes_q, numbytes_d; always @* begin numbytes_d = numbytes_q if(newbyte) begin numbytes_d = numbytes_q + 1; end end always @(posedge clk) begin if(setEdge) begin //send one of the bytes, decrement counter by one. numbytes_q <= numbytes_q - 1; end else begin numbytes_q <= numbytes_d; end end
10-01-2016 11:18 PM - edited 10-01-2016 11:19 PM
you don't really need two always blocks.
end else if (newbyte) begin numbytes_q <= numbytes_q +1; end
10-02-2016 04:12 AM
Thanks for the suggestion, but as I mentioned in my original post this problem is part of a much larger code base. The reason for the two always blocks is that one is essentially a state machine running off a 100Mhz input clock signal, the FPGA main clock source. The other always block is triggered by an external clock source, in this case a piece of hardware I am interfacing with. The clocks are not synchronized or the same speeds.
10-02-2016 08:58 AM
>> The clocks are not synchronized or the same speeds.
There is your problem. There is no amount of heartache this won't cause you (said Yoda ;-). You have to find a way to compute all your logic in the same clock. Read about asynchronous clocks and clock domain crossing if you are not familiar with the topic.
10-02-2016 02:21 PM
As always, I start answers to this with the phase "Think Hardware". You are asking for the synthesis tool to create some circuit that changes on the rising edges of two different clocks. What hardware cell that you know of can do this? In an FPGA, the answer is "there is no such thing".
For "generic" logic, an FPGA has LUTs (and some other stuff) for combinatorial logic, flip-flops (which have only one clock input) and latches. None of these have two clocks. Therefore, it shouldn't be a surprise to you that the tools are telling you "What you are asking me is impossible" - it's right!
So, as @muzaffer said, you absolutely have to find a way of doing this counter on one clock. If the conditions that affect this clock come from different clock domains, then you first must properly cross one of the two conditions from its clock domain to the other one, and do the counter on only one domain.
Alternatively, you need to create an architecture that does what you want in a different way. For example, it may be possible to have TWO counters, one on each domain, and then do some kind of comparison between them with proper clock crossing to accomplish what you want - this is, for example, how the read and write pointers of a FIFO operate...