When describing circuits to computers, have you ever felt that the languages for EDA, be it SPICE or Verilog or whatever are not flexible enough ? Well, I have. Coding regular structures such as adders, ring oscillators, multipliers etc. with popular languages in EDA can be a pain. A couple of weeks ago, I was checking out a synthesized ring oscillator to build a time-to-digital converter (TDC) [1]. Building long chains of inverters by hand is drudgery and SPICE does precious little to help in automation. At first, I tried writing a python program with string manipulations that generates verilog code, but quickly came to realize that its way more natural to have snippets of python inside verilog. Now, that needs a bit of work to get going. Thankfully, web developers solved this problem long ago for programmatically generating HTML. I used web.py 's templating engine to write verilog code that describes a ring oscillator (in case you are surprised by the fact that I used verilog rather than SPICE, the whole idea is to create the TDC with standard cells).
The following snippet causes web.py to create a HTML page of verilog code that describes a loaded ring oscillator. The loading and the number of inverters can be easily changed by setting variables M and N below.
<body>
module ringosc(clk); </br></br>
output clk; </br>
</br>
<div id="body">
$# first add the AND gates
$for i in range(M+1):
ND2CHD U$us (.I1(en),.I2(n$ns),.O(n$(ns+1))); </br>
$ us += 1
$ ns += 1
</br>
$# now complete the ring with buffers
$for i in range(N-1):
$ no = ns + 1
$if no==N:
$ no = 0
INVTCHD U$us (.I(n$ns), .E(high), .O(n$no) ); </br>
$ us += 1
$for j in range(M):
INVTCHD U$us (.I(n$ns), .E(control[$cb]), .O(n$no) ); </br>
$ us += 1
$ cb += 1
$ ns += 1
$# now put clock buffers before sending it out.
</br>
INVCKDHD UCK1( .I(n1), .O(nc1) ); </br>
INVCKJHD UCK2( .I(nc1), .O(nc2) ); </br>
INVCKQHD UCK3( .I(nc2), .O(clk) ); </br>
</br>
TIE0DHD Ulo( .O(low) ); </br>
TIE1DHD Uhigh( .O(high) ); </br>
</br></br></br>
</div>
<div id="declare">
wire
$for i in range(N-1):
n$i,
n$(N-1),en,nc1,nc2,high,low;
</br></br>
</div>
endmodule
</body>
The resulting HTML page is
module ringosc(clk);
output clk;
Now, it takes hardly a second to jump from a 5 tap ring oscillator described above to a 105 tap ring oscillator.
References
1. Youngmin Park and David D. Wentzloff, A cyclic vernier time-to-digital converter synthesized from a 65nm CMOS standard library.
The following snippet causes web.py to create a HTML page of verilog code that describes a loaded ring oscillator. The loading and the number of inverters can be easily changed by setting variables M and N below.
<body>
module ringosc(clk); </br></br>
output clk; </br>
</br>
<div id="body">
$# first add the AND gates
$for i in range(M+1):
ND2CHD U$us (.I1(en),.I2(n$ns),.O(n$(ns+1))); </br>
$ us += 1
$ ns += 1
</br>
$# now complete the ring with buffers
$for i in range(N-1):
$ no = ns + 1
$if no==N:
$ no = 0
INVTCHD U$us (.I(n$ns), .E(high), .O(n$no) ); </br>
$ us += 1
$for j in range(M):
INVTCHD U$us (.I(n$ns), .E(control[$cb]), .O(n$no) ); </br>
$ us += 1
$ cb += 1
$ ns += 1
$# now put clock buffers before sending it out.
</br>
INVCKDHD UCK1( .I(n1), .O(nc1) ); </br>
INVCKJHD UCK2( .I(nc1), .O(nc2) ); </br>
INVCKQHD UCK3( .I(nc2), .O(clk) ); </br>
</br>
TIE0DHD Ulo( .O(low) ); </br>
TIE1DHD Uhigh( .O(high) ); </br>
</br></br></br>
</div>
<div id="declare">
wire
$for i in range(N-1):
n$i,
n$(N-1),en,nc1,nc2,high,low;
</br></br>
</div>
endmodule
</body>
The resulting HTML page is
module ringosc(clk);
output clk;
wire
n0,
n1,
n2,
n3,
n4,en,nc1,nc2,high,low;
ND2CHD U0 (.I1(en),.I2(n0),.O(n1));
ND2CHD U1 (.I1(en),.I2(n0),.O(n1));
ND2CHD U2 (.I1(en),.I2(n0),.O(n1));
ND2CHD U3 (.I1(en),.I2(n0),.O(n1));
ND2CHD U4 (.I1(en),.I2(n0),.O(n1));
ND2CHD U5 (.I1(en),.I2(n0),.O(n1));
ND2CHD U6 (.I1(en),.I2(n0),.O(n1));
ND2CHD U7 (.I1(en),.I2(n0),.O(n1));
ND2CHD U8 (.I1(en),.I2(n0),.O(n1));
INVTCHD U9 (.I(n1), .E(high), .O(n2) );
INVTCHD U10 (.I(n1), .E(control[0]), .O(n2) );
INVTCHD U11 (.I(n1), .E(control[1]), .O(n2) );
INVTCHD U12 (.I(n1), .E(control[2]), .O(n2) );
INVTCHD U13 (.I(n1), .E(control[3]), .O(n2) );
INVTCHD U14 (.I(n1), .E(control[4]), .O(n2) );
INVTCHD U15 (.I(n1), .E(control[5]), .O(n2) );
INVTCHD U16 (.I(n1), .E(control[6]), .O(n2) );
INVTCHD U17 (.I(n1), .E(control[7]), .O(n2) );
INVTCHD U18 (.I(n2), .E(high), .O(n3) );
INVTCHD U19 (.I(n2), .E(control[8]), .O(n3) );
INVTCHD U20 (.I(n2), .E(control[9]), .O(n3) );
INVTCHD U21 (.I(n2), .E(control[10]), .O(n3) );
INVTCHD U22 (.I(n2), .E(control[11]), .O(n3) );
INVTCHD U23 (.I(n2), .E(control[12]), .O(n3) );
INVTCHD U24 (.I(n2), .E(control[13]), .O(n3) );
INVTCHD U25 (.I(n2), .E(control[14]), .O(n3) );
INVTCHD U26 (.I(n2), .E(control[15]), .O(n3) );
INVTCHD U27 (.I(n3), .E(high), .O(n4) );
INVTCHD U28 (.I(n3), .E(control[16]), .O(n4) );
INVTCHD U29 (.I(n3), .E(control[17]), .O(n4) );
INVTCHD U30 (.I(n3), .E(control[18]), .O(n4) );
INVTCHD U31 (.I(n3), .E(control[19]), .O(n4) );
INVTCHD U32 (.I(n3), .E(control[20]), .O(n4) );
INVTCHD U33 (.I(n3), .E(control[21]), .O(n4) );
INVTCHD U34 (.I(n3), .E(control[22]), .O(n4) );
INVTCHD U35 (.I(n3), .E(control[23]), .O(n4) );
INVTCHD U36 (.I(n4), .E(high), .O(n0) );
INVTCHD U37 (.I(n4), .E(control[24]), .O(n0) );
INVTCHD U38 (.I(n4), .E(control[25]), .O(n0) );
INVTCHD U39 (.I(n4), .E(control[26]), .O(n0) );
INVTCHD U40 (.I(n4), .E(control[27]), .O(n0) );
INVTCHD U41 (.I(n4), .E(control[28]), .O(n0) );
INVTCHD U42 (.I(n4), .E(control[29]), .O(n0) );
INVTCHD U43 (.I(n4), .E(control[30]), .O(n0) );
INVTCHD U44 (.I(n4), .E(control[31]), .O(n0) );
INVCKDHD UCK1( .I(n1), .O(nc1) );
INVCKJHD UCK2( .I(nc1), .O(nc2) );
INVCKQHD UCK3( .I(nc2), .O(clk) );
TIE0DHD Ulo( .O(low) );
TIE1DHD Uhigh( .O(high) );
endmodule
ND2CHD U1 (.I1(en),.I2(n0),.O(n1));
ND2CHD U2 (.I1(en),.I2(n0),.O(n1));
ND2CHD U3 (.I1(en),.I2(n0),.O(n1));
ND2CHD U4 (.I1(en),.I2(n0),.O(n1));
ND2CHD U5 (.I1(en),.I2(n0),.O(n1));
ND2CHD U6 (.I1(en),.I2(n0),.O(n1));
ND2CHD U7 (.I1(en),.I2(n0),.O(n1));
ND2CHD U8 (.I1(en),.I2(n0),.O(n1));
INVTCHD U9 (.I(n1), .E(high), .O(n2) );
INVTCHD U10 (.I(n1), .E(control[0]), .O(n2) );
INVTCHD U11 (.I(n1), .E(control[1]), .O(n2) );
INVTCHD U12 (.I(n1), .E(control[2]), .O(n2) );
INVTCHD U13 (.I(n1), .E(control[3]), .O(n2) );
INVTCHD U14 (.I(n1), .E(control[4]), .O(n2) );
INVTCHD U15 (.I(n1), .E(control[5]), .O(n2) );
INVTCHD U16 (.I(n1), .E(control[6]), .O(n2) );
INVTCHD U17 (.I(n1), .E(control[7]), .O(n2) );
INVTCHD U18 (.I(n2), .E(high), .O(n3) );
INVTCHD U19 (.I(n2), .E(control[8]), .O(n3) );
INVTCHD U20 (.I(n2), .E(control[9]), .O(n3) );
INVTCHD U21 (.I(n2), .E(control[10]), .O(n3) );
INVTCHD U22 (.I(n2), .E(control[11]), .O(n3) );
INVTCHD U23 (.I(n2), .E(control[12]), .O(n3) );
INVTCHD U24 (.I(n2), .E(control[13]), .O(n3) );
INVTCHD U25 (.I(n2), .E(control[14]), .O(n3) );
INVTCHD U26 (.I(n2), .E(control[15]), .O(n3) );
INVTCHD U27 (.I(n3), .E(high), .O(n4) );
INVTCHD U28 (.I(n3), .E(control[16]), .O(n4) );
INVTCHD U29 (.I(n3), .E(control[17]), .O(n4) );
INVTCHD U30 (.I(n3), .E(control[18]), .O(n4) );
INVTCHD U31 (.I(n3), .E(control[19]), .O(n4) );
INVTCHD U32 (.I(n3), .E(control[20]), .O(n4) );
INVTCHD U33 (.I(n3), .E(control[21]), .O(n4) );
INVTCHD U34 (.I(n3), .E(control[22]), .O(n4) );
INVTCHD U35 (.I(n3), .E(control[23]), .O(n4) );
INVTCHD U36 (.I(n4), .E(high), .O(n0) );
INVTCHD U37 (.I(n4), .E(control[24]), .O(n0) );
INVTCHD U38 (.I(n4), .E(control[25]), .O(n0) );
INVTCHD U39 (.I(n4), .E(control[26]), .O(n0) );
INVTCHD U40 (.I(n4), .E(control[27]), .O(n0) );
INVTCHD U41 (.I(n4), .E(control[28]), .O(n0) );
INVTCHD U42 (.I(n4), .E(control[29]), .O(n0) );
INVTCHD U43 (.I(n4), .E(control[30]), .O(n0) );
INVTCHD U44 (.I(n4), .E(control[31]), .O(n0) );
INVCKDHD UCK1( .I(n1), .O(nc1) );
INVCKJHD UCK2( .I(nc1), .O(nc2) );
INVCKQHD UCK3( .I(nc2), .O(clk) );
TIE0DHD Ulo( .O(low) );
TIE1DHD Uhigh( .O(high) );
Now, it takes hardly a second to jump from a 5 tap ring oscillator described above to a 105 tap ring oscillator.
References
1. Youngmin Park and David D. Wentzloff, A cyclic vernier time-to-digital converter synthesized from a 65nm CMOS standard library.
No comments:
Post a Comment