# Sharing data in two different always @(posedge …) blocks

I have the following two signals A and B

      __________                                           __________
_____|          |_________________________________________|          |_____
__                   __    __    __    __    __    __                  __
|  |_________________|  |__|  |__|  |__|  |__|  |__|  |________________|


Note that:

• There is no common clock between them available
• Signal B always changes when A is low and A always changes when B is low

I would like to create a 6-bit counter that increments its value every negative edge of signal A and then outputs its value bitwise in between, exactly at the positive edges of signal B.

The problem is I have to share a state between these two, for example:

wire bit_output;
reg [5:0] counter;
reg [5:0] current_value;
always @(posedge signalA) begin
counter <= counter + 1;
current_value <= counter;
end

always @(posedge signalB) begin
current_value <= { current_value[4:0], 1'b0 };
end

assign bit_value = current_value[5];


Now this is unfortunately not a valid Verilog code, for example in Xilinx ISE I get:

Signal current_value[5] in unit test is connected to following multiple drivers:


I tried placing them into one always statement but this is not possible either:

Assignment under multiple single edges is not supported for synthesis


If I had a common clock I could use a conventional state machine but in this case I only have these two independent signals.

No matter with which solution I come up, I always need to share data somehow.

I do not want to run both paths independently; for example having a counter for SignalB and if it is zero, initialize with data from A because the initial condition would be undefined. I would like to ensure that the data that is spit out on the positive edges of signal B are always properly initialized at the falling edge of signal A even if, for example, only 3 positive signal B edges occur.

What is the easiest way to implement this?

(this is just a simplified example to keep things compact; the actual task is more complicated)

• If you had to implement this with actual logic components, how would you do it? If you're not sure of that, then this is a logic design question, not a Verilog question. – The Photon Mar 30 '18 at 15:34

To do this in an FPGA, the usual way would be to introduce a new clock, running much faster than A or B. Clock your logic from this new clock and use A and B only as control signals, not as clocks.

The new clock must be fast enough to be guaranteed to have at least one edge for each change of value of the A and B inputs.

module weird_counter(A, B, CLK, Q);
input A, B;
input CLK;
output Q;

reg [2:0] Bd; /* Delayed copies of A and B */
reg [5:0] ctr;
reg [5:0] obuf;

assign Q = obuf[5];

always @(posedge CLK) begin
Bd <= {Bd[1:0], B};

always @(posedge CLK) begin
if(Ad[1] & ~Ad[2]) begin /* We are seeing a rising edge on A */
/* Do something with ctr and obuf*/
end
if(Bd[1] & ~Bd[2]) begin /*Rising edge on B */
/* Do something else with ctr and obuf*/
end
end

endmodule;


Edit: Added some stages to Ad and Bd at Tom Carpenter's suggestion to demonstrate syncronizing a signal across clock boundaries. This reduces the risk of a logic fault due to violating set-up and hold times.

• I'd also add a couple or registers to synchronise the signals to the clock given they have no common clock. – Tom Carpenter Mar 30 '18 at 15:56

If I use this specification:
Signal B always changes when A is low and A always changes when B is low, I would like to create a 6-bit counter that increments its value every negative edge of signal A and then outputs its value bitwise in between, exactly at the positive edges of signal B.

I get this code:

always @(negedge A)
if (B==0)
counter <= counter + 1;

always @(posedge B)
if (A==0)
bit_out <= bit_out + 1;

assign serial_out = counter[bit_out];


I you can guarantee the transition do no happen when the signals are high you can omit the two "if (A/B==0)" sections.
As to in between, exactly at the positive edges of signal. You must control that by correctly making the A and B signals.

if, for example, only 3 positive signal B edges occur.? In this case, the next cycle should still have a fresh start. bit_out has to be set to zero by the first always @ statement

You might still do that by using A as a-synchronous reset:

always @(posedge B or posedge A)
if (A)
bit_out <= 0; // reset counter when A is high
else
bit_out <= bit_out + 1;


The rising edge of B must not coincide with the falling edge of A.

But there comes a time when you can't do these things with purely synchronous logic. For example I2C is very, very difficult to do in pure Verilog logic and most of the time the interface runs using a clock at a much higher frequency.

• But what about the requirement even if, for example, only 3 positive signal B edges occur.? In this case, the next cycle should still have a fresh start. bit_out has to be set to zero by the first always @ statement ... – divB Mar 30 '18 at 9:53