From 09de918198c9d560c956bb17db110d33eb1ee11b Mon Sep 17 00:00:00 2001 From: steve Date: Sun, 5 Dec 1999 19:30:42 +0000 Subject: [PATCH] Generate XNF RAMS from synthesized memories. --- README.txt | 18 +++--------------- netlist.cc | 14 +++++++++++++- netlist.h | 9 ++++++++- t-xnf.cc | 39 ++++++++++++++++++++++++++++++++++++++- xnf.txt | 48 +++++++++++++++++++++++++++++++++++++++++++++++- 5 files changed, 109 insertions(+), 19 deletions(-) diff --git a/README.txt b/README.txt index 2d288e21f..47c552da9 100644 --- a/README.txt +++ b/README.txt @@ -273,13 +273,6 @@ current state of support for Verilog. - Min/Typ/Max expressions: Example: a = (1 : 6 : 14); - - Memories work, but only in procedural code. - - reg [1:0] b [2:0], bar; - wire [1:0] foo; - always foo = b[i]; // sorry - always @(i) bar = b[i]; // OK - - `timescale directive - force/release/assign/deassign procedural assignments not @@ -295,19 +288,14 @@ current state of support for Verilog. - fork/join is not supported in vvm runtime - - Structural shift operators are in general not supported. - Procedural expressions are OK. Constant expressions are OK. - - assign foo = a << b; // sorry - always @(a or b) foo = a << b; // OK - parameter foo = a << b; // OK - - Functions in structural contexts are not supported. assign foo = user_function(a,b); // sorry always @(a or b) foo = user_function(a,b); // OK - - multiplicative operators (*, /, %) are not supported. + - multiplicative operators (*, /, %) are not supported in + general. They do work if the compiler can evaluate them at compile + time. assign foo = a * b; // sorry always @(a or b) foo = a * b; // sorry diff --git a/netlist.cc b/netlist.cc index 9f14d0555..6d5d4b1b3 100644 --- a/netlist.cc +++ b/netlist.cc @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) -#ident "$Id: netlist.cc,v 1.98 1999/12/05 02:24:09 steve Exp $" +#ident "$Id: netlist.cc,v 1.99 1999/12/05 19:30:43 steve Exp $" #endif # include @@ -1093,6 +1093,15 @@ const NetMemory* NetRamDq::mem() const return mem_; } +unsigned NetRamDq::count_partners() const +{ + unsigned count = 0; + for (NetRamDq*cur = mem_->ram_list_ ; cur ; cur = cur->next_) + count += 1; + + return count; +} + void NetRamDq::absorb_partners() { NetRamDq*cur, *tmp; @@ -2725,6 +2734,9 @@ NetNet* Design::find_signal(bool (*func)(const NetNet*)) /* * $Log: netlist.cc,v $ + * Revision 1.99 1999/12/05 19:30:43 steve + * Generate XNF RAMS from synthesized memories. + * * Revision 1.98 1999/12/05 02:24:09 steve * Synthesize LPM_RAM_DQ for writes into memories. * diff --git a/netlist.h b/netlist.h index 165055238..91117cc20 100644 --- a/netlist.h +++ b/netlist.h @@ -19,7 +19,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) -#ident "$Id: netlist.h,v 1.98 1999/12/05 02:24:09 steve Exp $" +#ident "$Id: netlist.h,v 1.99 1999/12/05 19:30:43 steve Exp $" #endif /* @@ -569,6 +569,10 @@ class NetRamDq : public NetNode { // connections. void absorb_partners(); + // Use this method to count the partners (including myself) + // that are ports to the attached memory. + unsigned count_partners() const; + private: NetMemory*mem_; NetRamDq*next_; @@ -2062,6 +2066,9 @@ extern ostream& operator << (ostream&, NetNet::Type); /* * $Log: netlist.h,v $ + * Revision 1.99 1999/12/05 19:30:43 steve + * Generate XNF RAMS from synthesized memories. + * * Revision 1.98 1999/12/05 02:24:09 steve * Synthesize LPM_RAM_DQ for writes into memories. * diff --git a/t-xnf.cc b/t-xnf.cc index 32c85b3f2..112341587 100644 --- a/t-xnf.cc +++ b/t-xnf.cc @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) -#ident "$Id: t-xnf.cc,v 1.18 1999/11/19 03:02:25 steve Exp $" +#ident "$Id: t-xnf.cc,v 1.19 1999/12/05 19:30:43 steve Exp $" #endif /* XNF BACKEND @@ -77,11 +77,13 @@ class target_xnf : public target_t { public: void start_design(ostream&os, const Design*); void end_design(ostream&os, const Design*); + void memory(ostream&os, const NetMemory*); void signal(ostream&os, const NetNet*); void lpm_add_sub(ostream&os, const NetAddSub*); void lpm_ff(ostream&os, const NetFF*); void lpm_mux(ostream&os, const NetMux*); + void lpm_ram_dq(ostream&os, const NetRamDq*); void net_const(ostream&os, const NetConst*); void logic(ostream&os, const NetLogic*); @@ -295,6 +297,14 @@ void scrape_pad_info(string str, char&dir, unsigned&num) num = val; } +/* + * Memories are handled by the lpm_ram_dq method, so there is nothing + * to do here. + */ +void target_xnf::memory(ostream&, const NetMemory*) +{ +} + /* * Look for signals that have attributes that are pertinent to XNF * files. The most obvious are those that have the PAD attribute. @@ -545,6 +555,30 @@ void target_xnf::lpm_mux(ostream&os, const NetMux*net) } +void target_xnf::lpm_ram_dq(ostream&os, const NetRamDq*ram) +{ + assert(ram->count_partners() == 1); + + const NetMemory*mem = ram->mem(); + + for (unsigned idx = 0 ; idx < ram->width() ; idx += 1) { + os << "SYM, " << mangle(ram->name()) + << "<" << idx << ">, RAMS" << endl; + + draw_pin(os, "O", ram->pin_Q(idx)); + draw_pin(os, "D", ram->pin_Data(idx)); + draw_pin(os, "WE", ram->pin_WE()); + draw_pin(os, "WCLK", ram->pin_InClock()); + for (unsigned adr = 0 ; adr < ram->awidth() ; adr += 1) { + strstream tmp; + tmp << "A" << adr << ends; + draw_pin(os, tmp.str(), ram->pin_Address(adr)); + } + + os << "END" << endl; + } +} + void target_xnf::net_const(ostream&os, const NetConst*c) { verinum::V v=c->value(); @@ -653,6 +687,9 @@ extern const struct target tgt_xnf = { "xnf", &target_xnf_obj }; /* * $Log: t-xnf.cc,v $ + * Revision 1.19 1999/12/05 19:30:43 steve + * Generate XNF RAMS from synthesized memories. + * * Revision 1.18 1999/11/19 03:02:25 steve * Detect flip-flops connected to opads and turn * them into OUTFF devices. Inprove support for diff --git a/xnf.txt b/xnf.txt index 6a7aad325..b8ae5f393 100644 --- a/xnf.txt +++ b/xnf.txt @@ -65,7 +65,50 @@ programmer really knows how the pins of the XNF device are to be connected. It also bypasses the efforts of the compiler, so is not checked for correctness. -XNF SPECIAL DEVICES +XNF STORAGE ELEMENTS + +Storage elements in XNF include flip-flops, latches and CLB +rams. These devices are generated from the LPM equivilents that the +-Fsynth functor synthesizes from behavioral descriptions. + +Flip-flops, or more specifically DFF devices, are generated to +implement behavioral code like this: + + reg Q; + always @(posedge clk) Q = ; + +The edge can be positive or negative, and the expression can be any +synthesizeable expression. Furthermore, the register "Q" can have +width, which will cause the appropriate number of flip-flops to be +created. A clock enable expression can also be added like so: + + reg Q; + always @(posedge clk) if () Q = ; + +The expression can be any synthesizeable expression. + +With or without the CE, the generated DFF devices are written into the +XNF output one bit at a time, with the clock input inverted if necessary. + +Xilinx parts also support CLB circuitry as synchronous RAMS. These +devices are created from Verilog memories if the properties are +right. The behavioral description that the -Fsynth functor matches to +get a synchronous RAM looks very similar to that for a DFF: + + memory [15:0] M; + always @(posedge clk) if () M[] = ; + +Note that in this case the l-value of the assignment is an addressed +memory. This statement models writes into the memory. Reads from the +device can be modeled with ordinary structural code, i.e.: + + assign foo = M[]; + +For the memory to be synthesizeable in the XNF target, the address +lines for writes and reads must be connected. This corresponds to the +limitations of the real hardware. + +OTHER XNF SPECIAL DEVICES There are certain special devices in XNF that Verilog does not naturally represent, although there are similar more generic Verilog @@ -176,6 +219,9 @@ IBUF, NOT gates cannot be absorbed as in the OPAD case. $Log: xnf.txt,v $ + Revision 1.10 1999/12/05 19:30:43 steve + Generate XNF RAMS from synthesized memories. + Revision 1.9 1999/11/18 03:52:20 steve Turn NetTmp objects into normal local NetNet objects, and add the nodangle functor to clean up the local