How to drive outputs in Verilog

Viewed 35

I am trying to implement I2C in a FPGA to learn verilog, i am a complete beginner and am having trouble with an error:

 Error (10028): Can't resolve multiple constant drivers for net "rComStarted" at I2CModule.v(14)

I am currently just trying to implement the start and end conditions for I2C and as a half way point just want to connect the rComStarted value to the output just to see it working (also you can ignore the face that i have an input and output sda I'm just seperating them for now because im worried about frying something)

To be clearer about what I expect from this code:

  • If SDAIn has negative edge and SCL is high I want to enable rComStarted
  • if SDAOut has posedge and SCL is high i want to pull rComStarted low
  • rComStarted should be connected to SDAOut

code:

module SafeI2CSlave(input SDAIn, output SDAOut, input SCL);

reg rComStarted;
reg rChipSelect;
assign SDAOut = rComStarted;
always@(negedge SDAIn)
begin 
    if(SCL)
    begin
        rComStarted = 1'h1;
    end
end

always@(posedge SDAIn)
begin 
    if(SCL)
    begin
        rComStarted = 1'h0;
    end
end
endmodule

why am i getting this errors? What is the best way to implement the functionality i want?

Thanks so much!

2 Answers

You are driving the same var rComStarted from two different always blocks. It cannot be implemented in hardware. Therefore it is illegal. Think of a different way of implementing your algorithm. It can only be driven by a single block.

I guess you need to do something like the following:

always @* begin
   if (SCL)
      rComStarted = ~SDAIn;
end

You need two separate registers for each edge. The example bellow toggles the rComStarted_p and rComStarted_n on there respected edges, then XORs them to rComStarted. The first negedge SDAIn will raise rComStarted (p:0 ^ n:1 = 1). The first posedge will lower rComStarted ( p:1 ^ n:1 = 0). The second negedge will raise rComStarted (p:1 ^ n:0 = 0). Finally, the second posedge will lower rComStarted and will bring rComStarted_p and rComStarted_n back to there initial state.

module SafeI2CSlave(input SDAIn, output SDAOut, input SCL);
  reg rComStarted_p = 1'b0;
  reg rComStarted_n = 1'b0;
  reg rChipSelect;
  wire rComStarted = rComStarted_p ^ rComStarted_n;
  assign SDAOut = rComStarted;
  always@(negedge SDAIn) begin 
    if(SCL && !rComStarted) begin
      rComStarted_n <= !rComStarted_n;
    end
  end
  always@(posedge SDAIn) begin 
    if(SCL && rComStarted) begin
      rComStarted_p <= !rComStarted_p;
    end
  end
endmodule
Related