How to make a VCO in Qspice

Hello, everyone.

I wanna know how to make a VCO in Qspice.
The VCO spec is here.
I wanna make pulse, and I want to control pulse width.

(Repetition) Freqency 3.84MHz.
Supply Voltage 3.3V.
Stability ±25ppm(±96Hz) @ 2.97V~3.63V.

Please tell me.

Regards,
taiki.

I implemented the VCO using behavior model.
Please show me a improve way.


// Automatically generated .v file

//

module vco ( vin, clk100m, fout ) ;
// You will probably want to flush out the nature of these port declarations:
input real vin;
input reg clk100m;
output reg fout;

// Implement the module here
reg[21:0] freq; // out freq
reg[15:0] freqcnt;
reg[21:0] cntr100m; // clk10m counter

assign freq = 291*(vin-3.3)+3840000;
assign freqcnt = (100*1000000)/freq;

always @(posedge clk100m) begin
if (cntr100m == freqcnt) begin
cntr100m = 0;
end else begin
cntr100m = cntr100m + 1;
end
end

always @(cntr100m) begin
if (cntr100m < 2) begin
fout = 1;
end else begin
fout = 0;
end
end

endmodule

I notice that Qspice’s verilog can’t deal with float, so can’t deal with decimal point.
I control the vin 3~5V, but fout does’nt vary.

Please, show me how to deal with decimal point.
If I use C++, is this no problem??

regards,
taiki

There was a discussion about VCO in this post
How to make a voltage controlled oscillator in simulation? - QSPICE - Qorvo Tech Forum

However, a VCO in general is designed to take a control voltage as input and produce a square or sine wave with a frequency controlled by that input voltage. From what you have shown above, with a clk100m input resulting in a pulse at 100kHz, are you truly seeking a VCO?

Thanks reply.

From what you have shown above, with a clk100m input resulting in a pulse at 100kHz, are you truly seeking a VCO?

I seeking a VCO.
I don’t use clk100m as a control voltage.In my circuit, control voltage is vin.
As below code.
assign freq = 291(vin-3.3)+3840000;*
assign freqcnt = (1001000000)/freq;*

I use clk100m to count frequency period(freqcnt).
As below code.
always @(posedge clk100m) begin
if (cntr100m == freqcnt) begin
cntr100m = 0;
end else begin
cntr100m = cntr100m + 1;
end
end

always @(cntr100m) begin
if (cntr100m < 2) begin
fout = 1;
end else begin
fout = 0;
end
endf


My problem is solved now, by using C++ code.
↓↓↓
extern “C” __declspec(dllexport) void vco(void **opaque, double t, union uData *data)
{
double vin = data[0].d; // input
bool clk = data[1].b; // input
bool &fout = data[2].b; // output

// Implement module evaluation code here:
unsigned long freq=0;
unsigned long freqcnt=0;
char clk_pre = 0;

freq = 291*(vin-3.3)+3840000;
freqcnt = 1000000000000/freq;

if (clk_pre==0 && clk==1){cnt++;}
if (cnt==2*freqcnt) {cnt=0;}
fout=(cnt<=1000)?1:0;
clk_pre = clk;
}

Thanks, a lot.

@Taiki ,

Is your VCO trying to control the frequency or the pulse width?

Len

@lpoma
This VCO can control the frequency by vin.
Pulse repeted frequency is described by the following fomula.
freq = 291(vin-3.3)+3840000

But, It is necessary to compile this code in order to control pulse width.
The pulse width is 1Terra Clock*1000 in this C++ code.
fout=(cnt<=1000)?1:0;

taiki