1 |
6 |
leshabiruk |
|
2 |
|
|
|
3 |
|
|
|
4 |
|
|
`define PI_x64 (68'sd57952155664616982739/4)
|
5 |
|
|
`define K_DEFORM (64'h26dd3b6a10d7969a)
|
6 |
|
|
|
7 |
|
|
|
8 |
|
|
module sin_pipelined(
|
9 |
|
|
input clk,
|
10 |
|
|
input signed [UP:0] x,
|
11 |
|
|
output signed [UP:0] osin, //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
12 |
|
|
output signed [UP:0] ocos,
|
13 |
|
|
output signed [UP:0] odebug
|
14 |
|
|
);
|
15 |
|
|
|
16 |
|
|
parameter BITS_HIGH= 16;
|
17 |
|
|
parameter BITS_LOW= 16;
|
18 |
|
|
parameter BITS_GUARD= 2;
|
19 |
|
|
// Производные константы, не переопределять.
|
20 |
|
|
|
21 |
|
|
// разрядность аргумента
|
22 |
|
|
parameter UP= BITS_HIGH +BITS_LOW -1;
|
23 |
|
|
|
24 |
|
|
// у результата старшая часть- все нули(или единицы)
|
25 |
|
|
parameter UPL= BITS_LOW -1;
|
26 |
|
|
|
27 |
|
|
// добавляем "сторожевые" или "мусорные" биты для точности
|
28 |
|
|
parameter UPG= UP +BITS_GUARD;
|
29 |
|
|
parameter UPLG= UPL +BITS_GUARD;
|
30 |
|
|
|
31 |
|
|
`define BOUT (UP) // Чтобы мониторить промежуточные стадии при отладке
|
32 |
|
|
reg signed [UPG:0] cx [`BOUT:0];
|
33 |
|
|
|
34 |
|
|
reg signed [UPLG+1:0] csin [`BOUT:BITS_HIGH-1];//!!!+2!!!!
|
35 |
|
|
reg signed [UPLG+1:0] ccos [`BOUT:BITS_HIGH-1];
|
36 |
|
|
|
37 |
|
|
wire signed [UPG:0] x0= (x[UP] ? -x : x)<<
|
38 |
|
|
|
39 |
|
|
//wire [UP:0] p_osin= s_sign[BITS_HIGH-1]? (-cx[BITS_HIGH-1]>>BITS_GUARD): cx[BITS_HIGH-1]>>BITS_GUARD; // !!!!!!!!!!!!!!!!!!!!!
|
40 |
|
|
//wire [UP:0] p_osin= s_sign[BITS_HIGH+1]? (-csin[BITS_HIGH+1][UPLG:BITS_GUARD]>>BITS_GUARD): csin[BITS_HIGH+1][UPLG:BITS_GUARD]>>BITS_GUARD; // !!!!!!!!!!!!!!!!!!!!!
|
41 |
|
|
//wire [UPL:0] p_osin= csin[BITS_HIGH][UPLG:BITS_GUARD];
|
42 |
|
|
//wire [UPL:0] p_osin= csin[UPL][UPLG:BITS_GUARD] +csin[UPL][BITS_GUARD-1];
|
43 |
|
|
|
44 |
|
|
assign osin= csin[`BOUT]>>>BITS_GUARD; // !!!!!!!!!!!!!!!!!!!!!
|
45 |
|
|
assign ocos= ccos[`BOUT]>>>BITS_GUARD; // !!!!!!!!!!!!!!!!!!!!!
|
46 |
|
|
assign odebug= cx[`BOUT]>>>BITS_GUARD; // !!!!!!!!!!!!!!!!!!!!!
|
47 |
|
|
|
48 |
|
|
//assign osin= s_sign[`BOUT]? (-cx[`BOUT]>>BITS_GUARD): cx[`BOUT]>>>BITS_GUARD; // !!!!!!!!!!!!!!!!!!!!!
|
49 |
|
|
//assign ocos= ccos[UPL][UPLG:BITS_GUARD] +ccos[UPL][BITS_GUARD-1];
|
50 |
|
|
|
51 |
|
|
// углы, для которых поворот соответствует умножению на 1.00...001
|
52 |
|
|
wire signed [63:0] C_ANGLE [63:0];
|
53 |
|
|
|
54 |
|
|
reg s_sign [UP:0];
|
55 |
|
|
reg c_sign [UP:BITS_HIGH-2];
|
56 |
|
|
reg xy_swap [UP:BITS_HIGH-1];
|
57 |
|
|
|
58 |
|
|
always @( posedge clk )
|
59 |
|
|
begin
|
60 |
|
|
integer ind;
|
61 |
|
|
|
62 |
|
|
// сохраняем знак, чтобы в конце обратить синус ( sin(-x)=sin(x) )
|
63 |
|
|
for (ind=0; ind< BITS_HIGH-4; ind=ind+1)
|
64 |
|
|
begin
|
65 |
|
|
end
|
66 |
|
|
|
67 |
|
|
// x <- x-Pi*n
|
68 |
|
|
// s_sign[BITS_HIGH-2]<= ( cx[BITS_HIGH-3]- (`PI_x64>>(67-(UPG-(BITS_HIGH-3)) )) >0
|
69 |
|
|
// ? s_sign[BITS_HIGH-3] : ~s_sign[BITS_HIGH-3] );
|
70 |
|
|
//
|
71 |
|
|
// c_sign[BITS_HIGH-2]<= ( cx[BITS_HIGH-3]- (`PI_x64>>(67-(UPG-(BITS_HIGH-3)) )) >0
|
72 |
|
|
// ? s_sign[BITS_HIGH-3] : ~s_sign[BITS_HIGH-3] );
|
73 |
|
|
|
74 |
|
|
|
75 |
|
|
// x <- x-Pi*n/2
|
76 |
|
|
// s_sign[BITS_HIGH-1]<= s_sign[BITS_HIGH-2];
|
77 |
|
|
|
78 |
|
|
// приводим аргумент к беззнаковому виду
|
79 |
|
|
s_sign[0]<= x[UP];
|
80 |
|
|
cx[0]<= ( x0- (`PI_x64>>>(65-(UPG) )) >0 ? x0- (`PI_x64>>>(65-(UPG) )) : x0 );
|
81 |
|
|
|
82 |
|
|
// вычитаем 2*Pi*n
|
83 |
|
|
for (ind=0; ind< BITS_HIGH-4; ind=ind+1)
|
84 |
|
|
begin
|
85 |
|
|
cx[ind+1]<= ( cx[ind]- (`PI_x64>>>(66-(UPG-ind) )) >0 ? cx[ind]- (`PI_x64>>>(66-(UPG-ind) )) : cx[ind] );
|
86 |
|
|
s_sign[ind+1]<= s_sign[ind];
|
87 |
|
|
end
|
88 |
|
|
|
89 |
|
|
// for (ind=BITS_HIGH-4; ind< BITS_HIGH-1; ind=ind+1)
|
90 |
|
|
begin
|
91 |
|
|
// вычитаем Pi*n
|
92 |
|
|
ind= BITS_HIGH-4;
|
93 |
|
|
if ( cx[ind]- (`PI_x64>>>(66-(UPG-ind) )) >0 )
|
94 |
|
|
begin
|
95 |
|
|
cx[ind+1]<= (`PI_x64>>>(65-(UPG-ind) ))-cx[ind];
|
96 |
|
|
s_sign[ind+1]<= ~s_sign[ind];
|
97 |
|
|
end
|
98 |
|
|
else
|
99 |
|
|
begin
|
100 |
|
|
cx[ind+1]<= cx[ind];
|
101 |
|
|
s_sign[ind+1]<= s_sign[ind];
|
102 |
|
|
end
|
103 |
|
|
end
|
104 |
|
|
begin
|
105 |
|
|
ind= BITS_HIGH-3;
|
106 |
|
|
if ( cx[ind]- (`PI_x64>>>(66-(UPG-ind) )) >0 )
|
107 |
|
|
begin
|
108 |
|
|
cx[ind+1]<= (`PI_x64>>>(65-(UPG-ind) ))-cx[ind];
|
109 |
|
|
s_sign[ind+1]<= s_sign[ind];
|
110 |
|
|
c_sign[ind+1]<= 1'h1;
|
111 |
|
|
end
|
112 |
|
|
else
|
113 |
|
|
begin
|
114 |
|
|
cx[ind+1]<= cx[ind];
|
115 |
|
|
s_sign[ind+1]<= s_sign[ind];
|
116 |
|
|
c_sign[ind+1]<= 1'h0;
|
117 |
|
|
end
|
118 |
|
|
end
|
119 |
|
|
|
120 |
|
|
begin
|
121 |
|
|
ind= BITS_HIGH-2;
|
122 |
|
|
if ( cx[ind] > (`PI_x64>>(66-(UPG-ind) )) )
|
123 |
|
|
begin
|
124 |
|
|
cx[ind+1]<= (s_sign[ind]^c_sign[ind]) ? ((`PI_x64>>>(65-(UPG-ind) ))-cx[ind]) : -((`PI_x64>>>(65-(UPG-ind) ))-cx[ind]);
|
125 |
|
|
csin[ind+1]<= 0;
|
126 |
|
|
ccos[ind+1]<= -(`K_DEFORM>>(64-UPLG-3))
|
127 |
|
|
+(1<=|1.0|, if you prefer more precision, you need to
|
128 |
|
|
// csin[ind+1]<= s_sign[ind] ? -(64'sh9B74) : 64'sh9B74;
|
129 |
|
|
// ccos[ind+1]<= 0;
|
130 |
|
|
end
|
131 |
|
|
else
|
132 |
|
|
begin
|
133 |
|
|
cx[ind+1]<= (s_sign[ind]^c_sign[ind]) ? -(cx[ind]) : (cx[ind]);
|
134 |
|
|
csin[ind+1]<= 0;
|
135 |
|
|
ccos[ind+1]<= (`K_DEFORM>>(64-UPLG-3))
|
136 |
|
|
-(1<=|1.0|
|
137 |
|
|
// csin[ind+1]<= 0;
|
138 |
|
|
// ccos[ind+1]<= c_sign[ind] ? -(64'sh9B74) : 64'sh9B74;
|
139 |
|
|
end
|
140 |
|
|
s_sign[ind+1]<= 0;
|
141 |
|
|
c_sign[ind+1]<= 0;
|
142 |
|
|
end
|
143 |
|
|
|
144 |
|
|
`define BHm1 (BITS_HIGH-1)
|
145 |
|
|
// собственно, CORDIC
|
146 |
|
|
// cx[16]<= cx[15]- 32'sh00003000;//(C_ANGLE[ind-`BHm1] >> (64-UPLG));
|
147 |
|
|
|
148 |
|
|
// Каждый "проход по циклу" создаёт ступень конвеера
|
149 |
|
|
for (ind=`BHm1; ind< `BOUT; ind=ind+1)
|
150 |
|
|
// ind - псевдопеременная цикла, `BHm1, `BOUT - макропеременные, определённые
|
151 |
|
|
// с помощью директивы `define
|
152 |
|
|
// меняя `BHm1, `BOUT, UPLG можно настроить такие параметры как
|
153 |
|
|
// разрядность, глубина конвеера.
|
154 |
|
|
begin
|
155 |
|
|
if ( cx[ind] >0 )
|
156 |
|
|
begin
|
157 |
|
|
// поворот туда (см. CORDIC)
|
158 |
|
|
// cx, csin, ccos - массивы шин, cx[ind] - конкретная шина
|
159 |
|
|
// шина, в свою очередь, это массив битов (число)
|
160 |
|
|
cx[ind+1]<= cx[ind]- (C_ANGLE[ind-`BHm1] >>> (64-UPLG));
|
161 |
|
|
csin[ ind +1 ]<= csin[ ind ] + (ccos[ ind ] >>>(ind-`BHm1 ) );
|
162 |
|
|
ccos[ ind +1 ]<= ccos[ ind ] - (csin[ ind ] >>>(ind-`BHm1 ) );
|
163 |
|
|
end
|
164 |
|
|
else
|
165 |
|
|
begin
|
166 |
|
|
// поворот cуда
|
167 |
|
|
cx[ind+1]<= cx[ind]+ (C_ANGLE[ind-`BHm1] >>> (64-UPLG));
|
168 |
|
|
csin[ ind +1 ]<= csin[ ind ] - (ccos[ ind ] >>>(ind-`BHm1 ) );
|
169 |
|
|
ccos[ ind +1 ]<= ccos[ ind ] + (csin[ ind ] >>>(ind-`BHm1 ) );
|
170 |
|
|
end
|
171 |
|
|
end
|
172 |
|
|
// Последний шаг
|
173 |
|
|
// begin
|
174 |
|
|
// ind= UP-2;
|
175 |
|
|
// if ( cx[ind] >0 )
|
176 |
|
|
// begin
|
177 |
|
|
// cx[ind+1]<= cx[ind]- (C_ANGLE[ind-BITS_HIGH+1] >>> (63-UPLG));
|
178 |
|
|
// csin[ ind +1 ]<= s_sign[ind] ?-(csin[ ind ] + (ccos[ ind ] >>>(ind-(BITS_HIGH-1) +1) )) :
|
179 |
|
|
// csin[ ind ] - (ccos[ ind ] >>>(ind-(BITS_HIGH-1) +1) );
|
180 |
|
|
// ccos[ ind +1 ]<= c_sign[ind] ? -(ccos[ ind ] - (csin[ ind ] >>>(ind-(BITS_HIGH-1) +1) )) :
|
181 |
|
|
// ccos[ ind ] + (csin[ ind ] >>>(ind-(BITS_HIGH-1) +1) );
|
182 |
|
|
// end
|
183 |
|
|
// else
|
184 |
|
|
// begin
|
185 |
|
|
// cx[ind+1]<= cx[ind]+ (C_ANGLE[ind-BITS_HIGH+1] >>> (63-UPLG));
|
186 |
|
|
// csin[ ind +1 ]<= s_sign[ind] ?-(csin[ ind ] + (ccos[ ind ] >>>(ind-(BITS_HIGH-1) +1) )) :
|
187 |
|
|
// csin[ ind ] + (ccos[ ind ] >>>(ind-(BITS_HIGH-1) +1) );
|
188 |
|
|
//
|
189 |
|
|
// ccos[ ind +1 ]<= c_sign[ind] ? -(ccos[ ind ] - (csin[ ind ] >>>(ind-(BITS_HIGH-1) +1) )) :
|
190 |
|
|
// ccos[ ind ] - (csin[ ind ] >>>(ind-(BITS_HIGH-1) +1) );
|
191 |
|
|
// end
|
192 |
|
|
// s_sign[ind+1]<= s_sign[ind];
|
193 |
|
|
// c_sign[ind+1]<= c_sign[ind];
|
194 |
|
|
// end
|
195 |
|
|
|
196 |
|
|
|
197 |
|
|
// if ( x[UP] )
|
198 |
|
|
// begin
|
199 |
|
|
// end
|
200 |
|
|
// else
|
201 |
|
|
// begin
|
202 |
|
|
// cx[0]= x;
|
203 |
|
|
// end
|
204 |
|
|
end
|
205 |
|
|
|
206 |
|
|
// for ( i=0; i<64; i++){
|
207 |
|
|
// double dval= atan(1./pow(2.,i)) * pow(2.,63.); //((long long)1 << i);
|
208 |
|
|
// unsigned long long val= dval;
|
209 |
|
|
// cout << "assign C_ANGLE[" << dec << i << "]= 64'h" << hex << val << ";" << endl;
|
210 |
|
|
// }
|
211 |
|
|
|
212 |
|
|
assign C_ANGLE[0] = 64'sh6487ed5110b46000;
|
213 |
|
|
assign C_ANGLE[1] = 64'sh3b58ce0ac3769e00;
|
214 |
|
|
assign C_ANGLE[2] = 64'sh1f5b75f92c80dd00;
|
215 |
|
|
assign C_ANGLE[3] = 64'shfeadd4d5617b700;
|
216 |
|
|
assign C_ANGLE[4] = 64'sh7fd56edcb3f7a80;
|
217 |
|
|
assign C_ANGLE[5] = 64'sh3ffaab7752ec4a0;
|
218 |
|
|
assign C_ANGLE[6] = 64'sh1fff555bbb729b0;
|
219 |
|
|
assign C_ANGLE[7] = 64'shfffeaaadddd4b8;
|
220 |
|
|
assign C_ANGLE[8] = 64'sh7fffd5556eeedc;
|
221 |
|
|
assign C_ANGLE[9] = 64'sh3ffffaaaab7778;
|
222 |
|
|
assign C_ANGLE[10]= 64'sh1fffff55555bbc;
|
223 |
|
|
assign C_ANGLE[11]= 64'shfffffeaaaaade;
|
224 |
|
|
assign C_ANGLE[12]= 64'sh7fffffd555557;
|
225 |
|
|
assign C_ANGLE[13]= 64'sh3ffffffaaaaaa;
|
226 |
|
|
assign C_ANGLE[14]= 64'sh1fffffff55555;
|
227 |
|
|
assign C_ANGLE[15]= 64'shfffffffeaaaa;
|
228 |
|
|
assign C_ANGLE[16]= 64'sh7fffffffd555;
|
229 |
|
|
assign C_ANGLE[17]= 64'sh3ffffffffaaa;
|
230 |
|
|
assign C_ANGLE[18]= 64'sh1fffffffff55;
|
231 |
|
|
assign C_ANGLE[19]= 64'shfffffffffea;
|
232 |
|
|
assign C_ANGLE[20]= 64'sh7fffffffffd;
|
233 |
|
|
assign C_ANGLE[21]= 64'sh3ffffffffff;
|
234 |
|
|
assign C_ANGLE[22]= 64'sh1ffffffffff;
|
235 |
|
|
assign C_ANGLE[23]= 64'shffffffffff;
|
236 |
|
|
assign C_ANGLE[24]= 64'sh7fffffffff;
|
237 |
|
|
assign C_ANGLE[25]= 64'sh3fffffffff;
|
238 |
|
|
assign C_ANGLE[26]= 64'sh1fffffffff;
|
239 |
|
|
assign C_ANGLE[27]= 64'sh1000000000;
|
240 |
|
|
assign C_ANGLE[28]= 64'sh800000000;
|
241 |
|
|
assign C_ANGLE[29]= 64'sh400000000;
|
242 |
|
|
assign C_ANGLE[30]= 64'sh200000000;
|
243 |
|
|
assign C_ANGLE[31]= 64'sh100000000;
|
244 |
|
|
assign C_ANGLE[32]= 64'sh80000000;
|
245 |
|
|
assign C_ANGLE[33]= 64'sh40000000;
|
246 |
|
|
assign C_ANGLE[34]= 64'sh20000000;
|
247 |
|
|
assign C_ANGLE[35]= 64'sh10000000;
|
248 |
|
|
assign C_ANGLE[36]= 64'sh8000000;
|
249 |
|
|
assign C_ANGLE[37]= 64'sh4000000;
|
250 |
|
|
assign C_ANGLE[38]= 64'sh2000000;
|
251 |
|
|
assign C_ANGLE[39]= 64'sh1000000;
|
252 |
|
|
assign C_ANGLE[40]= 64'sh800000;
|
253 |
|
|
assign C_ANGLE[41]= 64'sh400000;
|
254 |
|
|
assign C_ANGLE[42]= 64'sh200000;
|
255 |
|
|
assign C_ANGLE[43]= 64'sh100000;
|
256 |
|
|
assign C_ANGLE[44]= 64'sh80000;
|
257 |
|
|
assign C_ANGLE[45]= 64'sh40000;
|
258 |
|
|
assign C_ANGLE[46]= 64'sh20000;
|
259 |
|
|
assign C_ANGLE[47]= 64'sh10000;
|
260 |
|
|
assign C_ANGLE[48]= 64'sh8000;
|
261 |
|
|
assign C_ANGLE[49]= 64'sh4000;
|
262 |
|
|
assign C_ANGLE[50]= 64'sh2000;
|
263 |
|
|
assign C_ANGLE[51]= 64'sh1000;
|
264 |
|
|
assign C_ANGLE[52]= 64'sh800;
|
265 |
|
|
assign C_ANGLE[53]= 64'sh400;
|
266 |
|
|
assign C_ANGLE[54]= 64'sh200;
|
267 |
|
|
assign C_ANGLE[55]= 64'sh100;
|
268 |
|
|
assign C_ANGLE[56]= 64'sh80;
|
269 |
|
|
assign C_ANGLE[57]= 64'sh40;
|
270 |
|
|
assign C_ANGLE[58]= 64'sh20;
|
271 |
|
|
assign C_ANGLE[59]= 64'sh10;
|
272 |
|
|
assign C_ANGLE[60]= 64'sh8;
|
273 |
|
|
assign C_ANGLE[61]= 64'sh4;
|
274 |
|
|
assign C_ANGLE[62]= 64'h2;
|
275 |
|
|
assign C_ANGLE[63]= 64'h1;
|
276 |
|
|
endmodule
|
277 |
|
|
|
278 |
|
|
|
279 |
|
|
|
280 |
|
|
|