[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]

Re: gEDA-user: iVerilog -tfpga: if-else errors?



Mike Butts wrote:
In iVerilog, synthesizing even a simple if-else results in errors:
For example, this simple FF with clock enable and asynch reset from the Alternate Verilog FAQ:

module dff_cke (data, clock, reset, cke, q);
// port list
input data, clock, reset, cke;
output q;

// reg / wire declaration for outputs / inouts
reg q;

// logic begins here
always @(posedge clock or negedge reset)
if (reset == 0)
q <= 1'b0;
else if (cke == 1'b1)
q <= data;
endmodule
Normally, I would try to get a bug report into the ivl-bugs database
before really working on a problem like this, but I happen to be in
the area anyhow, so I'll let it slide:-)

The problem here, it turns out, was the inability to detect the
asynchronous clear that you had. The "reset == 0" expression is
what confused the rather simplistic check. I've improved that check
and now I get an asynchronous clear where intended. Note that the
error handling here is still pretty weak.

I've attached a patch that should apply to the 20030730 snapshot.
I've also attached the edif output I get from -tfpga -parch=virtex.

Please follow the links from the Icarus Verilog web page to the
bugs reporting page. You can submit bugs by web form or e-mail.

--
Steve Williams                "The woods are lovely, dark and deep.
steve at icarus.com           But I have promises to keep,
http://www.icarus.com         and lines to code before I sleep,
http://www.picturel.com       And lines to code before I sleep."


Index: synth2.cc
===================================================================
RCS file: /home/u/icarus/steve/CVS/verilog/synth2.cc,v
retrieving revision 1.27
diff -p -u -r1.27 synth2.cc
--- synth2.cc	23 Jun 2003 00:14:44 -0000	1.27
+++ synth2.cc	10 Aug 2003 16:49:42 -0000
@@ -481,61 +481,75 @@ bool NetCondit::synth_sync(Design*des, N
 			   const NetNet*nex_map, NetNet*nex_out,
 			   const svector<NetEvProbe*>&events_in)
 {
+	/* First try to turn the condition expression into an
+	   asynchronous set/reset. If the condition expression has
+	   inputs that are included in the sensitivity list, then it
+	   is likely intended as an asynchronous input. */
 
-	/* Synthesize the enable expression. */
-      NetNet*ce = expr_->synthesize(des);
-      assert(ce->pin_count() == 1);
-
-	/* Try first to turn the ce into an asynchronous set/reset
-	   input. If the ce is linked to a probe, then that probe is a
-	   set/reset input. */
+      NexusSet*expr_input = expr_->nex_input();
+      assert(expr_input);
       for (unsigned idx = 0 ;  idx < events_in.count() ;  idx += 1) {
+
 	    NetEvProbe*ev = events_in[idx];
+	    NexusSet pin_set;
+	    pin_set.add(ev->pin(0).nexus());
+
+	    if (! expr_input->contains(pin_set))
+		  continue;
 
-	    if (connected(ce->pin(0), ev->pin(0))) {
+	      /* Ah, this edge is in the sensitivity list for the
+		 expression, so we have an asynchronous
+		 input. Synthesize the set/reset input expression. */
+
+	    NetNet*rst = expr_->synthesize(des);
+	    assert(rst->pin_count() == 1);
+
+	      /* XXXX I really should find a way to check that the
+		 edge used on the reset input is correct. This would
+		 involve interpreting the exression that is fed by the
+		 reset expression. */
+	      //assert(ev->edge() == NetEvProbe::POSEDGE);
+
+	      /* Synthesize the true clause to figure out what
+		 kind of set/reset we have. */
+	    NetNet*asig = new NetNet(scope, scope->local_symbol(),
+				     NetNet::WIRE, nex_map->pin_count());
+	    asig->local_flag(true);
+	    bool flag = if_->synth_async(des, scope, nex_map, asig);
+
+	    assert(asig->pin_count() == ff->width());
+
+	      /* Collect the set/reset value into a verinum. If
+		 this turns out to be entirely 0 values, then
+		 use the Aclr input. Otherwise, use the Aset
+		 input and save the set value. */
+	    verinum tmp (verinum::V0, ff->width());
+	    for (unsigned bit = 0 ;  bit < ff->width() ;  bit += 1) {
 
-		  bool flag = true;
-		  assert(ev->edge() == NetEvProbe::POSEDGE);
+		  assert(asig->pin(bit).nexus()->drivers_constant());
+		  tmp.set(bit, asig->pin(bit).nexus()->driven_value());
+	    }
 
-		    /* Synthesize the true clause to figure out what
-		       kind of set/reset we have. */
-		  NetNet*asig = new NetNet(scope, scope->local_symbol(),
-					   NetNet::WIRE, nex_map->pin_count());
-		  asig->local_flag(true);
-		  flag = if_->synth_async(des, scope, nex_map, asig) && flag;
-
-		  assert(asig->pin_count() == ff->width());
-
-		    /* Collect the set/reset value into a verinum. If
-		       this turns out to be entirely 0 values, then
-		       use the Aclr input. Otherwise, use the Aset
-		       input and save the set value. */
-		  verinum tmp (verinum::V0, ff->width());
-		  for (unsigned bit = 0 ;  bit < ff->width() ;  bit += 1) {
-
-			assert(asig->pin(bit).nexus()->drivers_constant());
-			tmp.set(bit, asig->pin(bit).nexus()->driven_value());
-		  }
-
-		  assert(tmp.is_defined());
-		  if (tmp.is_zero()) {
-			connect(ff->pin_Aclr(), ce->pin(0));
-
-		  } else {
-			connect(ff->pin_Aset(), ce->pin(0));
-			ff->aset_value(tmp);
-		  }
-
-		  delete asig;
-
-		  assert(events_in.count() == 1);
-		  return else_->synth_sync(des, scope, ff, nex_map,
-					   nex_out, svector<NetEvProbe*>(0))
-			&& flag;
+	    assert(tmp.is_defined());
+	    if (tmp.is_zero()) {
+		  connect(ff->pin_Aclr(), rst->pin(0));
+
+	    } else {
+		  connect(ff->pin_Aset(), rst->pin(0));
+		  ff->aset_value(tmp);
 	    }
 
+	    delete asig;
+	    delete expr_input;
+
+	    assert(events_in.count() == 1);
+	    return else_->synth_sync(des, scope, ff, nex_map,
+				     nex_out, svector<NetEvProbe*>(0))
+		  && flag;
       }
 
+      delete expr_input;
+
 	/* Failed to find an asynchronous set/reset, so any events
 	   input are probably in error. */
       if (events_in.count() > 0) {
@@ -543,6 +557,11 @@ bool NetCondit::synth_sync(Design*des, N
 		 << " for in process synthesis." << endl;
 	    des->errors += 1;
       }
+
+	/* Synthesize the enable expression. */
+      NetNet*ce = expr_->synthesize(des);
+      assert(ce->pin_count() == 1);
+
 
 	/* If this is an if/then/else, then it is likely a
 	   combinational if, and I should synthesize it that way. */
(edif dff_cke
    (edifVersion 2 0 0)
    (edifLevel 0)
    (keywordMap (keywordLevel 0))
    (status
     (written
        (timeStamp 0 0 0 0 0 0)
        (author "unknown")
        (program "Icarus Verilog/fpga.tgt")))
    (external VIRTEX (edifLevel 0) (technology (numberDefinition))
      (cell FDCE (cellType GENERIC)
            (view net
              (viewType NETLIST)
              (interface
                (port Q (direction INPUT))
                (port C (direction INPUT))
                (port D (direction OUTPUT))
                (port CE (direction INPUT))
                (port CLR (direction INPUT)))))
      (cell INV (cellType GENERIC)
            (view net
              (viewType NETLIST)
              (interface
                (port O (direction OUTPUT))
                (port I (direction INPUT)))))
      (cell BUF (cellType GENERIC)
            (view net
              (viewType NETLIST)
              (interface
                (port O (direction OUTPUT))
                (port I (direction INPUT)))))
      (cell VCC (cellType GENERIC)
            (view net
              (viewType NETLIST)
              (interface
                (port VCC (direction OUTPUT)))))
      (cell GND (cellType GENERIC)
            (view net
              (viewType NETLIST)
              (interface
                (port GROUND (direction OUTPUT)))))
    )
    (library DESIGN
      (edifLevel 0)
      (technology (numberDefinition))
      (cell dff_cke
        (cellType GENERIC)
        (view net
          (viewType NETLIST)
          (interface
            (port cke (direction INPUT))
            (port clock (direction INPUT))
            (port data (direction INPUT))
            (port q (direction OUTPUT))
            (port reset (direction INPUT))
          )
          (contents
(instance U3 (viewRef net (cellRef FDCE (libraryRef VIRTEX))))
(instance U2 (viewRef net (cellRef INV (libraryRef VIRTEX))))
(instance U1 (viewRef net (cellRef BUF (libraryRef VIRTEX))))
(net N0 (joined (portRef CLR (instanceRef U3)) (portRef O (instanceRef U2))))
(net N1 (joined (portRef CE (instanceRef U3)) (portRef O (instanceRef U1))))
(net N2 (joined (portRef I (instanceRef U2)) (portRef reset)))
(net N3 (joined (portRef Q (instanceRef U3)) (portRef q)))
(net N4 (joined (portRef D (instanceRef U3)) (portRef data)))
(net N5 (joined (portRef C (instanceRef U3)) (portRef clock)))
(net N6 (joined (portRef I (instanceRef U1)) (portRef cke)))
          )
        )
      )
    )
    (design dff_cke
      (cellRef dff_cke (libraryRef DESIGN))
    )
)