There isn't quite enough information in your question as to the best way to approach this. However I will make two assumptions:
- The signals are conditioned (i.e. no spurious pulses or noisy edges)
- You are able to sample the signals with a fast clock to make them synchronous. This means you can simply check the signals at discrete time points rather than asynchronously.
Given these assumptions, the approach I would use is to detect the edges of the signals using a simple synchronous edge detector. You can then use a state machine to determine the order of events.
//First we sample the signals with fast clock and perform edge detection.
//This gives us a series of discrete time points to work with
reg aDly, bDly;
reg aFall, bRise;
always @ (posedge fastClock) begin
aDly <= a;
bDly <= b;
aFall <= aDly && !a; //Falling edge of a when aDly high and a low.
bRise <= !bDly && b; //Rising edge of b when bDly low and b high.
end
reg someEvent; //Set this high when c needs to fall.
//Now we do the logic for C with a state machine.
localparam IDLE_STATE = 2'b00;
localparam AFIRST_STATE = 2'b01;
localparam BFIRST_STATE = 2'b10;
reg [1:0] stateMachine;
reg c;
always @ (posedge fastClock or posedge reset) begin
if (reset) begin
stateMachine <= IDLE_STATE;
c <= 1'b0;
end else begin
case (stateMachine) begin
IDLE_STATE: begin //Wait for the start of an event sequence.
//If the start of a sequnece
if (bRise && aFall) begin
//If both happen at the same time
c <= 1'b1; //C goes high immediately.
end else if (aFall) begin
//If falling edge of a comes first
c <= 1'b0; //C stays low.
stateMachine <= AFIRST_STATE; //And go on to wait for b rising.
end else if (bRise) begin
//If rising edge of b comes first
c <= 1'b0; //C stays low.
stateMachine <= BFIRST_STATE; //And go on to wait for a falling.
end else if (someEvent) begin
//Work out when C should go low - I can't tell this from your description
c <= 1'b0; //C goes low.
end
end
AFIRST_STATE: begin //Wait for rising edge of b
if (bRise) begin
//Once rising edge of b occurs,
c <= 1'b1; //C goes high.
stateMachine <= IDLE_STATE ; //Return to idle.
end
end
BFIRST_STATE: begin //Wait for falling edge of a
if (aFall) begin
//Once rising edge of b occurs,
c <= 1'b1; //C goes high.
stateMachine <= IDLE_STATE ; //Return to idle.
end
end
endcase
end
end
You will need to work out what logic to use to determine when C should go low. I can't tell this from your question.
If you want a fixed width, you could use a counter which is triggered when C goes high.