Commit dc92d265 authored by Tomasz Wlostowski's avatar Tomasz Wlostowski

initial commit

parents
#include <math.h>
#include <stdint.h>
#include <stdio.h>
#define LUT_SIZE_LOG2 10
#define LUT_SIZE (1<<LUT_SIZE_LOG2)
#define ACC_FRAC_BITS 32
#define ACC_BITS (ACC_FRAC_BITS + LUT_SIZE_LOG2 + 2)
#define SLOPE_BITS 18
#define SLOPE_SHIFT 7
#define LUT_BITS 18
#define LUT_AMPL ((1ULL<<(LUT_BITS-1))-(1<<12))
struct lut_entry {
int value;
int slope;
} lut [LUT_SIZE];
struct dds_state {
uint64_t acc;
uint64_t delta;
};
int dds_update(struct dds_state *s)
{
int rv;
int frac;
int quad;
int index;
index = (s->acc >> (ACC_FRAC_BITS)) & ((1 << LUT_SIZE_LOG2) - 1);
quad = (s->acc >> (ACC_FRAC_BITS + LUT_SIZE_LOG2)) & 1;
frac = (s->acc >> (ACC_FRAC_BITS - SLOPE_BITS)) & ((1ULL << SLOPE_BITS) - 1);
struct lut_entry e;
int sign = 1;
// printf("quad %d index %d \n", quad,index);
switch(quad)
{
case 0:
sign = 1;
break;
case 1:
sign = -1;
break;
}
e=lut[index];
int adj = ((int64_t)e.slope * (int64_t)frac) >> (SLOPE_BITS + SLOPE_SHIFT);
printf("idx %d l %d slope %d frac %d adj %d\n", index, e.value, e.slope, frac, adj);
int dither_bits = 7;
// printf("f %d %d %d\n", frac, e.slope, adj);
int v0 = ((((e.value + adj )* sign))); // + (random()&(1<<dither_bits)-1)) << 1) + 1;
printf("v0 %d\n", v0);
v0 >>= 1;
int vb = v0 & (1<<(dither_bits-1));
v0 >>= (dither_bits - 1);
if(vb) v0 ++;
// printf("v %d adj %d\n", v0, adj);
s->acc += s->delta;
s->acc &= ((1ULL << ACC_BITS) - 1ULL);
return v0;
}
void calc_lut()
{
int i,p;
for(i=0;i<LUT_SIZE;i++)
{
double x0 = M_PI*((double)i/LUT_SIZE);
double x1 = M_PI*((double)(i+1)/LUT_SIZE);
double y0 = (double) LUT_AMPL * sin(x0);
double y1 = (double) LUT_AMPL * sin(x1);
double slope = (y1-y0) * (double)(1<<SLOPE_SHIFT);
// printf("v %.3f [%d] slope %.3f [%d] %d\n", y0, (int)y0, slope, (int)slope );
lut[i].value = (int) y0;
lut[i].slope = (int)slope;
p=lut[i].value;
// printf("lut[%d]=36'h%llx;\n",i, (uint64_t) (lut[i].value & 0x3ffff) | (((uint64_t)lut[i].slope & 0x3ffff) << 18));
}
}
void dds_init(struct dds_state *dds, double freq, double fs)
{
dds->acc = 0;
dds->delta = (uint64_t) (((double)LUT_SIZE * freq/fs) * (double)(1ULL << ACC_FRAC_BITS));
dds->delta = 100000000000ULL;
}
main()
{
struct dds_state dds;
calc_lut();
dds_init(&dds, 11.1111e6, 500e6);
int i;
for(i=0;i<262144;i++)
{
printf("", dds_update(&dds));
}
}
files = ["dds_single_channel.v","lfsr_gen.vhd" ]
`timescale 1ns/1ps
module dds_single_channel
(
clk_i,
rst_n_i,
acc_load_i,
tune_load_i,
acc_i,
tune_i,
dreq_i,
y_o,
lut_addr_o,
lut_data_i
);
parameter integer g_acc_frac_bits = 32;
parameter integer g_dither_init_value = 32'h00000001;
parameter integer g_output_bits = 12;
parameter integer g_lut_sample_bits= 18;
parameter integer g_lut_slope_bits = 18;
parameter integer g_interp_shift = 7;
parameter integer g_lut_size_log2 = 12;
parameter integer g_dither_taps = 32'hD0000001;
parameter integer g_dither_length = 32;
localparam c_dither_bits = (g_lut_sample_bits - g_output_bits - 1);
localparam c_acc_bits = g_acc_frac_bits + g_lut_size_log2 + 1;
localparam c_output_shift = g_lut_sample_bits - g_output_bits;
wire signed [c_dither_bits :0 ] dither_in;
input clk_i;
input rst_n_i;
input acc_load_i;
input tune_load_i;
input [g_acc_frac_bits + g_lut_size_log2 : 0] acc_i;
input [g_acc_frac_bits + g_lut_size_log2 : 0] tune_i;
input dreq_i;
output reg [g_output_bits-1:0] y_o;
output reg [g_lut_size_log2-1:0] lut_addr_o;
input [g_lut_sample_bits + g_lut_slope_bits - 1:0] lut_data_i;
reg [c_acc_bits-1:0] acc0, acc1, tune;
wire [g_lut_size_log2 : 0] phase;
wire [g_lut_slope_bits-1 : 0] frac;
reg [g_lut_slope_bits-1 : 0] frac_d0, frac_d1, frac_d2, frac_d3;
wire half;
reg [g_lut_size_log2-1:0] addr0, addr1,tmp,tmp2,tmp3;
reg [8:0] sign;
reg [g_lut_sample_bits + g_lut_slope_bits-1:0] lut_in;
wire signed [g_lut_slope_bits-1:0] lut_slope;
reg signed [g_lut_slope_bits-1:0] slope_d0;
wire signed [g_lut_sample_bits-1:0] lut_sample;
reg signed [g_lut_sample_bits-1:0] sample_d0;
reg signed [g_lut_sample_bits-1:0] interp, interp_d0;
reg signed [g_lut_sample_bits-1:0] qv;
reg signed [g_output_bits:0] yt;
wire signed [2*g_lut_slope_bits-1:0] interp_mul;
reg [g_dither_length-1:0] lfsr=g_dither_init_value;
assign lut_slope = lut_in[g_lut_sample_bits + g_lut_slope_bits - 1 : g_lut_sample_bits ];
assign lut_sample = lut_in[g_lut_sample_bits - 1 : 0];
assign phase = acc1 [ g_acc_frac_bits + g_lut_size_log2 - 1 : g_acc_frac_bits - 1];
assign half = acc1 [g_acc_frac_bits + g_lut_size_log2];
assign frac = acc1 [g_acc_frac_bits - 1 : g_acc_frac_bits-g_lut_slope_bits];
always@(posedge clk_i)
begin
if (!rst_n_i) begin
lfsr <= g_dither_init_value;
end else if (dreq_i) begin
if(lfsr[0])
lfsr <= {1'b0, lfsr[g_dither_length-1:1]} ^ g_dither_taps;
else
lfsr <= {1'b0, lfsr[g_dither_length-1:1]};
end
end
assign dither_in = { lfsr[c_dither_bits+4:5], 1'b0 };
assign interp_mul = signed'(lut_slope) * signed'({1'b0, frac_d3});
always@(posedge clk_i)
begin
if (!rst_n_i) begin
acc0 <= 0;
acc1 <= 0;
tune <= 0;
end else begin
if(tune_load_i)
tune <= tune_i;
if(acc_load_i)
acc0 <= acc_i;
if(dreq_i) begin
acc0 <= acc0 + tune;
acc1 <= acc0;
addr0 <= acc1[g_acc_frac_bits + g_lut_size_log2-1 : g_acc_frac_bits];
sign <= {sign[7:0], half };
lut_addr_o <= addr0;
lut_in <= lut_data_i;
frac_d0 <= frac;
frac_d1 <= frac_d0;
frac_d2 <= frac_d1;
frac_d3 <= frac_d2;
interp <= interp_mul >>> (g_lut_slope_bits + g_interp_shift);
sample_d0 <= lut_sample;
qv <= signed'(sample_d0) + signed'(interp) + signed'(dither_in) + 1;
if(sign[5])
yt <= qv >>> (c_output_shift-1);
else
yt <= (-qv) >>> (c_output_shift-1);
if(yt[0])
y_o <= yt[g_output_bits:1] + 1;
else
y_o <= yt[g_output_bits:1];
end
end // else: !if(!rst_n_i)
end // always@ (posedge clk_i)
endmodule // dds_single_channel
library ieee;
use ieee.STD_LOGIC_1164.all;
entity lfsr_gen is
generic (
g_length : integer;
g_init_value : std_logic_vector;
g_taps : std_logic_vector;
g_recurse : integer := 1
);
port (
clk_i : in std_logic;
rst_n_i : in std_logic;
enable_i : in std_logic;
q_o : out std_logic_vector(g_length-1 downto 0)
);
end lfsr_gen;
architecture rtl of lfsr_gen is
subtype t_lfsr_reg is std_logic_vector(g_length-1 downto 0);
function f_next(x : t_lfsr_reg; taps : std_logic_vector; recurse : integer) return t_lfsr_reg is
variable tmp : t_lfsr_reg;
variable t0 : std_logic;
begin
tmp := x;
for i in 1 to recurse loop
t0 := tmp(0);
tmp := '0' & tmp(tmp'length-1 downto 1);
if(t0 = '1')then
tmp := tmp xor taps;
end if;
end loop; -- i
return tmp;
end f_next;
signal r : t_lfsr_reg;
begin -- rtl
p_generate : process(clk_i)
begin
if rising_edge(clk_i) then
if rst_n_i = '0' then
r <= g_init_value;
elsif(enable_i = '1') then
r <= f_next(r, g_taps, g_recurse);
q_o <= r;
end if;
end if;
end process;
end rtl;
action= "simulation"
target= "xilinx"
fetchto="../../ip_cores"
modules = { "local" : [ "../../rtl" ] }
files = ["main.sv"]
vlog_opt="+incdir+../../sim"
This diff is collapsed.
module main;
parameter g_lut_size_log2 = 10;
parameter g_lut_sample_bits = 18;
parameter g_lut_slope_bits = 18;
reg clk = 0;
reg rst_n = 0;
reg [g_lut_sample_bits + g_lut_slope_bits-1:0] lut_data;
wire [g_lut_size_log2-1:0] lut_addr;
reg [g_lut_sample_bits + g_lut_slope_bits-1:0] lut[0:2**g_lut_size_log2-1];
wire signed [13:0] y;
always@(posedge clk)
lut_data <= lut[lut_addr];
dds_single_channel #(
.g_lut_sample_bits (g_lut_sample_bits),
.g_lut_slope_bits (g_lut_slope_bits),
.g_lut_size_log2 (g_lut_size_log2),
.g_acc_frac_bits (32),
.g_output_bits(14)
) DUT (
.clk_i (clk),
.rst_n_i (rst_n),
.acc_i (44'h0),
.tune_i (44'd100000000000),
.acc_load_i (1'b0),
.tune_load_i(1'b1),
.dreq_i(1'b1),
// #y_o : out std_logic_vector(g_sample_bits-1 downto 0);
.lut_addr_o (lut_addr),
.lut_data_i (lut_data),
.y_o(y)
);
initial #10ns rst_n = 1;
always #1ns clk <= ~clk;
initial begin
real fs=500e6;
real fout=10.079e6;
int i, lut_size;
lut_size = 2**g_lut_size_log2;
// tune = 44'd100000000000;
//int'(real'(2**g_frac_bits) * real'(2**g_lut_size_log2) / fout / fs * 4.0);
for (i=0;i<lut_size;i++)
begin
real y0,y1,ampl;
reg [g_lut_sample_bits + g_lut_slope_bits-1:0] lv;
ampl = real'((2**(g_lut_sample_bits-1)) - (2 ** 12));
//$display("Amplitude: %.3f\n",ampl);
y0 = ampl * $sin (3.14159265358979323846 / real'(lut_size) * i);
y1 = ampl * $sin (3.14159265358979323846 / real'(lut_size) * (i+1));
lv [g_lut_sample_bits-1:0] = int'(y0);
lv [g_lut_sample_bits+g_lut_slope_bits-1:g_lut_sample_bits] = int' ((y1-y0) * 128.0);
lut[i] = lv;
end
end // initial begin
/* initial begin
`include "lut.v"
end*/
int s_count = 0, l_count = 0;
integer f_out;
initial begin
f_out = $fopen("/tmp/dds-hw.dat","w");
$display("File opened, handle %d", f_out);
end
always@(posedge clk)
begin
s_count <= s_count + 1;
if(s_count > 128)
begin
string s;
l_count <= l_count + 1;
$sformat(s, "%d\n", int'(y));
$fwrite(f_out, s);
if(l_count == 262144)
begin
$fclose(f_out);
$stop;
end
end
end
endmodule // main
make
vlog -sv main.sv +incdir+../../sim
vsim -L unisim work.main -voptargs="+acc" -suppress 8684,8683
set NumericStdNoWarnings 1
set StdArithNoWarnings 1
do wave.do
run 100ns
wave zoomfull
radix -hex
onerror {resume}
quietly WaveActivateNextPane {} 0
add wave -noupdate /main/DUT/g_acc_frac_bits
add wave -noupdate /main/DUT/g_dither_init_value
add wave -noupdate /main/DUT/g_output_bits
add wave -noupdate /main/DUT/g_lut_sample_bits
add wave -noupdate /main/DUT/g_lut_slope_bits
add wave -noupdate /main/DUT/g_interp_shift
add wave -noupdate /main/DUT/g_lut_size_log2
add wave -noupdate /main/DUT/c_acc_bits
add wave -noupdate /main/DUT/c_output_shift
add wave -noupdate /main/DUT/clk_i
add wave -noupdate /main/DUT/rst_n_i
add wave -noupdate /main/DUT/acc_load_i
add wave -noupdate /main/DUT/tune_load_i
add wave -noupdate /main/DUT/acc_i
add wave -noupdate /main/DUT/tune_i
add wave -noupdate /main/DUT/dreq_i
add wave -noupdate -format Analog-Step -height 100 -max 2048.0 -min -2048.0 /main/DUT/y_o
add wave -noupdate -format Analog-Step -height 50 -max 1000.0 -min -1000.0 -radix decimal /main/DUT/interp
add wave -noupdate /main/DUT/lut_addr_o
add wave -noupdate /main/DUT/lut_data_i
add wave -noupdate /main/DUT/acc0
add wave -noupdate /main/DUT/acc1
add wave -noupdate /main/DUT/tune
add wave -noupdate /main/DUT/phase
add wave -noupdate /main/DUT/frac
add wave -noupdate /main/DUT/half
add wave -noupdate /main/DUT/addr0
add wave -noupdate /main/DUT/addr1
add wave -noupdate /main/DUT/tmp
add wave -noupdate /main/DUT/tmp2
add wave -noupdate /main/DUT/sign
add wave -noupdate /main/DUT/lut_in
add wave -noupdate /main/DUT/lut_slope
add wave -noupdate -radix decimal /main/DUT/lut_sample
add wave -noupdate -radix decimal /main/DUT/qv
add wave -noupdate /main/DUT/interp_mul
add wave -noupdate /main/DUT/clk_i
add wave -noupdate /main/DUT/rst_n_i
add wave -noupdate /main/DUT/acc_load_i
add wave -noupdate /main/DUT/tune_load_i
add wave -noupdate /main/DUT/acc_i
add wave -noupdate /main/DUT/tune_i
add wave -noupdate /main/DUT/dreq_i
add wave -noupdate -format Analog-Step -height 100 -max 2048.0 -min -2048.0 /main/DUT/y_o
add wave -noupdate /main/DUT/dither_in
add wave -noupdate /main/DUT/lfsr
add wave -noupdate /main/DUT/lut_addr_o
add wave -noupdate /main/DUT/lut_data_i
TreeUpdate [SetDefaultTree]
WaveRestoreCursors {{Cursor 1} {19833 ps} 0}
configure wave -namecolwidth 150
configure wave -valuecolwidth 100
configure wave -justifyvalue left
configure wave -signalnamewidth 1
configure wave -snapdistance 10
configure wave -datasetprefix 0
configure wave -rowmargin 4
configure wave -childrowmargin 2
configure wave -gridoffset 0
configure wave -gridperiod 1
configure wave -griddelta 40
configure wave -timeline 0
configure wave -timelineunits ns
update
WaveRestoreZoom {6845 ps} {33095 ps}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment