1 package edu.berkeley.fleet.fpga.verilog;
2 import edu.berkeley.fleet.api.*;
3 import edu.berkeley.fleet.two.*;
4 import edu.berkeley.fleet.util.*;
5 import edu.berkeley.fleet.*;
6 import java.lang.reflect.*;
9 import static edu.berkeley.fleet.two.FleetTwoFleet.*;
13 - ideally: want to merge Fpga.dump() with this... but have to resolve
14 the handling of flushing first.
16 - eliminate uses of SimpleXXX
17 - force width parameter in remaining uses
18 - re-enable width checking (add zero-extend and sign-extend)
20 - ideally: make getVerilog() package-private somehow
22 - change Event constructors from Object[] to Event[]/Action[]
23 - change portorder to LinkedHashMap
25 => mangle the names given for strings
26 => ensure uniquification of percolated ports
32 * Among the benefits are:
33 * - automatic scan-chain insertion
34 * - better error-checking (for example, width mismatches) than Verilog provides
37 * One of the most annoying things about Verilog is that you cannot
38 * "double-slice" a value; in other words, foo[10:2] is valid
39 * Verilog, but foo[10:2][4:3] is not; the programmer must write
40 * foo[4+2:3+2]. This lack of compositionality is the reason for
41 * most of the complexity in the Value class.
43 public class Verilog {
45 public static interface Value {
46 public String getVerilog();
47 public Value getBits(int high, int low);
48 public Value getBits(Mask mask);
49 public Trigger testMask(Mask mask);
50 public Value invertBits();
51 public int getWidth();
54 public static class SimpleValue implements Value {
55 public final String s;
56 private final String s0;
57 private final int high;
58 private final int low;
59 private final int width;
60 public SimpleValue(String s) { this(s, -1); }
61 public SimpleValue(String s, int width) {
68 public SimpleValue(String s, int high, int low) {
69 this.s = s+"["+high+":"+low+"]";
73 this.width = 1+high-low;
75 public Value getBits(Mask mask) { return getBits(mask.valmaskmax, mask.valmaskmin); }
76 public Trigger testMask(Mask mask) { return new SimpleTrigger(mask.verilog(getVerilog())); }
77 public Value getBits(int high, int low) {
78 if (this.high==-1 && this.low==-1) return new SimpleValue(s, high, low);
79 if (high+this.low > this.high) throw new RuntimeException("out of range");
80 return new SimpleValue(s0, high+this.low, low+this.low);
82 public String getVerilog() { return s; }
83 public Value invertBits() { return new SimpleValue("~("+getVerilog()+")",width); }
84 public int getWidth() {
85 if (width==-1) throw new RuntimeException("not implemented");
90 public static class MuxValue implements Value {
91 private final Trigger sel;
92 private final Value if0;
93 private final Value if1;
94 public MuxValue(Trigger sel, Value if1, Value if0) {
98 if (if0.getWidth() != if1.getWidth())
99 throw new RuntimeException("width mismatch; "+if0+"="+if0.getWidth()+", "+if1+"="+if1.getWidth());
101 public int getWidth() { return if0.getWidth(); }
102 public String getVerilog() { return "("+sel.getVerilogTrigger()+" ? "+if1.getVerilog()+" : "+if0.getVerilog()+")"; }
103 public Value getBits(int high, int low) { return new MuxValue(sel, if1.getBits(high,low), if0.getBits(high,low)); }
104 public Value getBits(Mask mask) { return new MuxValue(sel, if1.getBits(mask), if0.getBits(mask)); }
105 public Value invertBits() { return new MuxValue(sel, if1.invertBits(), if0.invertBits()); }
106 public Trigger testMask(Mask mask) { return new SimpleTrigger(mask.verilog(getVerilog())); }
109 public static class ConstantValue implements Value {
110 private final BitVector bits;
111 public ConstantValue(BitVector bits) { this.bits = bits; }
112 public Value getBits(int high, int low) { return new ConstantValue(bits.get(high, low)); }
113 public Value getBits(Mask mask) { throw new RuntimeException("FIXME"); }
114 public Value invertBits() {
115 BitVector ret = new BitVector(bits.length());
116 for(int i=0; i<bits.length(); i++) ret.set(i, !bits.get(i));
117 return new ConstantValue(ret);
119 public String getVerilog() {
120 StringBuffer sb = new StringBuffer();
121 sb.append(bits.length());
123 for(int i=bits.length()-1; i>=0; i--)
124 sb.append(bits.get(i) ? '1' : '0');
125 return sb.toString();
127 public Trigger testMask(Mask mask) { return new SimpleTrigger(mask.verilog(getVerilog())); }
128 public int getWidth() { return bits.length(); }
131 public static class CatValue implements Value {
132 private final Value[] values;
133 public CatValue(Value[] values) { this.values = values; }
134 public Value getBits(Mask mask) { return getBits(mask.valmaskmax, mask.valmaskmin); }
135 public Value getBits(int high, int low) { throw new RuntimeException(); }
136 public int getWidth() {
138 for (Value val : values) ret += val.getWidth();
141 public String getVerilog() {
142 StringBuffer sb = new StringBuffer();
144 boolean first = true;
145 for(int i=0; i<values.length; i++) {
146 if (values[i]==null) continue;
147 if (!first) sb.append(", ");
148 sb.append(values[i].getVerilog());
152 return sb.toString();
154 public Value invertBits() {
155 Value[] newvals = new Value[values.length];
156 for(int i=0; i<values.length; i++)
157 newvals[i] = values[i].invertBits();
158 return new CatValue(newvals);
160 public Trigger testMask(Mask mask) { return new SimpleTrigger(mask.verilog(getVerilog())); }
163 public static class LogicValue implements Value {
164 public static enum LogicType { OR, AND };
165 private final Value v1;
166 private final Value v2;
167 private final LogicType tt;
168 public LogicValue(Value v1, LogicType tt, Value v2) {
172 // FIXME: check width match
174 public String getVerilog() {
176 case OR: return "("+v1.getVerilog()+"||"+v2.getVerilog()+")";
177 case AND: return "("+v1.getVerilog()+"&&"+v2.getVerilog()+")";
179 throw new RuntimeException("impossible");
181 public Value getBits(int high, int low) { return new LogicValue(v1.getBits(high,low),tt,v2.getBits(high,low)); }
182 public Value getBits(Mask mask) { return new LogicValue(v1.getBits(mask),tt,v2.getBits(mask)); }
183 public Trigger testMask(Mask mask) { throw new RuntimeException("FIXME"); }
184 public Value invertBits() {
186 case OR: return new LogicValue(v1.invertBits(), LogicType.AND, v2.invertBits());
187 case AND: return new LogicValue(v1.invertBits(), LogicType.OR, v2.invertBits());
189 throw new RuntimeException("impossible");
191 public int getWidth() { return v1.getWidth(); }
194 public static class TestValue implements Value, Trigger {
195 public static enum TestType { NE, EQ, LT, GT, LE, GE };
196 private final Value v1;
197 private final Value v2;
198 private final TestType tt;
199 public TestValue(Value v1, TestType tt, Value v2) {
203 // FIXME: check width match
205 public String getVerilogTrigger() { return getVerilog(); }
206 public String getVerilog() {
208 case NE: return "("+v1.getVerilog()+"!="+v2.getVerilog()+")";
209 case EQ: return "("+v1.getVerilog()+"=="+v2.getVerilog()+")";
210 case LE: return "("+v1.getVerilog()+"<="+v2.getVerilog()+")";
211 case GE: return "("+v1.getVerilog()+">="+v2.getVerilog()+")";
212 case LT: return "("+v1.getVerilog()+"<" +v2.getVerilog()+")";
213 case GT: return "("+v1.getVerilog()+">" +v2.getVerilog()+")";
215 throw new RuntimeException("impossible");
217 public Value getBits(int high, int low) { throw new RuntimeException("you probably didn't mean to do this"); }
218 public Value getBits(Mask mask) { throw new RuntimeException("you probably didn't mean to do this"); }
219 public Trigger testMask(Mask mask) { throw new RuntimeException("you probably didn't mean to do this"); }
220 public Trigger invert() { return invertMe(); }
221 public Value invertBits() { return invertMe(); }
222 private TestValue invertMe() {
224 case NE: return new TestValue(v1, TestType.EQ, v2);
225 case EQ: return new TestValue(v1, TestType.NE, v2);
226 case LE: return new TestValue(v1, TestType.GT, v2);
227 case GE: return new TestValue(v1, TestType.LT, v2);
228 case LT: return new TestValue(v1, TestType.GE, v2);
229 case GT: return new TestValue(v1, TestType.LE, v2);
231 throw new RuntimeException("impossible");
233 public int getWidth() { return 1; }
236 // Triggers //////////////////////////////////////////////////////////////////////////////
238 public static interface Trigger {
239 public String getVerilogTrigger();
240 public Trigger invert();
243 public static class SimpleTrigger implements Trigger {
244 private final String s;
245 public SimpleTrigger(String s) { this.s = s; }
246 public String getVerilogTrigger() { return s; }
247 public Trigger invert() { return new SimpleTrigger("!("+s+")"); }
250 public static class AndTrigger implements Trigger {
251 private final Trigger t1, t2;
252 public AndTrigger(Trigger t1, Trigger t2) { this.t1 = t1; this.t2 = t2; }
253 public String getVerilogTrigger() { return "("+t1.getVerilogTrigger()+" && "+t2.getVerilogTrigger()+")"; }
254 public Trigger invert() { return new InvertedTrigger(this); }
257 public static class OrTrigger implements Trigger {
258 private final Trigger t1, t2;
259 public OrTrigger(Trigger t1, Trigger t2) { this.t1 = t1; this.t2 = t2; }
260 public String getVerilogTrigger() { return "("+t1.getVerilogTrigger()+" || "+t2.getVerilogTrigger()+")"; }
261 public Trigger invert() { return new InvertedTrigger(this); }
264 public static class InvertedTrigger implements Trigger {
265 private final Trigger original;
266 public InvertedTrigger(Trigger original) { this.original = original; }
267 public String getVerilogTrigger() { return "!("+original.getVerilogTrigger()+")"; }
268 public Trigger invert() { return original; }
271 public static class ConditionalTrigger implements Trigger {
272 public Trigger condition;
273 public Trigger trigger;
274 public ConditionalTrigger(Trigger condition, Trigger trigger) {
275 this.condition = condition;
276 this.trigger = trigger;
278 public String getVerilogTrigger() {
279 return "(("+condition.getVerilogTrigger()+") ? (" + trigger.getVerilogTrigger() + ") : 1)";
281 public Trigger invert() { return new InvertedTrigger(this); }
284 // Actions //////////////////////////////////////////////////////////////////////////////
286 public static interface Action {
287 public String getVerilogAction();
290 public static class ConditionalAction implements Action {
291 public Trigger condition;
292 public Action action;
293 public ConditionalAction(Trigger condition, Action action) {
294 this.condition = condition;
295 this.action = action;
297 public String getVerilogAction() { return "if ("+condition.getVerilogTrigger()+") begin "+action.getVerilogAction()+" end"; }
300 public static class AssignAction implements Action {
301 public Assignable left;
303 public AssignAction(Assignable left, Value right) {
307 public String getVerilogAction() { return left.getVerilog() + "<=" + right.getVerilog() + ";"; }
310 // Assignables //////////////////////////////////////////////////////////////////////////////
312 public static interface Assignable {
313 public String getVerilog();
316 public static class SimpleAssignable implements Assignable {
317 public final String s;
318 public SimpleAssignable(String s) { this.s = s; }
319 public String getVerilog() { return s; }
322 // Percolated Ports //////////////////////////////////////////////////////////////////////////////
325 * A PercolatedPort is a connection to a top-level pin; it is
326 * propagated up or down the hierarchy
328 public static class PercolatedPort {
329 public static enum PortType { UP, DOWN, INOUT };
330 public final String name;
331 public final int width;
332 public final PortType type;
333 public PercolatedPort(String name, int width, PortType type) {
341 // Module Internals //////////////////////////////////////////////////////////////////////////////
343 public static class Module {
344 public void dump(String prefix) throws IOException {
345 PrintWriter pw = new PrintWriter(new OutputStreamWriter(new FileOutputStream(prefix+"/"+name+".v")));
348 for(InstantiatedModule m : instantiatedModules)
349 m.module.dump(prefix);
352 public final String name;
353 public String getName() { return name; }
354 public Port getPort(String name) { return ports.get(name); }
356 // order matters here
357 public LinkedList<InstantiatedModule> instantiatedModules = new LinkedList<InstantiatedModule>();
359 // order matters here
360 public LinkedList<PercolatedPort> percolatedPorts = new LinkedList<PercolatedPort>();
361 public final ArrayList<Event> events = new ArrayList<Event>();
363 // FIXME: always-alphabetical convention?
364 public final HashMap<String,Port> ports = new HashMap<String,Port>();
365 public final ArrayList<String> portorder = new ArrayList<String>();
366 public final HashMap<String,StateWire> statewires = new HashMap<String,StateWire>();
367 public final HashMap<String,Latch> latches = new HashMap<String,Latch>();
368 public final HashMap<String,WireValue> wires = new HashMap<String,WireValue>();
370 public Module(String name) { this.name = name; }
372 public SourcePort createInputPort(String name, int width) { return new SourcePort(name, width, true); }
373 public SinkPort createOutputPort(String name, int width) { return new SinkPort(name, width, true); }
375 // Latches and Wires //////////////////////////////////////////////////////////////////////////////
377 public class StateWire {
378 public final String name;
379 public final boolean initiallyFull;
380 public String getName() { return name; }
381 public Trigger isFull() { return new SimpleTrigger("("+name+"==1)"); }
382 public Trigger isEmpty() { return new SimpleTrigger("("+name+"==0)"); }
383 public Action doFill() { return new AssignAction(new SimpleAssignable(name), new ConstantValue(new BitVector(1).set(1))); }
384 public Action doDrain() { return new AssignAction(new SimpleAssignable(name), new ConstantValue(new BitVector(1).set(0))); }
385 public String getResetCode() { return name+"<="+(initiallyFull?"1":"0")+";"; }
386 public StateWire(String name) { this(name, false); }
387 public StateWire(String name, boolean initiallyFull) {
389 this.initiallyFull = initiallyFull;
390 statewires.put(name, this);
392 public void dump(PrintWriter pw) {
393 pw.println(" reg "+name+";");
394 pw.println(" initial "+name+"="+(initiallyFull?"1":"0")+";");
398 public class Latch implements Assignable, Value {
399 public final String name;
400 public final int width;
401 public final long initial;
402 public Latch(String name, int width) { this(name, width, 0); }
403 public Latch(String name, int width, long initial) {
406 this.initial = initial;
407 latches.put(name, this);
409 public int getWidth() { return width; }
410 public String getVerilog() { return name; }
411 public Value getBits(int high, int low) { return new SimpleValue(getVerilog(), high, low); }
412 public Value getBits(Mask mask) { return getBits(mask.valmaskmax, mask.valmaskmin); }
413 public Value invertBits() { return new SimpleValue("~("+getVerilog()+")",getWidth()); }
414 public String getResetCode() { return name+"<="+initial+";"; }
415 public void dump(PrintWriter pw) {
416 pw.println(" reg ["+(width-1)+":0] "+name+";");
417 pw.println(" initial "+name+"="+initial+";");
419 public Trigger testMask(Mask mask) { return new SimpleTrigger(mask.verilog(getVerilog())); }
422 public class WireValue implements Value {
423 public final String name;
424 public final int width;
425 public final Value assign;
426 public WireValue(String name, int width, Value assign) {
429 this.assign = assign;
430 wires.put(name, this);
432 public int getWidth() { return width; }
433 public String getVerilog() { return name; }
434 public Value getBits(int high, int low) { return new SimpleValue(getVerilog(), high, low); }
435 public Value getBits(Mask mask) { return getBits(mask.valmaskmax, mask.valmaskmin); }
436 public Value invertBits() { return new SimpleValue("~("+getVerilog()+")",getWidth()); }
437 public Trigger testMask(Mask mask) { return new SimpleTrigger(mask.verilog(getVerilog())); }
438 public void dump(PrintWriter pw) { pw.println(" wire ["+(width-1)+":0] "+name+";"); }
439 public String getAssignments() { return " assign "+name+" = "+assign.getVerilog()+";"; }
442 // Ports //////////////////////////////////////////////////////////////////////////////
444 public abstract class Port implements Action, Trigger {
447 final boolean external;
448 public Port(String name, int width, boolean external) {
451 this.external = external;
452 if (ports.get(name)!=null)
453 throw new RuntimeException("port "+name+" already exists");
454 ports.put(name, this);
458 public String getName() { return name; }
459 public int getWidth() { return width; }
460 public String getVerilog() { return name; }
461 String getAck() { return name+"_a"; }
462 String getReq() { return name+"_r"; }
463 public String isFull() { return "("+getReq()+" && !"+getAck()+")"; }
464 public abstract String getResetCode();
465 public abstract String getInterface();
466 public abstract String getSimpleInterface();
467 public abstract String getDeclaration();
468 public abstract String getAssignments();
469 public abstract String getCleanup();
470 public Trigger invert() { return new InvertedTrigger(this); }
471 public Trigger testMask(Mask mask) { return new SimpleTrigger(mask.verilog(getVerilog())); }
474 public class SourcePort extends Port implements Value {
475 private SinkPort driven = null;
476 public SourcePort(String name, int width, boolean external) { super(name, width, external); }
477 public Value getBits(int high, int low) { return new SimpleValue(getVerilog(), high, low); }
478 public Value getBits(Mask mask) { return getBits(mask.valmaskmax, mask.valmaskmin); }
479 public Value invertBits() { return new SimpleValue("~("+getVerilog()+")",getWidth()); }
480 public String getVerilogTrigger() { return getReq() + " && !"+getAck(); }
481 public String getVerilogAction() { return getAck() + " <= 1;"; }
482 public String getInterface() { return getReq()+", "+getAck()+"_, "+name+""; }
483 public String getSimpleInterface() { return getReq()+", "+getAck()+", "+name+""; }
484 public String testBit(int index, boolean value) { return "("+name+"["+index+"]=="+(value?1:0)+")"; }
485 public String getDeclaration() {
486 StringBuffer sb = new StringBuffer();
488 sb.append("input " + name +"_r;\n");
489 sb.append("output " + name +"_a_;\n");
490 sb.append("input ["+Math.max(0,width-1)+":0]" + name +";\n");
492 sb.append("wire " + name +"_r;\n");
493 sb.append("wire ["+Math.max(0,width-1)+":0]" + name +";\n");
496 sb.append("wire " + name +"_a;\n");
498 sb.append("reg " + name +"_a;\n");
499 sb.append("initial " + name +"_a = 0;\n");
501 return sb.toString();
503 public String getCleanup() { return driven==null ? "if (!"+getReq()+" && "+getAck()+") "+getAck()+"<=0;" : ""; }
504 public String getResetCode() { return driven==null ? name+"_a<=1;" : ""; }
505 public String getAssignments() {
506 StringBuffer sb = new StringBuffer();
508 sb.append("assign " + name +"_a_ = " + name + "_a;\n");
509 return sb.toString();
511 public void connect(SinkPort driven) {
512 if (driven.controlDriver!=null) throw new RuntimeException("driven net already has a driver");
513 if (driven.latchDriver!=null) throw new RuntimeException("driven net already has a driver");
514 if (this.driven!=null) throw new RuntimeException("driver already has a driven net");
515 this.driven = driven;
516 driven.controlDriver = this;
517 driven.latchDriver = this;
519 // if (getWidth() != driven.getWidth())
520 // throw new RuntimeException("width mismatch: " + getWidth() + " " + driven.getWidth());
524 public class SinkPort extends Port implements Assignable {
525 SourcePort controlDriver = null;
526 Value latchDriver = null;
527 public SinkPort(String name, int width, boolean external) { super(name, width, external); }
528 public String getVerilogAction() { return getReq() + " <= 1;"; }
529 public String getVerilogTrigger() { return "!" + getReq() + " && !"+getAck(); }
530 public String getInterface() { return name+"_r_, "+name+"_a, "+name+"_"; }
531 public String getSimpleInterface() { return name+"_r, "+name+"_a, "+name; }
532 public String getCleanup() { return controlDriver==null ? "if ("+getReq()+" && "+getAck()+") begin "+getReq()+"<=0; end" : ""; }
533 public Assignable getBits(Mask mask) { return new SimpleAssignable(name+"["+mask.valmaskmax+":"+mask.valmaskmin+"]"); }
534 public String getResetCode() { return controlDriver!=null ? "" : name+"_r<=0;"; }
535 public void connectControl(SourcePort controlDriver) {
536 if (this.controlDriver != null) throw new RuntimeException("attempt to connect control twice");
537 this.controlDriver = controlDriver;
539 public void connectValue(Value val) {
540 //if (latchDriver!=null) throw new RuntimeException("attempt to re-assign via connectValue()");
541 this.latchDriver = val;
543 //if (getWidth() != val.getWidth())
544 //throw new RuntimeException("width mismatch: " + getWidth() + " " + val.getWidth());
546 public String getDeclaration() {
547 StringBuffer sb = new StringBuffer();
549 sb.append("output " + name +"_r_;\n");
550 sb.append("input " + name +"_a;\n");
551 sb.append("output ["+Math.max(0,width-1)+":0]" + name +"_;\n");
553 sb.append("wire " + name +"_a;\n");
555 if (controlDriver!=null) {
556 sb.append("wire " + name +"_r;\n");
557 sb.append("wire ["+Math.max(0,width-1)+":0]" + name +";\n");
559 sb.append("reg " + name +"_r;\n");
560 sb.append("initial " + name +"_r = 0;\n");
561 if (latchDriver!=null) sb.append("wire ["+Math.max(0,width-1)+":0]" + name +";\n");
562 else sb.append("reg ["+Math.max(0,width-1)+":0]" + name +";\n");
564 return sb.toString();
566 public String getAssignments() {
567 StringBuffer sb = new StringBuffer();
569 sb.append("assign " + name +"_r_ = " + name + "_r;\n");
570 sb.append("assign " + name +"_ = " + name + ";\n");
572 if (controlDriver != null) {
573 sb.append("assign " + name +"_r = " + controlDriver.name + "_r;\n");
574 sb.append("assign " + controlDriver.name +"_a = " + name + "_a;\n");
575 if (latchDriver==null)
576 sb.append("assign " + name +" = " + controlDriver.name + ";\n");
578 if (latchDriver != null)
579 sb.append("assign " + name +" = " + latchDriver.getVerilog() + ";\n");
580 return sb.toString();
584 // InstantiatedModule //////////////////////////////////////////////////////////////////////////////
586 public static class InstantiatedModule {
587 public final Module module;
588 public final Module thisModule;
590 public final HashMap<String,Port> ports = new HashMap<String,Port>();
591 public String getName() { return module.getName()+"_"+id; }
592 public InstantiatedModule(Module thisModule, Module module) {
593 this.thisModule = thisModule;
594 this.module = module;
595 this.id = thisModule.id++;
596 thisModule.instantiatedModules.add(this);
597 for(String s : module.portorder)
600 public void dump(PrintWriter pw) {
601 pw.println(" " + module.getName() + " " + getName() + "(clk, rst ");
602 for(String s : module.portorder)
603 pw.println(", " + getPort(s).getSimpleInterface());
604 for(PercolatedPort pp : module.percolatedPorts)
605 pw.println(" , "+pp.name);
608 public Port getPort(String name) {
609 return (module.ports.get(name) instanceof SinkPort) ? getOutputPort(name) : getInputPort(name);
611 public SinkPort getInputPort(String name) {
612 int width = module.getPort(name).getWidth();
613 SinkPort port = (SinkPort)ports.get(name);
615 port = thisModule.new SinkPort(getName()+"_"+name, width, false);
616 ports.put(name, port);
620 public SourcePort getOutputPort(String name) {
621 int width = module.getPort(name).getWidth();
622 SourcePort port = (SourcePort)ports.get(name);
624 port = thisModule.new SourcePort(getName()+"_"+name, width, false);
625 ports.put(name, port);
631 public void dump(PrintWriter pw, boolean fix) {
632 if (!fix) throw new RuntimeException();
633 boolean isRoot = name.equals("main");
634 pw.print("module "+name);
635 pw.println(isRoot ? "(clk_pin, rst_pin " : "(clk, rst ");
636 for(String name : portorder) pw.println(" , " + ports.get(name).getInterface());
637 for (InstantiatedModule im : this.instantiatedModules)
638 for(PercolatedPort pp : im.module.percolatedPorts)
639 if (!isRoot || (!pp.name.startsWith("root_in_") && !pp.name.startsWith("rst_")))
640 pw.println(" , "+pp.name);
645 pw.println(" input clk_pin;");
646 pw.println(" input rst_pin;");
647 pw.println(" wire clk;");
648 pw.println(" wire clk_fb;");
649 pw.println(" wire clk_unbuffered;");
650 pw.println(" assign clk_unbuffered = clk_pin;");
651 //pw.println(" assign clk = clk_pin;");
653 pw.println(" BUFG GBUF_FOR_MUX_CLOCK (.I(clk_unbuffered), .O(clk));");
657 pw.println(" .CLKFX_MULTIPLY(4),");
658 pw.println(" .CLKFX_DIVIDE(8),");
659 pw.println(" .CLKIN_PERIOD(\"10 ns\")");
660 pw.println(" ) mydcm(");
661 pw.println(" .CLKIN (clk_pin),");
662 pw.println(" .CLKFB(clk_fb),");
663 pw.println(" .CLKFX (clk_unbuffered),");
664 pw.println(" .CLK0 (clk_fb)");
667 pw.println(" wire rst;");
669 pw.println(" input clk;");
670 pw.println(" input rst;");
673 for (InstantiatedModule im : this.instantiatedModules)
674 for(PercolatedPort pp : im.module.percolatedPorts) {
675 if (isRoot && (pp.name.startsWith("root_in_") || pp.name.startsWith("rst_")))
677 else switch(pp.type) {
678 case UP: pw.print("output"); break;
679 case DOWN: pw.print("input"); break;
680 case INOUT: pw.print("inout"); break;
684 pw.print("["+(pp.width-1)+":0]");
691 pw.println(" assign rst = rst_out;");
692 pw.println(" assign rst_in = !rst_pin;");
695 for(String name : ports.keySet()) pw.println(" " + ports.get(name).getDeclaration());
696 for(StateWire sw : statewires.values()) sw.dump(pw);
697 for(Latch l : latches.values()) l.dump(pw);
698 for(WireValue wv : wires.values()) wv.dump(pw);
699 for(String name : ports.keySet()) pw.println(" " + ports.get(name).getAssignments());
700 for(WireValue wv : wires.values()) pw.println(" " + wv.getAssignments());
701 for(InstantiatedModule m : instantiatedModules) m.dump(pw);
702 pw.println("always @(posedge clk) begin");
703 pw.println(" if (rst) begin");
704 for(Latch l : latches.values()) pw.println(l.getResetCode());
705 for(StateWire sw : statewires.values()) pw.println(sw.getResetCode());
706 for(Port p : ports.values()) pw.println(p.getResetCode());
707 pw.println(" end else begin");
708 for(Port p : ports.values()) pw.println(p.getCleanup());
709 for(Event a : events) a.dump(pw, fix);
710 pw.println(" begin end");
713 pw.println("endmodule");
717 public Object[] triggers;
718 public Object[] actions;
719 public Event(Object[] triggers, Object action) { this(triggers, new Object[] { action }); }
720 public Event(Object[] triggers, Object[] actions) {
721 Module.this.events.add(this);
722 this.triggers = triggers;
723 this.actions = actions;
725 public void dump(PrintWriter pw, boolean fix) {
726 if (!fix) throw new RuntimeException();
728 for(Object o : triggers) {
729 if (o instanceof Trigger) pw.print(" && " + ((Trigger)o).getVerilogTrigger());
730 else pw.print(" && " + o);
732 pw.println(") begin ");
733 for(Object a : actions) if (a!=null) pw.println(((Action)a).getVerilogAction());
734 if (fix) pw.println("end /*else*/ ");
735 else pw.println("end else ");