Generate XNF RAMS from synthesized memories.
This commit is contained in:
parent
3e2bb85f58
commit
09de918198
18
README.txt
18
README.txt
|
|
@ -273,13 +273,6 @@ current state of support for Verilog.
|
||||||
|
|
||||||
- Min/Typ/Max expressions: Example: a = (1 : 6 : 14);
|
- 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
|
- `timescale directive
|
||||||
|
|
||||||
- force/release/assign/deassign procedural assignments not
|
- 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
|
- 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.
|
- Functions in structural contexts are not supported.
|
||||||
|
|
||||||
assign foo = user_function(a,b); // sorry
|
assign foo = user_function(a,b); // sorry
|
||||||
always @(a or b) foo = user_function(a,b); // OK
|
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
|
assign foo = a * b; // sorry
|
||||||
always @(a or b) foo = a * b; // sorry
|
always @(a or b) foo = a * b; // sorry
|
||||||
|
|
|
||||||
14
netlist.cc
14
netlist.cc
|
|
@ -17,7 +17,7 @@
|
||||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||||
*/
|
*/
|
||||||
#if !defined(WINNT)
|
#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
|
#endif
|
||||||
|
|
||||||
# include <cassert>
|
# include <cassert>
|
||||||
|
|
@ -1093,6 +1093,15 @@ const NetMemory* NetRamDq::mem() const
|
||||||
return mem_;
|
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()
|
void NetRamDq::absorb_partners()
|
||||||
{
|
{
|
||||||
NetRamDq*cur, *tmp;
|
NetRamDq*cur, *tmp;
|
||||||
|
|
@ -2725,6 +2734,9 @@ NetNet* Design::find_signal(bool (*func)(const NetNet*))
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* $Log: netlist.cc,v $
|
* $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
|
* Revision 1.98 1999/12/05 02:24:09 steve
|
||||||
* Synthesize LPM_RAM_DQ for writes into memories.
|
* Synthesize LPM_RAM_DQ for writes into memories.
|
||||||
*
|
*
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,7 @@
|
||||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||||
*/
|
*/
|
||||||
#if !defined(WINNT)
|
#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
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -569,6 +569,10 @@ class NetRamDq : public NetNode {
|
||||||
// connections.
|
// connections.
|
||||||
void absorb_partners();
|
void absorb_partners();
|
||||||
|
|
||||||
|
// Use this method to count the partners (including myself)
|
||||||
|
// that are ports to the attached memory.
|
||||||
|
unsigned count_partners() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
NetMemory*mem_;
|
NetMemory*mem_;
|
||||||
NetRamDq*next_;
|
NetRamDq*next_;
|
||||||
|
|
@ -2062,6 +2066,9 @@ extern ostream& operator << (ostream&, NetNet::Type);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* $Log: netlist.h,v $
|
* $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
|
* Revision 1.98 1999/12/05 02:24:09 steve
|
||||||
* Synthesize LPM_RAM_DQ for writes into memories.
|
* Synthesize LPM_RAM_DQ for writes into memories.
|
||||||
*
|
*
|
||||||
|
|
|
||||||
39
t-xnf.cc
39
t-xnf.cc
|
|
@ -17,7 +17,7 @@
|
||||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||||
*/
|
*/
|
||||||
#if !defined(WINNT)
|
#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
|
#endif
|
||||||
|
|
||||||
/* XNF BACKEND
|
/* XNF BACKEND
|
||||||
|
|
@ -77,11 +77,13 @@ class target_xnf : public target_t {
|
||||||
public:
|
public:
|
||||||
void start_design(ostream&os, const Design*);
|
void start_design(ostream&os, const Design*);
|
||||||
void end_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 signal(ostream&os, const NetNet*);
|
||||||
|
|
||||||
void lpm_add_sub(ostream&os, const NetAddSub*);
|
void lpm_add_sub(ostream&os, const NetAddSub*);
|
||||||
void lpm_ff(ostream&os, const NetFF*);
|
void lpm_ff(ostream&os, const NetFF*);
|
||||||
void lpm_mux(ostream&os, const NetMux*);
|
void lpm_mux(ostream&os, const NetMux*);
|
||||||
|
void lpm_ram_dq(ostream&os, const NetRamDq*);
|
||||||
|
|
||||||
void net_const(ostream&os, const NetConst*);
|
void net_const(ostream&os, const NetConst*);
|
||||||
void logic(ostream&os, const NetLogic*);
|
void logic(ostream&os, const NetLogic*);
|
||||||
|
|
@ -295,6 +297,14 @@ void scrape_pad_info(string str, char&dir, unsigned&num)
|
||||||
num = val;
|
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
|
* Look for signals that have attributes that are pertinent to XNF
|
||||||
* files. The most obvious are those that have the PAD attribute.
|
* 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)
|
void target_xnf::net_const(ostream&os, const NetConst*c)
|
||||||
{
|
{
|
||||||
verinum::V v=c->value();
|
verinum::V v=c->value();
|
||||||
|
|
@ -653,6 +687,9 @@ extern const struct target tgt_xnf = { "xnf", &target_xnf_obj };
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* $Log: t-xnf.cc,v $
|
* $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
|
* Revision 1.18 1999/11/19 03:02:25 steve
|
||||||
* Detect flip-flops connected to opads and turn
|
* Detect flip-flops connected to opads and turn
|
||||||
* them into OUTFF devices. Inprove support for
|
* them into OUTFF devices. Inprove support for
|
||||||
|
|
|
||||||
48
xnf.txt
48
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
|
connected. It also bypasses the efforts of the compiler, so is not
|
||||||
checked for correctness.
|
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 = <expr>;
|
||||||
|
|
||||||
|
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 (<ce>) Q = <expr>;
|
||||||
|
|
||||||
|
The <ce> 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 (<we>) M[<addr>] = <expr>;
|
||||||
|
|
||||||
|
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[<addr>];
|
||||||
|
|
||||||
|
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
|
There are certain special devices in XNF that Verilog does not
|
||||||
naturally represent, although there are similar more generic Verilog
|
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 $
|
$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
|
Revision 1.9 1999/11/18 03:52:20 steve
|
||||||
Turn NetTmp objects into normal local NetNet objects,
|
Turn NetTmp objects into normal local NetNet objects,
|
||||||
and add the nodangle functor to clean up the local
|
and add the nodangle functor to clean up the local
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue