Hi!
I have a verilog system with two modules. The first one operates on some data then passes the processed data to the next module for processing. Both modules share memory space and so I need to pass memory control from one module to the next depending on who is processing. Therefore each module has an output called RAM_LOCK that indicates that the module wants to have control of RAM.
Each module has an input called NEW_DATA_IN that marks the start of operation and then operates for some clock cycles. The RAM_LOCK signal needs to be asserted as soon as NEW_DATA_IN is asserted so that it can set up the addresses for the RAM on the next clock cycle (ie it cannot wait until the next clock edge after NEW_DATA_IN is asserted because that is when it needs to do a memory operation). It will then de-assert RAM_LOCK after a certain number of RAM cycles.
Unfortunately, my system is far too complex to post all the code here but I'll post the most relevant parts.
Module A: (RAM_LOCK is an output, NEW_DATA is the input specifying new input data, cycle_count is the number of cycles since data was recieved
...
always @(*) begin
// We need RAM control as soon as NEW_DATA is asserted so we can set the read address for the next cycle
// We can deassert RAM control jsut before the last cycle as we do not need to set up any more read/writes
RAM_LOCK = (NEW_DATA == 1 ? 1 : (cycle_count == READ_CYCLES+WRITE_CYCLES-1 ? 0 : RAM_LOCK));
end
...
Module B:
...
always @(*) begin
// We need RAM control as soon as NEW_DATA_IN is asserted so we can set the read address for the next cycle
// We can deassert RAM control just before the last cycle as we do not need to set up any more read/writes
RAM_LOCK = (NEW_DATA_IN == 1 ? 1 : (CYCLE_COUNT == (KERNEL_WIDTH*KERNEL_HEIGHT*2)-1 ? 0 : RAM_LOCK));
end
...
Memory interface is main module:
...
assign RAM_ADDR = (A_RAM_LOCK ? A_RAM_ADDR : (B_RAM_LOCK ? B_RAM_ADDR : 0));
assign RAM_WE = (A_RAM_LOCK ? A_RAM_WE : (B_RAM_LOCK ? B_RAM_WE : 0));
assign A_RAM_DO = (A_RAM_LOCK ? RAM_DO : 16'hBABE);
assign B_RAM_DO = (B_RAM_LOCK ? RAM_DO : 16'hBEEF);
assign RAM_DI = (A_RAM_LOCK ? A_RAM_DI : (B_RAM_LOCK ? B_RAM_DI : 16'hDEAD));
...RAM_ADDR, RAM_WE, RAM_DI (data in) and RAM_DO (data out) are the wires for the memory.
So what's the problem? Module A is working fine, but BEEF keeps showing up my output from module B indicating that control of the memory is not being passed correctly to module B.
If I replace the RAM_DO lines with these lines:
assign A_RAM_DO =RAM_DO;
assign B_RAM_DO = RAM_DO;
Then it fixes the issue, but clearly there is something going on in the background that I want to fix so it doesn't come back to bite me later.
What's even weirder? If I put in a comparison in my Main module it fixes the issue:
...
assign LED[11] = ramalam;
assign LED[10] = ramalam2;
assign LED[9] = ramalam3;
... (in an always at posedge of clock)
if(A_RAM_LOCK == 1) begin
ramalam <= 1;
end
if(B_RAM_LOCK == 1) begin
ramalam2 <= 1;
end
if(A_RAM_LOCK == 1 && B_RAM_LOCK == 1) begin
ramalam3 <= 1;
end
...
If I put these lines in (basically detecting whether each of the locks have been asserted) and show them on an LED, suddenly everything is fixed. What on earth?
I've seen a similar issue before where one of my inputs was labelled as an output, and fixing that fixed the issue, but I can't find anything similar in this case.
What could be causing this issue?!