-
Notifications
You must be signed in to change notification settings - Fork 13
/
Copy pathafterburner_tb.v
114 lines (103 loc) · 3.16 KB
/
afterburner_tb.v
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
`timescale 1ns / 1ns
// Somewhat compatible with machine-generated freq.vh from FERMI builds
`define COHERENT_DEN (7)
`define RF_NUM (1)
// floor(32768*0.5*sec(2*pi*1/7/2)+0.5)
`define AFTERBURNER_COEFF (18185)
// needed by interpon.v to even pass syntax checks
`define CIC_CNTW (6)
`define CIC_PERIOD (14)
`define CIC_MULT 16'd0
`include "constants.vams"
module afterburner_tb;
// plot "foo" using 1:4 with lp, sin(11*(x-6)/196*2*3.14159265)*1000
reg clk=0, fail=0;
integer cc;
reg debug=0;
integer test_amp=65535;
real fourier_s=0, fourier_v;
integer fourier_n=0;
reg fourier_fault=0;
initial begin
if ($test$plusargs("vcd")) begin
$dumpfile("afterburner.vcd");
$dumpvars(3,afterburner_tb);
end
if ($test$plusargs("debug")) debug=1;
for (cc=0; cc<140; cc=cc+1) begin
clk=0; #5;
clk=1; #5;
end
// Normalized Fourier fundamental component should be basically unity,
// even with a small amount of clipping
fourier_v = 8.0*fourier_s/fourier_n/test_amp/test_amp;
if (fourier_v < 0.9) begin
fourier_fault=1;
fail=1;
end
$display("# Fourier %d %f %s",fourier_n,fourier_v,fourier_fault?"FAULT":" .");
if (fail) begin
$display("FAIL");
$stop(0);
end else begin
$display("PASS");
$finish(0);
end
end
integer wave;
reg signed [16:0] ind=0;
integer iph=0;
real ph; initial ph=0;
always @(posedge clk) begin
// The "10" in the denominator here (and in the similar stanza
// that checks the output) represents the conversion between time
// and clock cycles.
iph = ($time*`RF_NUM) % (`COHERENT_DEN*10);
ph = iph *`M_TWO_PI/(`COHERENT_DEN*10);
wave = $floor(test_amp*$sin(ph)+0.5);
if (wave> 65535) wave = 65535;
if (wave<-65536) wave = -65536;
if (cc==10) ind <= -1000;
else if (cc>20 && cc<140) ind <= wave;
else ind <= 0;
if (cc==80) test_amp=75000; // introduce a small amount of overdrive
end
wire [15:0] outd0, outd1;
reg [15:0] coeff = `AFTERBURNER_COEFF;
afterburner dut(clk, ind, coeff, outd0, outd1);
// Combine outd0 and outd1 to double-data-rate form.
// Don't use dac_cells and FDDRRSE here, because this is
// supposed to be hardware-independent.
reg [15:0] outd1x, outd;
always @(negedge clk) outd1x <= outd1;
always @(posedge clk) outd <= outd0;
always @(negedge clk) outd <= outd1x;
`ifdef AFTERBURNER_TRIPLE
`define COMPUTE_DELAY 60
`else
`define COMPUTE_DELAY 50
`endif
reg signed [15:0] outs;
integer iph2=0;
real ph2; initial ph2=0;
reg signed [16:0] wave2;
reg fail1;
always @(clk) if (cc>3) begin
// See note above to explain the extra "10" in the denominators.
// The point is that time flows by half-cycles.
// The "50" here represents the time delay of the computation.
iph2 = (($time-`COMPUTE_DELAY)*`RF_NUM) % (`COHERENT_DEN*10);
ph2 = iph2 *`M_TWO_PI/(`COHERENT_DEN*10);
// Amplitude of output is half of the input signal
wave2 = $floor(test_amp*0.5*$sin(ph2)+0.5);
// Convert offset binary result of afterburner back to signed.
outs=outd-32768;
fail1=(outs > wave2+3) || outs < (wave2-3);
if (cc>28 && cc<80) fail = fail|fail1;
if (cc>88 && cc<140) begin
fourier_s=fourier_s+outs*1.0*wave2;
fourier_n=fourier_n+1;
end
if (debug) $display("%d %d %d %d %d %d %d %d", $time, clk, ind, outs, wave2, outs-wave2, fail1, cc);
end
endmodule