/*******************************************/
/* A High-Quality Analog Oscillator */
/* Albert K. Lu */
/* March 19, 1993 */
/*******************************************/
`timescale 1ns/1ps
module oscillator(input_coefficients[10:0],sign_out,
reset,clk);
input [10:0] input_coefficients;
input reset;
input clk;
output sign_out;
/****************************/
/* Load Circuit */
/****************************/
reg load;
reg doneyet;
reg [10:0] coefficients;
/*** Reset load and doneyet bits ***/
always @ (negedge reset or negedge clk) begin
if (!reset) begin
load=0;
doneyet=0;
end
else if (input_coefficients[10]==1 & !load &
!doneyet) begin
doneyet=1;
load=1;
end
else if (!input_coefficients[10]) begin
doneyet=0;
load=0;
end
else load=0;
end
/*** Latch Coefficients ***/
always @ (input_coefficients or doneyet) begin
if (doneyet)
coefficients=input_coefficients;
else coefficients=11'h094;
end
/******************************************/
/* Body of Oscillator Circuit */
/******************************************/
reg [15:0] integ_1_out;
reg [15:0] integ_2_out;
reg [15:0] shift_out;
reg [15:0] a12_mult_out;
wire [15:0] next_integ_1_out;
wire [15:0] next_integ_2_out;
wire sign_out;
wire dummy1,dummy2;
// First Delay Element
always @(posedge clk or negedge reset or posedge
load) begin
if (!reset) integ_1_out = 16'h6000;
else if (load) integ_1_out={1'b0,
coefficients[4:0],10'h200};
else
integ_1_out = next_integ_1_out;
end
// Second Delay Element
always @(posedge clk or negedge reset or posedge
load) begin
if (!reset) integ_2_out = 16'd0;
else if (load) integ_2_out=16'd0;
else
integ_2_out = next_integ_2_out;
end
// Shift Register - shift left by 8
always @(next_integ_2_out) begin
shift_out={next_integ_2_out[15],next_integ_2_out[15],
next_integ_2_out[15],
next_integ_2_out[15],next_integ_2_out[15],
next_integ_2_out[15],next_integ_2_out[15],
next_integ_2_out[15],next_integ_2_out[15],
next_integ_2_out[14:8]};
end
// First 16 Bit Adder
add16 firstadd(shift_out,integ_1_out,1'd0,
next_integ_1_out,
dummy1);
// Second 16 Bit Adder
add16 secondadd(a12_mult_out,integ_2_out,1'd0,
next_integ_2_out,
dummy2);
// Sigmadelta Modulator
ddisdm sigmadelta(next_integ_1_out,sign_out,
load,reset,clk);
// a12 Coefficient Multiplication
always @(sign_out or coefficients) begin
if (sign_out) a12_mult_out={2'd0,coefficients[9],3'd0,
coefficients[8:5],6'h11};
else a12_mult_out={2'b11,~coefficients[9],3'd7,
~coefficients[8:5],6'h2f};
end
endmodule
/******************************************/
/* Second Order 1 Bit Digital to Analog */
/* Albert K. Lu */
/* March 17, 1993 */
/******************************************/
`timescale 1ns/1ps
module ddisdm(input_signal,sign_out,load,reset,clk);
input [15:0] input_signal;
input reset;
input clk;
input load;
output sign_out;
reg sign_out;
reg [15:0] signalin;
reg feedback;
/* Define signals for first stage */
reg [1:0] integ_1_input_w;
wire [17:0] next_integ_1_out;
reg [17:0] integ_1_out;
always @(input_signal) begin
signalin=input_signal;
end
/* -------------------------------- */
/* Define signals for second stage */
wire [19:0] next_integ_2_out;
wire [3:0] integ_2_input_w;
reg [19:0] integ_2_out;
wire dummy1, dummy2, dummy3, dummy4;
/* -------------------------------- */
/* Feedback is equal to the sign bit of the output */
/* --- Describe First Stage --- */
// First adder - feedback
always @(integ_2_out or signalin) begin
integ_1_input_w[1] = ~integ_2_out[19];
integ_1_input_w[0] = ~signalin[15];
end
// Second adder - integrator 1
add18 adder2({integ_1_input_w[1],integ_1_input_w,
signalin[14:0]}, integ_1_out[17:0],
1'd0,next_integ_1_out,dummy1);
// First integrator delay
always @(posedge clk or negedge reset or posedge
load) begin
if (!reset) integ_1_out = 18'd0;
else if (load) integ_1_out = 18'd0;
else
integ_1_out = next_integ_1_out;
end
/* --- Describe Second Stage --- */
// Third adder
add4 adder3({next_integ_1_out[17],next_integ_1_out[17],
next_integ_1_out[16],next_integ_1_out[15]},
{~integ_2_out[19],~integ_2_out[19],
~integ_2_out[19],1'd1},
1'd0,integ_2_input_w,dummy2,dummy4);
// Fourth adder
add20 adder4({integ_2_input_w[3],integ_2_input_w,
next_integ_1_out[14:0]},
integ_2_out,1'd0,next_integ_2_out,dummy3);
// Second integrator delay
always @(posedge clk or negedge reset or posedge
load) begin
if (!reset) integ_2_out = 20'd0;
else if (load) integ_2_out=20'd0;
else
integ_2_out = next_integ_2_out;
end
/* ------- Define Output ---------- */
always @(integ_2_out) begin
sign_out = integ_2_out[19];
end
endmodule
/*************************************/
/* End D to A */
/*************************************/
/*************************************/
/* Begin Adding Modules */
/*************************************/
/* -------- 4 bit adder ----------- */
`timescale 1ns/1ps
module add4(a,b,cin,sumout,carry,overflow);
input [3:0] a,b;
input cin;
output [3:0] sumout;
output carry;
output overflow;
wire [3:0] sum,co;
reg [3:0] sumout;
reg carry;
reg overflow;
add1 a0(a[0],b[0],cin,sum[0],co[0]);
add1 a1(a[1],b[1],co[0],sum[1],co[1]);
add1 a2(a[2],b[2],co[1],sum[2],co[2]);
add1 a3(a[3],b[3],co[2],sum[3],co[3]);
always @(a or b or co or sum) begin
carry= co[2];
if (carry & !(a[3] | b[3])) begin
sumout= {1'd0,3'h7}; /*saturate to max positive */
overflow=1;
end
if ((a[3] & b[3]) & !sum[3]) begin
sumout= {1'd1,3'd0};
overflow=1;
end
else begin
sumout= sum;
overflow=0;
end
end /* always*/
endmodule
/* ---------------------------------------- */
/* ------------ 18 bit adder -------------- */
`timescale 1ns/1ps
module add18(a,b,cin,sumout,carry);
input [17:0] a,b;
input cin;
output [17:0] sumout;
output carry;
wire [17:0] sum,co;
reg [17:0] sumout;
reg carry;
add1 a0(a[0],b[0],cin,sum[0],co[0]);
add1 a1(a[1],b[1],co[0],sum[1],co[1]);
add1 a2(a[2],b[2],co[1],sum[2],co[2]);
add1 a3(a[3],b[3],co[2],sum[3],co[3]);
add1 a4(a[4],b[4],co[3],sum[4],co[4]);
add1 a5(a[5],b[5],co[4],sum[5],co[5]);
add1 a6(a[6],b[6],co[5],sum[6],co[6]);
add1 a7(a[7],b[7],co[6],sum[7],co[7]);
add1 a8(a[8],b[8],co[7],sum[8],co[8]);
add1 a9(a[9],b[9],co[8],sum[9],co[9]);
add1 a10(a[10],b[10],co[9],sum[10],co[10]);
add1 a11(a[11],b[11],co[10],sum[11],co[11]);
add1 a12(a[12],b[12],co[11],sum[12],co[12]);
add1 a13(a[13],b[13],co[12],sum[13],co[13]);
add1 a14(a[14],b[14],co[13],sum[14],co[14]);
add1 a15(a[15],b[15],co[14],sum[15],co[15]);
add1 a16(a[16],b[16],co[15],sum[16],co[16]);
add1 a17(a[17],b[17],co[16],sum[17],co[17]);
always @(a or b or co or sum) begin
carry= co[16];
if (carry & !(a[17] | b[17]))
sumout= {1'd0,17'h1ffff}; /*saturate to max pos */
else if (a[17] & b[17] & !sum[17])
sumout= {1'd1,17'd0};
else sumout= sum;
end /* always*/
endmodule
/* ---------------------------------------- */
/* ------------ 16 bit adder -------------- */
`timescale 1ns/1ps
module add16(a,b,cin,sumout,carry);
input [15:0] a,b;
input cin;
output [15:0] sumout;
output carry;
wire [15:0] sum,co;
reg [15:0] sumout;
reg carry;
add1 a0(a[0],b[0],cin,sum[0],co[0]);
add1 a1(a[1],b[1],co[0],sum[1],co[1]);
add1 a2(a[2],b[2],co[1],sum[2],co[2]);
add1 a3(a[3],b[3],co[2],sum[3],co[3]);
add1 a4(a[4],b[4],co[3],sum[4],co[4]);
add1 a5(a[5],b[5],co[4],sum[5],co[5]);
add1 a6(a[6],b[6],co[5],sum[6],co[6]);
add1 a7(a[7],b[7],co[6],sum[7],co[7]);
add1 a8(a[8],b[8],co[7],sum[8],co[8]);
add1 a9(a[9],b[9],co[8],sum[9],co[9]);
add1 a10(a[10],b[10],co[9],sum[10],co[10]);
add1 a11(a[11],b[11],co[10],sum[11],co[11]);
add1 a12(a[12],b[12],co[11],sum[12],co[12]);
add1 a13(a[13],b[13],co[12],sum[13],co[13]);
add1 a14(a[14],b[14],co[13],sum[14],co[14]);
add1 a15(a[15],b[15],co[14],sum[15],co[15]);
always @(a or b or co or sum) begin
carry= co[14];
if (carry & !(a[15] | b[15]))
sumout= {1'd0,15'h7fff}; /*saturate to max pos */
else if (a[15] & b[15] & !sum[15])
sumout= {1'd1,15'd0};
else sumout= sum;
end /* always*/
endmodule
/* ---------------------------------------- */
/* ------------ 20 bit adder -------------- */
`timescale 1ns/1ps
module add20(a,b,cin,sumout,carry);
input [19:0] a,b;
input cin;
output [19:0] sumout;
output carry;
wire [19:0] sum,co;
reg [19:0] sumout;
reg carry;
add1 a0(a[0],b[0],cin,sum[0],co[0]);
add1 a1(a[1],b[1],co[0],sum[1],co[1]);
add1 a2(a[2],b[2],co[1],sum[2],co[2]);
add1 a3(a[3],b[3],co[2],sum[3],co[3]);
add1 a4(a[4],b[4],co[3],sum[4],co[4]);
add1 a5(a[5],b[5],co[4],sum[5],co[5]);
add1 a6(a[6],b[6],co[5],sum[6],co[6]);
add1 a7(a[7],b[7],co[6],sum[7],co[7]);
add1 a8(a[8],b[8],co[7],sum[8],co[8]);
add1 a9(a[9],b[9],co[8],sum[9],co[9]);
add1 a10(a[10],b[10],co[9],sum[10],co[10]);
add1 a11(a[11],b[11],co[10],sum[11],co[11]);
add1 a12(a[12],b[12],co[11],sum[12],co[12]);
add1 a13(a[13],b[13],co[12],sum[13],co[13]);
add1 a14(a[14],b[14],co[13],sum[14],co[14]);
add1 a15(a[15],b[15],co[14],sum[15],co[15]);
add1 a16(a[16],b[16],co[15],sum[16],co[16]);
add1 a17(a[17],b[17],co[16],sum[17],co[17]);
add1 a18(a[18],b[18],co[17],sum[18],co[18]);
add1 a19(a[19],b[19],co[18],sum[19],co[19]);
always @(a or b or co or sum) begin
carry= co[18];
if (carry & !(a[19] | b[19]))
sumout= {1'd0,19'h7ffff}; /*saturate to max pos */
else if (a[19] & b[19] & !sum[19])
sumout= {1'd1,19'd0};
else sumout= sum;
end /* always*/
endmodule
/* ---------------------------------------- */
/* ----------- one bit adder -------------- */
`timescale 1ns/1ps
module add1(a,b,cin,sum,carry);
input a,b,cin;
output sum,carry;
reg sum,carry;
always @(a or b or cin) begin
sum= ((a & !b & !cin) | (!a & b & !cin)
| (!a & !b & cin) | (a & b & cin));
carry= ((a & b & !cin) | (!a & b & cin)
| (a & !b & cin) | (a & b & cin));
end
endmodule
/* ------------------------------------------ */
/*********************************************/
/* End Adding Modules */
/*********************************************/
\end{verbatim}
\section{Oscillator Test Routine}
\begin{verbatim}
/*
Oscillator test module
*/
`timescale 1ns / 1ps
module oscillatortest;
reg [10:0] input_coefficients;
reg clk;
reg reset;
reg [12:0] mem_address;
wire sign_out;
/* define memory to provide an input to the convertor*/
reg [10:0] Mem[0:65550];
reg [12:0] i; // counter for for loops
oscillator oscillator(input_coefficients[10:0],sign_out,
reset,clk);
/* initialize the memory */
//initial
// begin
// $readmemb("coefficients.data", Mem, 0);
// for (i = 0; i < 1999; i = i + 1)
$display (" DMem[%0d] = %0d ",i,Mem[i]);
// end
initial begin
// $bnr_write_spdata("fn=oscillatortest.out","hier=1",
oscillator);
reset= 1;
clk = 'b0;
input_coefficients = 11'd0;
mem_address= 0;
#10 reset= 0;
#110 reset = 1;
#400 input_coefficients = 11'h000;
#500 input_coefficients = 11'h48D;
#104957600 $finish;
end
always @(posedge clk or posedge reset) begin
$display("%b ",sign_out);
// input_coefficients = Mem[mem_address];
// if (mem_address == 2047)
// mem_address= 0;
// else
// mem_address= mem_address +1;
end
always #50 clk = ~clk;
endmodule