3
\$\begingroup\$

I am trying to output a 2 bit-number that indicates which input signal changed during the time span when "detection mode" is switched on by another input signal. The output is saved in a register.

Each time detection mode is switched off and on again, the output/register should be set to 0.

So the register depends on changes in multiple signals. The way I know of to react to signal changes is using always blocks. However, inside one always @* block reacting to any change, as I understood, it is not possible to differentiate between changes in different signals and react to each of them in a separate block, as always cannot be nested, and @negedge / @posedge is not synthesizable.

I do not use a clock, purely combinatorial logic, to limit complexity in the overall FPGA-Microcontroller system. Unless there is no other solution, this should not change.

Edit on May 28, 2023 The signals are independent from each other and use a one-wire data transmission protocol without a second clock line. The minimum period between signal changes is around 100ns. I prefer not to have to include a clock detection circuit. Only one input is connected at a time. The aim of the circuit is to detect which input is connected. Edit end

I have difficulties realizing this behaviour using only one always block (always @*). Using several always blocks, I run into the problem that one register cannot be set by several always blocks. I could not find any hints on how implement this logic on stackexchange or elsewhere. I believe that maybe combinatorial logic with more registers could somehow lead to the desired result, but I am not sure how.

Neither do I understand how I can integrate the always @Local_Mother1 and 2 blocks into the first always block and set the Signal Number inside that block correctly.

My code looks as follows, but results in an error (Only one always block can assign a given variable)

input wire Local_Mother1, Local_Mother2; //The signals to be detected (only one signal may be connected)
            
input wire Steuerung;   //Used for controlling detection mode

reg r_LMCode[0:1]=0 ;   //Initialized at 0, this synthesizes using Lattice ICE40 - Signal number        
reg r_LMdetectmode=0;   //Initialized at 0, this synthesizes using Lattice ICE40 - Detection mode
        
//Handle the detection mode switch-on and off
always @(Steuerung) begin
    if (r_LMdetectmode==0) begin    //detection mode off

        if (Steuerung==1)   //This switches on detection mode
            r_LMdetectmode <= 1; 
            //r_LMCode <=0; //could be set here as well, but does not change the problem

    end else begin //Detection mode is on
        if (Steuerung==0) begin
            r_LMdetectmode <=0;     //Switch off detection mode
            r_LMCode <= 0;      //Signal Number set to 0 - gives an error!
        end
    end
end

always @(Local_Mother1) begin   //in case Signal 1 has changed
    if (r_LMdetectmode==1)
        r_LMCode <= 1;  //Set signal number to 1 if detect mode is on - error!
end
        
always @(Local_Mother2) begin   //in case Signal 2 has changed
    if (r_LMdetectmode==1)
        r_LMCode <= 2;  //Set signal number to 2 if detect mode is on - error!
end
\$\endgroup\$

2 Answers 2

1
\$\begingroup\$

There is no advantage in doing this asynchronously, it doesn't reduce complexity. In fact it is worse as you are inferring latches.

Here's a suggested synchronous solution - it assumes your inputs are already synchronous to the clock; if they are not they should be resynchronised. I've also assumed that the inputs are independent and the r_LMCode bits are also independent. (From edited question, only one input will be active at any time).

reg  r_Local_Mother1;
wire LM1_delta;
reg  r_Local_Mother2;
wire LM2_delta;
reg  [1:0] r_LMCode;
wire [1:0] LMCode_nxt;

// Set delta flag when the current input doesn't match the last
assign LM1_delta = r_Local_Mother1 ^ Local_Mother1;
assign LM2_delta = r_Local_Mother2 ^ Local_Mother2;

assign LMCode_nxt =   Steuerung 
                    // r_LMCode is sticky when set in detection mode
                    ? (r_LMCode | {LM2_delta, LM1_delta}) 
                    // Clear to 0 when ~Steuerung
                    : 2'b00; 

always @(posedge clk or posedge reset) begin
  if (reset) begin
    r_LMCode        <= 2'b00;
    r_Local_Mother1 <= 1'b0;
    r_Local_Mother2 <= 1'b0;
  end else begin
    r_LMCode        <= LMCode_nxt;
    r_Local_Mother1 <= Local_Mother1;
    r_Local_Mother2 <= Local_Mother2;
  end
end

NB, this is just a suggestion, depending on your exact requirements (signal ordering etc) you may need to change it :)

\$\endgroup\$
2
  • \$\begingroup\$ Dear Awjlogan, I now realize that I can detect signal changes by comparing the current value to a saved last value of the signal. However, I do not understand the disadvantage to do this comparison every time any signal changes (when an always@* block is called) versus every time a clock advances. Is there an issue when signal changes occur very rapidly? Does the added information in the question (highlighted with edit) eliminate potential latch timing problems? \$\endgroup\$
    – DerGrisu
    May 28, 2023 at 7:35
  • \$\begingroup\$ @DerGrisu - comparing to a previous value implies storage, ie, a latch or a clocked register (also the captured output). The information re. the minimum period is useful - you will be able to capture this with a clock >10 MHz (ie, very easy). Latches make timing harder, and tools will generally warn you when a latch is inferred - it's not usually what you want. Have a search for many articles on this topic :) Is there a reason you really want to do it this way? \$\endgroup\$
    – awjlogan
    May 28, 2023 at 20:05
2
\$\begingroup\$

I do not use a clock, purely combinatorial logic, to limit complexity in the overall FPGA-Microcontroller system.

Since your current attempts at implementing your design do not work, you should consider using a clock instead of trying to implement purely combinatorial logic. You tagged this question with register and mention using registers several times. The term register implies memory storage, which can be achieved with flip flops, latches, etc. Latches have more timing limitations than flip flops for synthesis.

A good approach uses flip flops with clocks; refer to synthesizable constructs and your FPGA tool suite documentation. Those show you good Verilog coding style for synthesis.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.