Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

Simulating a DAC in Cadence

Status
Not open for further replies.

curious_engineer

Junior Member level 2
Junior Member level 2
Joined
Nov 12, 2009
Messages
20
Helped
0
Reputation
0
Reaction score
0
Trophy points
1,281
Activity points
1,455
Hi all,

I am trying to simulate a 12-bit DAC in Cadence, specifically, the output voltage at every digital input combination. I want to input all digitial input combinations from 000000000000 to 111111111111 (0 to 4096), incrementing by 1 each time. I would then be able to use the output values to calculate dnl,inl, etc.

The problem is that is it not very feasible to set these inputs using 12 vpulse or pwl components. I was wondering if anyone knew of a veriloga/vhdl program that could implement this digital counter type function that I can use to properly input into my DAC in order to plot Vout vs digital in from 0 to 4096.

Thanks a lot.
 

you could just write a simple matlab code that writes the input waveform in a file and use it in a vpwlf source.
 

you mean import the matlab code to cadence and make a symbol out of it? I thought cadence only reads veriloga/vhdl.
 

No, no! I mean that in cadence you use a pwlf source that points to a file. The file contains two columns, the first for time and the second for voltage.
You could use matlab to generate the data points with a simple script.
 
wow that sounds exactly like what I'm looking for. Thanks a lot.

So if i have two columns in a .txt file that are in the form:
time1 voltage1
time2 voltage2
time3 voltage3

then the pwlf source will interpret that correctly? That seems very convenient. I appreciate the help
 

yes, that is correct. Note that you will need to take care of rise and fall time in the waveform definition.
 

yes, I would have to do that. Thanks.

I just realized a potential problem though. The input into the DAC is 12 bits, so I would need 12 of these pwlf sources with the timings properly set for each of them. That seems like it would be quite hard to do. I was hoping I could feed in one source into the DAC, which represents my 12-bit digital input code, but I dont think that would be allowed.
 

Mmm... right!
What about using verilog-a and load a file with
time1 voltage1_1 ... voltage1_12
time2 voltage2_1 ... voltage2_12
time3 voltage3_1 ... voltage3_12
and send it out on a bus.
The advantage is that you can still create any waveform with your matlab script. Your verilog-a will just translate it for cadence.

Added after 4 minutes:

Actually, I do not think verilog-a can read in files...
 
Hm...

How about use a 12-bit Verilog-a counter, and use the output to drive the DAC. increment the counter every cycle.
 
This should do the job...

`include "constants.vams"
`include "disciplines.vams"

module ramp_gen(b);
output [11:0] b;
electrical [11:0] b;

parameter real tp = 100e-9;
parameter real tr = 10e-9;
parameter real tf = 10e-9;
parameter real td = 0;
parameter real vh = 1.2;
parameter real vl = 0;

real count,
bit_v0,
bit_v1,
bit_v2,
bit_v3,
bit_v4,
bit_v5,
bit_v6,
bit_v7,
bit_v8,
bit_v9,
bit_v10,
bit_v11;

integer count_v;

analog begin
@(initial_step)
count=0;

@(timer(0.0,tp)) begin
if(count==4096)
count=0;

count_v=count;
bit_v0=vh*(count_v%2)+vl;
count_v = floor(count_v/2);

bit_v1=vh*(count_v%2)+vl;
count_v = floor(count_v/2);

bit_v2=vh*(count_v%2)+vl;
count_v = floor(count_v/2);

bit_v3=vh*(count_v%2)+vl;
count_v = floor(count_v/2);

bit_v4=vh*(count_v%2)+vl;
count_v = floor(count_v/2);

bit_v5=vh*(count_v%2)+vl;
count_v = floor(count_v/2);

bit_v6=vh*(count_v%2)+vl;
count_v = floor(count_v/2);

bit_v7=vh*(count_v%2)+vl;
count_v = floor(count_v/2);

bit_v8=vh*(count_v%2)+vl;
count_v = floor(count_v/2);

bit_v9=vh*(count_v%2)+vl;
count_v = floor(count_v/2);

bit_v10=vh*(count_v%2)+vl;
count_v = floor(count_v/2);

bit_v11=vh*(count_v%2)+vl;
count_v = floor(count_v/2);

count=count+1;
end

V(b[0]) <+ transition(bit_v0, td,tr,tf );
V(b[1]) <+ transition(bit_v1, td,tr,tf );
V(b[2]) <+ transition(bit_v2, td,tr,tf );
V(b[3]) <+ transition(bit_v3, td,tr,tf );
V(b[4]) <+ transition(bit_v4, td,tr,tf );
V(b[5]) <+ transition(bit_v5, td,tr,tf );
V(b[6]) <+ transition(bit_v6, td,tr,tf );
V(b[7]) <+ transition(bit_v7, td,tr,tf );
V(b[8]) <+ transition(bit_v8, td,tr,tf );
V(b[9]) <+ transition(bit_v9, td,tr,tf );
V(b[10])<+ transition(bit_v10,td,tr,tf );
V(b[11])<+ transition(bit_v11,td,tr,tf );
end
endmodule
 
Thanks! Looks like that code will do the trick. Only thing is that I'm seeing your LSB is bit 11 and MSB is bit 0 (it's flipped, no big deal).

Thank you tremendously for the help. I appreciate it.
 

curious_engineer said:
your LSB is bit 11 and MSB is bit 0 (it's flipped, no big deal).

No, the bits are in the correct order! ;-)
 

curious_engineer said:
Hi all,

I am trying to simulate a 12-bit DAC in Cadence, specifically, the output voltage at every digital input combination. I want to input all digitial input combinations from 000000000000 to 111111111111 (0 to 4096), incrementing by 1 each time. I would then be able to use the output values to calculate dnl,inl, etc.

The problem is that is it not very feasible to set these inputs using 12 vpulse or pwl components.

Why not? These 12 PULSE sources worked fine for my DAC (AFAIR) :

* 12bit input code for DAC

Vbit11 bit11 gnd PULSE (vlo vhi td tr tf 'per/2^1' 'per/2^0')
Vbit10 bit10 gnd PULSE (vlo vhi td tr tf 'per/2^2' 'per/2^1')
Vbit9 bit9 gnd PULSE (vlo vhi td tr tf 'per/2^3' 'per/2^2')
Vbit8 bit8 gnd PULSE (vlo vhi td tr tf 'per/2^4' 'per/2^3')
Vbit7 bit7 gnd PULSE (vlo vhi td tr tf 'per/2^5' 'per/2^4')
Vbit6 bit6 gnd PULSE (vlo vhi td tr tf 'per/2^6' 'per/2^5')
Vbit5 bit5 gnd PULSE (vlo vhi td tr tf 'per/2^7' 'per/2^6')
Vbit4 bit4 gnd PULSE (vlo vhi td tr tf 'per/2^8' 'per/2^7')
Vbit3 bit3 gnd PULSE (vlo vhi td tr tf 'per/2^9' 'per/2^8')
Vbit2 bit2 gnd PULSE (vlo vhi td tr tf 'per/2^10' 'per/2^9')
Vbit1 bit1 gnd PULSE (vlo vhi td tr tf 'per/2^11' 'per/2^10')
Vbit0 bit0 gnd PULSE (vlo vhi td tr tf 'per/2^12' 'per/2^11')
 

you're right, I could have just done that. Thanks.

Anyways, now I am wondering how I can easily extract Vout data at each relevant time increment to capture the output voltage for each input combination. So say I want to record the output value at every 48us, store the values to a table, and somehow have the file saved as a text file.

I tried manually simulating this, but it takes forever. I would like to simply run the simulation and have it automatically create a text file with these Vout values stored. Is this possible by perhaps adding some lines in the ocean script?

Thanks agian guys for the help.
 

curious_engineer said:
Anyways, now I am wondering how I can easily extract Vout data at each relevant time increment to capture the output voltage for each input combination. So say I want to record the output value at every 48us, store the values to a table, and somehow have the file saved as a text file.

I tried manually simulating this, but it takes forever. I would like to simply run the simulation and have it automatically create a text file with these Vout values stored. Is this possible by perhaps adding some lines in the ocean script?
Don't know how it would work with ocean, but in any case Spectre provides an option for its transient analysis called strobing, which should do exactly what you want. The method is explained in Ken Kundert's book "The Designer's Guide to SPICE & SPECTRE", Chap. 4.4.10 Strobing. Or may be you can find out about strobing in Cadence workshops.
 

Here is an ocean snippet that collects the dac_out data and prints it to a file.
You will have to modify it to your needs.
Code:
openResults( <your_result_dir> )
selectResults( 'tran )

fid = outfile( "<your_data_file>" "w")

tsample_list = cross( VT( "/clk" <your_result_dir> ), 0.55, 0, "rising" )

foreach( tsample tsample_list

   dac_out = value( VT("/dac_out" <your_result_dir> ), tsample )
   fprintf( fid "%g\t%g\n" tsample dac_out )
   drain( fid )
)
close( fid )
Note that 0.55 should be changed to the trip voltage of your clock.
I hope it helps.
 

I will look into the strobing. Thanks.

I will also try using your code. This is the code I had before (testing w/ just 1us intervals for 3us):

out = outfile("<data_out text file> "w")
selectResults(`tran)
for(x 1 3
time = x*0.000001 - 1*0.000001
fprintf(out "%5.3f " time)
fprintf(out "%1.6e \n" value(VT("/dacout"), time))
)
close(out)

The time was not incrementing, so it just listed the same line 3 times. It looked like:
0.0000 value
0.0000 value
0.0000 value

I wasn't able to figure out the problem with that. I guess I will try the foreach method. Thanks.
 

curious_engineer said:
for(x 1 3
time = x*0.000001 - 1*0.000001
fprintf(out "%5.3f " time)
fprintf(out "%1.6e \n" value(VT("/dacout"), time))
)
close(out)

The time was not incrementing, so it just listed the same line 3 times. It looked like:
0.0000 value
0.0000 value
0.0000 value

I wasn't able to figure out the problem with that. I guess I will try the foreach method.

The problem is in the output format: if you are happy with your code, try to change fprintf(out "%5.3f " time) to fprintf(out "%5.8f " time)
 
Status
Not open for further replies.

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top