OpenCores
URL https://opencores.org/ocsvn/sincos/sincos/trunk

Subversion Repositories sincos

[/] [sincos/] [trunk/] [vhdl/] [arith/] [sincos/] [sincos.vhd] - Blame information for rev 43

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 43 dk4xp
-- portable sine table without silicon vendor macros.
2
-- (c) 2005... Gerhard Hoffmann, Ulm, Germany   opencores@hoffmann-hochfrequenz.de
3
--
4
-- V1.0  2010-nov-22  published under BSD license
5
-- V1.1  2011-feb-08  U_rom_dly_c cosine latency was off by 1. 
6
-- V1.2  2001-apr-04  corrected latency of block rom
7
--
8
-- In Crawford, Frequency Synthesizer Handbook is the Sunderland technique
9
-- to compress the table size up to 1/12th counted in storage bits by decomposing to 2 smaller ROMs. 
10
-- This has not yet been expoited here. 1/50 should be possible, too.
11
--
12
-- I'm more interested in low latency because latency introduces an unwelcome 
13
-- dead time in wideband PLLs / phase demodulators. That also rules out the CORDIC for me.
14
-- As long as it fits into a reasonable amount of block rams that's ok.
15
--
16
-- TODO: BCD version, so we can do a DDS that delivers EXACTLY 10 MHz out for 100 MHz in.
17
 
18
 
19
library ieee;
20
use ieee.std_logic_1164.all;
21
use ieee.numeric_std.all;
22
use ieee.math_real.all;
23
 
24
 
25
 
26
entity sintab is
27
   generic (
28
      pipestages: integer range 0 to 10
29
   );
30
   port (
31
      clk:        in  std_logic;
32
      ce:         in  std_logic := '1';
33
      rst:        in  std_logic := '0';
34
 
35
      theta:      in  unsigned;
36
      sine:       out signed
37
   );
38
end entity sintab;
39
 
40
 
41
 
42
architecture rtl of sintab is
43
 
44
 
45
-- pipeline delay distribution. 
46
-- address and output stage are just conditional two's complementers/subtractors
47
-- The ROM will consume most of the pipeline delay. Xilinx block rams won't do
48
-- without some latency. During synthesis, the register balancer will shift 
49
-- pipe stages anyway to its taste, but at least it gets a good start.
50
 
51
type delaytable is array(0 to 10) of integer;
52
 
53
constant in_pipe:  delaytable := ( 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1);
54
constant adr_pipe: delaytable := ( 0, 0, 0, 1, 1, 1, 1, 2, 2, 3, 3);
55
constant rom_pipe: delaytable := ( 0, 1, 1, 1, 2, 2, 2, 2, 3, 3, 4);
56
constant out_pipe: delaytable := ( 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 2);
57
 
58
--    total delay                  0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10
59
 
60
 
61
 
62
constant verbose:            boolean := false;
63
 
64
signal   piped_theta:        unsigned(theta'range);   -- pipelined input
65
 
66
signal   rom_address:        unsigned(theta'high-2 downto 0);
67
signal   piped_rom_address:  unsigned(theta'high-2 downto 0);
68
 
69
 
70
signal   piped_abs_sin:      unsigned(sine'high-1 downto 0);
71
 
72
signal   piped_invert:       std_logic;
73
signal   sig_sin:            signed(sine'range);
74
 
75
----------------------------------------------------------------------------------------------------
76
--
77
-- The sine lookup table and how it is initialized.
78
--
79
--
80
-- the sine lookup table is unsigned because we store one quarter wave only.
81
type sintab is array (0 to (2**(theta'length-2)) -1) of unsigned(sine'length-2 downto 0);
82
 
83
 
84
function sine_at_middle_of_bin( bin: integer; rom_words: integer) return real is
85
  variable x:  real;
86
begin
87
    x := (real(bin) + 0.5) * MATH_PI / 2.0 / real(rom_words);
88
    return sin(x);
89
end;
90
 
91
 
92
function init_sin(verbose: boolean; rom_words: integer; bits_per_uword: integer) return sintab is
93
  variable s: sintab;
94
  variable y: real;
95
  constant scalefactor: real := real((2 ** bits_per_uword)-1);
96
 
97
  begin
98
     if verbose
99
     then
100
       report "initializing sine table:    rom_words = "
101
            & integer'image(rom_words)
102
            & "   rom bits per unsigned word = "
103
            & integer'image(bits_per_uword)
104
            & "    scalefactor = "
105
            & real'image(scalefactor);
106
     end if;
107
 
108
     for i in 0 to rom_words-1 loop
109
       y := sine_at_middle_of_bin(i, rom_words);
110
       s(i) := to_unsigned(integer( round(y * scalefactor )), bits_per_uword);
111
 
112
       if verbose
113
       then
114
         report "i = "                & integer'image(i)
115
            & "  exact sin y = "      & real'image(y)
116
            & "  exact scaled y = "   & real'image(y*scalefactor)
117
            & "  rounded int s(i) = " & integer'image( to_integer(s(i)))
118
            & "  error = "            & real'image(y*scalefactor - real(to_integer(s(i))))
119
            ;
120
        end if;
121
      end loop;
122
 
123
  return s;
124
end function init_sin;
125
 
126
 
127
-- The 'constant' is important here.  It tells the synthesizer that 
128
-- all the computations can be done at compile time.
129
 
130
constant sinrom:  sintab := init_sin(verbose, 2 ** (theta'length-2), sine'length-1);
131
 
132
 
133
----------------------------------------------------------------------------------------------------
134
--
135
-- convert phase input to ROM address.
136
--
137
-- theta has an address range from 0 to a little less than 2 Pi. (full circle)
138
-- "a little less than 2 pi" is represented as all ones.
139
-- The look up table goes only from 0 to a little less than 1/2 Pi. (quarter circle)
140
-- The two highest bits of theta determine only the quadrant
141
-- and are implemented by address mirroring and sign change.
142
 
143
-- address mirroring    hi bits      sine    cosine
144
-- 1st quarter wave     00           no      yes
145
-- 2nd quarter wave     01           yes     no
146
-- 3rd quarter wave     10           no      yes
147
-- 4th quarter wave     11           yes     no
148
 
149
function reduce_sin_address (theta: unsigned) return unsigned is
150
 
151
   variable quarterwave_address: unsigned(theta'high-2 downto 0);
152
   variable mirrored:            boolean;
153
   variable forward_address:     unsigned(theta'high-2 downto 0);
154
   variable backward_address:    unsigned(theta'high-2 downto 0);
155
 
156
begin
157
 
158
  -- the highest bit makes no difference on the abs. value of the sine
159
  -- it just negates the value if set. This is done on the output side
160
  -- after the ROM.
161
 
162
  mirrored := ((theta(theta'high) = '0') and (theta(theta'high-1) = '1'))  -- 2nd quadr.
163
           or ((theta(theta'high) = '1') and (theta(theta'high-1) = '1')); -- 4th quadr.
164
 
165
  forward_address    :=                      theta(theta'high-2 downto 0);
166
  backward_address   := unsigned(-1 -signed( theta(theta'high-2 downto 0)));
167
 
168
  if mirrored then
169
    quarterwave_address := backward_address;
170
  else
171
    quarterwave_address := forward_address;
172
  end if;
173
 
174
  if verbose
175
  then
176
    report "theta = "                   & integer'image(to_integer(theta))
177
         & "   forward: "               & integer'image(to_integer(forward_address))
178
         & "   backward: "              & integer'image(to_integer(backward_address))
179
         & "   Quarterwave address = "  & integer'image(to_integer(quarterwave_address))
180
         & "   mirrored: "              & boolean'image(mirrored);
181
  end if;
182
  return quarterwave_address;
183
end reduce_sin_address;
184
 
185
 
186
begin
187
 
188
-- input delay stage
189
 
190
u_adr:  entity work.unsigned_pipestage
191
generic map (
192
  n_stages      => in_pipe(pipestages)
193
)
194
Port map (
195
  clk => clk,
196
  ce  => ce,
197
  rst => rst,
198
 
199
  i   => theta,
200
  o   => piped_theta
201
);
202
 
203
----------------------------------------------------------------------------------------------------
204
-- propagate the information whether we will have to invert the output
205
 
206
u_inv:  entity work.sl_pipestage
207
generic map (
208
  n_stages      => adr_pipe(pipestages) + rom_pipe(pipestages)
209
)
210
Port map (
211
  clk => clk,
212
  ce  => ce,
213
  rst => rst,
214
 
215
  i   => std_logic(piped_theta(piped_theta'high)),   -- sine is neg. for 2nd half of cycle
216
  o   => piped_invert                                -- i.e. when the highest input bit is set.
217
);
218
 
219
----------------------------------------------------------------------------------------------------
220
--
221
-- address folding with potential pipe stage
222
--
223
 
224
rom_address <= reduce_sin_address(piped_theta);
225
 
226
u_pip_adr:      entity work.unsigned_pipestage
227
generic map (
228
  n_stages      => adr_pipe(pipestages)
229
)
230
Port map (
231
  clk => clk,
232
  ce  => ce,
233
  rst => rst,
234
 
235
  i   => rom_address,
236
  o   => piped_rom_address
237
);
238
 
239
--------------------------------------------------------------------------------
240
--
241
-- ROM access
242
 
243
dist_rom: if rom_pipe(pipestages) = 0
244
generate  -- a distributed ROM if no latency is allowed
245
begin
246
  piped_abs_sin <= sinrom(to_integer(piped_rom_address));
247
end generate;
248
 
249
 
250
 
251
block_rom: if rom_pipe(pipestages) > 0
252
generate
253
 
254
  signal   abs_sin:  unsigned(sine'high-1 downto 0);
255
 
256
begin
257
  -- Xilinx XST 12.3 needs a clocked process to infer
258
  -- BlockRam/ROM. It does not see that it could generate block ROM 
259
  -- if it propagated a pipestage. 
260
  u_rom: process(clk) is
261
  begin
262
    if rising_edge(clk)
263
    then
264
      abs_sin <= sinrom(to_integer(piped_rom_address));
265
    end if;
266
  end process;
267
 
268
 
269
  -- additional rom pipeline delay if needed
270
  u_rom_dly:    entity work.unsigned_pipestage
271
  generic map (
272
    n_stages    => rom_pipe(pipestages)-1
273
  )
274
  Port map (
275
    clk => clk,
276
    ce  => ce,
277
    rst => rst,
278
 
279
    i   => abs_sin,
280
    o   => piped_abs_sin
281
  );
282
end generate;
283
 
284
 
285
--------------------------------------------------------------------------------
286
--
287
-- conditional output inversion
288
-- table entries are unsigned. Make them one bit larger
289
-- so that we have a home for the sign bit.
290
 
291
 
292
   sig_sin <= -signed(resize(piped_abs_sin, sine'length)) when piped_invert = '1'
293
          else
294
               signed(resize(piped_abs_sin, sine'length));
295
 
296
 
297
 
298
u_2:    entity work.signed_pipestage
299
generic map (
300
  n_stages      => out_pipe(pipestages)
301
)
302
Port map (
303
  clk => clk,
304
  ce  => ce,
305
  rst => rst,
306
 
307
  i   => sig_sin,
308
  o   => sine
309
);
310
 
311
 
312
END ARCHITECTURE rtl;
313
 
314
 
315
 
316
 
317
 
318
 
319
-------------------------------------------------------------------------------------------------------------
320
-------------------------------------------------------------------------------------------------------------
321
-------------------------------------------------------------------------------------------------------------
322
 
323
 
324
-- same game again for sine and cosine at the same time. 
325
-- Does not take more ROM bits, the ROM is just split in two
326
-- for the first and second part of the address range.
327
 
328
 
329
library ieee;
330
use ieee.std_logic_1164.all;
331
use ieee.numeric_std.all;
332
use ieee.math_real.all;
333
 
334
 
335
 
336
entity sincostab is
337
   generic (
338
      pipestages: integer range 0 to 10
339
   );
340
   port (
341
      clk:        in  std_logic;
342
      ce:         in  std_logic := '1';
343
      rst:        in  std_logic := '0';
344
 
345
      theta:      in  unsigned;
346
      sine:       out signed;
347
      cosine:     out signed
348
   );
349
end entity sincostab;
350
 
351
 
352
 
353
architecture rtl of sincostab is
354
 
355
type delaytable is array(0 to 10) of integer;
356
 
357
constant in_pipe:  delaytable := ( 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1);
358
constant adr_pipe: delaytable := ( 0, 0, 0, 1, 1, 1, 1, 2, 2, 3, 3);
359
constant rom_pipe: delaytable := ( 0, 1, 1, 1, 2, 2, 2, 2, 3, 3, 4);
360
constant out_pipe: delaytable := ( 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 2);
361
 
362
--    total delay                  0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10
363
 
364
 
365
 
366
constant verbose:              boolean := true;
367
 
368
signal   piped_theta:          unsigned(theta'range);   -- pipelined input
369
 
370
signal   ras:                  unsigned(theta'high-2 downto 0); -- rom address for sine
371
signal   rac:                  unsigned(theta'high-2 downto 0); -- rom address for cos
372
 
373
signal   pras:                 unsigned(theta'high-2 downto 0); -- pipelined rom addresses
374
signal   prac:                 unsigned(theta'high-2 downto 0);
375
 
376
signal   piped_abs_sin:        unsigned(sine'high-1 downto 0);
377
signal   piped_abs_cos:        unsigned(cosine'high-1 downto 0);
378
 
379
signal   piped_invert_the_sin: std_logic;
380
signal   sig_sin:              signed(sine'range);
381
 
382
signal   invert_the_cos:       std_logic;
383
signal   piped_invert_the_cos: std_logic;
384
signal   sig_cos:              signed(cosine'range);
385
 
386
----------------------------------------------------------------------------------------------------
387
--
388
-- The sine lookup table and how it is initialized.
389
--
390
--
391
-- the sine lookup table is unsigned because we store one quarter wave only.
392
 
393
type sintab is array (0 to (2**(theta'length-3)) -1) of unsigned(sine'length-2 downto 0);
394
 
395
 
396
 
397
function sine_at_middle_of_bin( bin: integer; rom_words: integer) return real is
398
  variable x:  real;
399
begin
400
    x := (real(bin) + 0.5) * MATH_PI / 2.0 / real(rom_words);
401
    return sin(x);
402
end;
403
 
404
 
405
 
406
-- initialize sine table for 0 to 44 degrees
407
 
408
function init_sin1(verbose: boolean; rom_words: integer; bits_per_uword: integer) return sintab is
409
  variable s: sintab;
410
  variable y: real;
411
  constant scalefactor: real := real((2 ** bits_per_uword)-1);
412
 
413
  begin
414
     if verbose
415
     then
416
       report "initializing sine table:    rom_words = "
417
            & integer'image(rom_words)
418
            & "   rom bits per unsigned word = "
419
            & integer'image(bits_per_uword)
420
            & "    scalefactor = "
421
            & real'image(scalefactor);
422
     end if;
423
 
424
     for i in 0 to (rom_words/2)-1 loop
425
       y := sine_at_middle_of_bin(i, rom_words);
426
       s(i) := to_unsigned(integer( round(y * scalefactor )), bits_per_uword);
427
 
428
       if verbose
429
       then
430
         report "i = "                & integer'image(i)
431
            & "  exact sin y = "      & real'image(y)
432
            & "  exact scaled y = "   & real'image(y*scalefactor)
433
            & "  rounded int s(i) = " & integer'image( to_integer(s(i)))
434
            & "  error = "            & real'image(y*scalefactor - real(to_integer(s(i))))
435
            ;
436
        end if;
437
      end loop;
438
 
439
  return s;
440
end function init_sin1;
441
 
442
 
443
 
444
-- initialize sine table for 45 to 89 degrees
445
 
446
function init_sin2(verbose: boolean; rom_words: integer; bits_per_uword: integer) return sintab is
447
  variable s: sintab;
448
  variable y: real;
449
  constant scalefactor: real := real((2 ** bits_per_uword)-1);
450
 
451
  begin
452
     if verbose
453
     then
454
       report "initializing sine table:    rom_words = "
455
            & integer'image(rom_words)
456
            & "   rom bits per unsigned word = "
457
            & integer'image(bits_per_uword)
458
            & "    scalefactor = "
459
            & real'image(scalefactor);
460
     end if;
461
 
462
     for i in rom_words/2 to rom_words-1 loop
463
       y := sine_at_middle_of_bin(i, rom_words);
464
       s(i - (rom_words/2)) := to_unsigned(integer( round(y * scalefactor )), bits_per_uword);
465
 
466
       if verbose
467
       then
468
         report "i = "                & integer'image(i)
469
            & "  exact sin y = "      & real'image(y)
470
            & "  exact scaled y = "   & real'image(y*scalefactor)
471
            & "  rounded int s(i) = " & integer'image( to_integer(s(i-rom_words/2)))
472
            & "  error = "            & real'image(y*scalefactor - real(to_integer(s(i-rom_words/2))))
473
            ;
474
        end if;
475
      end loop;
476
 
477
  return s;
478
end function init_sin2;
479
 
480
 
481
 
482
 
483
 
484
-- The 'constant' is important here.  It tells the synthesizer that 
485
-- all the computations can be done at compile time.
486
 
487
constant rom1:  sintab := init_sin1(verbose, 2 ** (theta'length-2), sine'length-1);
488
constant rom2:  sintab := init_sin2(verbose, 2 ** (theta'length-2), sine'length-1);
489
 
490
----------------------------------------------------------------------------------------------------
491
--
492
-- convert phase input to ROM address.
493
--
494
-- theta has an address range from 0 to a little less than 2 Pi. (full circle)
495
-- "a little less than 2 pi" is represented as all ones.
496
-- The look up table goes only from 0 to a little less than 1/2 Pi. (quarter circle)
497
-- The two highest bits of theta determine only the quadrant
498
-- and are implemented by address mirroring and sign change.
499
 
500
-- address mirroring    hi bits      sine    cosine
501
-- 1st quarter wave     00           no      yes
502
-- 2nd quarter wave     01           yes     no
503
-- 3rd quarter wave     10           no      yes
504
-- 4th quarter wave     11           yes     no
505
 
506
 
507
function reduce_sin_address (theta: unsigned) return unsigned is
508
 
509
   variable quarterwave_address: unsigned(theta'high-2 downto 0);
510
   variable mirrored:            boolean;
511
   variable forward_address:     unsigned(theta'high-2 downto 0);
512
   variable backward_address:    unsigned(theta'high-2 downto 0);
513
   constant verbose:             boolean := false;
514
 
515
begin
516
 
517
  -- the highest bit makes no difference on the abs. value of the sine
518
  -- it just negates the value if set. This is done on the output side
519
  -- after the ROM.
520
 
521
  mirrored := ((theta(theta'high) = '0') and (theta(theta'high-1) = '1'))  -- 2nd quadr.
522
           or ((theta(theta'high) = '1') and (theta(theta'high-1) = '1')); -- 4th quadr.
523
 
524
  forward_address    := theta(theta'high-2 downto 0);
525
  backward_address   := unsigned(-1 -signed( theta(theta'high-2 downto 0)));
526
 
527
  if mirrored then
528
    quarterwave_address := backward_address;
529
  else
530
    quarterwave_address := forward_address;
531
  end if;
532
 
533
  if verbose
534
  then
535
    report "sin theta = "               & integer'image(to_integer(theta))
536
         & "   forward: "               & integer'image(to_integer(forward_address))
537
         & "   backward: "              & integer'image(to_integer(backward_address))
538
         & "   Quarterwave address = "  & integer'image(to_integer(quarterwave_address))
539
         & "   mirrored: "              & boolean'image(mirrored);
540
  end if;
541
  return quarterwave_address;
542
end reduce_sin_address;
543
 
544
 
545
 
546
function reduce_cos_address (theta: unsigned) return unsigned is
547
 
548
   variable quarterwave_address: unsigned(theta'high-2 downto 0);
549
   variable mirrored:            boolean;
550
   variable forward_address:     unsigned(theta'high-2 downto 0);
551
   variable backward_address:    unsigned(theta'high-2 downto 0);
552
   constant verbose:             boolean := false;
553
 
554
begin
555
 
556
  mirrored := ((theta(theta'high) = '0') and (theta(theta'high-1) = '0'))  -- 1st quadr.
557
           or ((theta(theta'high) = '1') and (theta(theta'high-1) = '0')); -- 3th quadr.
558
 
559
  forward_address    := theta(theta'high-2 downto 0);
560
  backward_address   := unsigned(-1 -signed( theta(theta'high-2 downto 0)));
561
 
562
  if mirrored then
563
    quarterwave_address := backward_address;
564
  else
565
    quarterwave_address := forward_address;
566
  end if;
567
 
568
  if verbose
569
  then
570
    report "cos theta = "               & integer'image(to_integer(theta))
571
         & "   forward: "               & integer'image(to_integer(forward_address))
572
         & "   backward: "              & integer'image(to_integer(backward_address))
573
         & "   Quarterwave address = "  & integer'image(to_integer(quarterwave_address))
574
         & "   mirrored: "              & boolean'image(mirrored);
575
  end if;
576
  return quarterwave_address;
577
end reduce_cos_address;
578
 
579
 
580
 
581
----------------------------------------------------------------------------------------------------
582
 
583
BEGIN
584
 
585
 
586
-- this assertion might be relaxed, but I see no justification
587
-- for the extra testing.
588
 
589
assert sine'length = cosine'length
590
  report "sincostab: sine and cosine length do not match: "
591
       & integer'image(sine'length)
592
       & " vs. "
593
       & integer'image(cosine'length)
594
  severity error;
595
 
596
 
597
----------------------------------------------------------------------------------------------------
598
--
599
-- input delay stage
600
 
601
u_adr:  entity work.unsigned_pipestage
602
generic map (
603
  n_stages      => in_pipe(pipestages)
604
)
605
Port map (
606
  clk => clk,
607
  ce  => ce,
608
  rst => rst,
609
 
610
  i   => theta,
611
  o   => piped_theta
612
);
613
 
614
----------------------------------------------------------------------------------------------------
615
-- propagate the information whether we will have to invert the output
616
 
617
u_invs: entity work.sl_pipestage
618
generic map (
619
  n_stages      => adr_pipe(pipestages) + rom_pipe(pipestages)
620
)
621
Port map (
622
  clk => clk,
623
  ce  => ce,
624
  rst => rst,
625
 
626
  i   => std_logic(piped_theta(piped_theta'high)),   -- sine is neg. for 2nd half of cycle
627
  o   => piped_invert_the_sin
628
);
629
 
630
 
631
invert_the_cos <= std_logic(piped_theta(piped_theta'high) xor piped_theta(piped_theta'high-1));
632
 
633
u_invc: entity work.sl_pipestage
634
generic map (
635
  n_stages      => adr_pipe(pipestages) + rom_pipe(pipestages)
636
)
637
Port map (
638
  clk => clk,
639
  ce  => ce,
640
  rst => rst,
641
 
642
  i   => invert_the_cos,
643
  o   => piped_invert_the_cos
644
);
645
 
646
----------------------------------------------------------------------------------------------------
647
--
648
-- address folding with potential pipe stage
649
--
650
 
651
ras <= reduce_sin_address(piped_theta);
652
rac <= reduce_cos_address(piped_theta);
653
 
654
u_pip_adrs:     entity work.unsigned_pipestage
655
generic map (
656
  n_stages      => adr_pipe(pipestages)
657
)
658
Port map (
659
  clk => clk,
660
  ce  => ce,
661
  rst => rst,
662
 
663
  i   => ras,
664
  o   => pras
665
);
666
 
667
 
668
u_pip_adrc:     entity work.unsigned_pipestage
669
generic map (
670
  n_stages      => adr_pipe(pipestages)
671
)
672
Port map (
673
  clk => clk,
674
  ce  => ce,
675
  rst => rst,
676
 
677
  i   => rac,
678
  o   => prac
679
);
680
 
681
 
682
 
683
--------------------------------------------------------------------------------
684
--
685
-- ROM access
686
--
687
 
688
distrib_rom: if rom_pipe(pipestages) = 0
689
generate  -- a distributed ROM if no latency is allowed
690
begin
691
 
692
  piped_abs_sin <= rom1(to_integer(pras(pras'high-1 downto 0)))
693
                when pras(pras'high) = '0' else
694
                   rom2(to_integer(pras(pras'high-1 downto 0)));
695
 
696
  piped_abs_cos <= rom1(to_integer(prac(prac'high-1 downto 0)))
697
                when prac(prac'high) = '0' else
698
                   rom2(to_integer(prac(prac'high-1 downto 0)));
699
 
700
end generate;
701
 
702
 
703
 
704
block_rom: if rom_pipe(pipestages) > 0
705
generate
706
 
707
  signal   rom_out1: unsigned(sine'high-1 downto 0);
708
  signal   rom_out2: unsigned(sine'high-1 downto 0);
709
 
710
  signal   abs_sin:  unsigned(sine'high-1 downto 0);  -- abs of sine at mux output
711
  signal   abs_cos:  unsigned(sine'high-1 downto 0);
712
 
713
begin
714
  -- Xilinx XST 12.3 needs a clocked process to infer BlockRam/ROM. 
715
  -- It does not see that it could generate block ROM if it propagated a pipestage. 
716
 
717
  u_rom: process(clk) is
718
  begin
719
    if rising_edge(clk)
720
    then
721
      rom_out1 <= rom1(to_integer(pras(pras'high-1 downto 0)));
722
      rom_out2 <= rom2(to_integer(prac(prac'high-1 downto 0)));
723
    end if;
724
  end process;
725
 
726
  abs_sin <= rom_out1 when pras(pras'high) = '0'
727
        else rom_out2;
728
 
729
  abs_cos <= rom_out1 when prac(prac'high) = '0'
730
        else rom_out2;
731
 
732
 
733
  -- more rom pipeline stages when needed
734
  u_rom_dly_s:  entity work.unsigned_pipestage
735
  generic map (
736
    n_stages    => rom_pipe(pipestages)-1          -- 0 is allowed.
737
  )
738
  Port map (
739
    clk => clk,
740
    ce  => ce,
741
    rst => rst,
742
 
743
    i   => abs_sin,
744
    o   => piped_abs_sin
745
  );
746
 
747
 
748
  u_rom_dly_c:  entity work.unsigned_pipestage
749
  generic map (
750
    n_stages    => rom_pipe(pipestages)-1
751
  )
752
  Port map (
753
    clk => clk,
754
    ce  => ce,
755
    rst => rst,
756
 
757
    i   => abs_cos,
758
    o   => piped_abs_cos
759
  );
760
 
761
end generate;
762
 
763
 
764
--------------------------------------------------------------------------------
765
--
766
-- conditional output inversion
767
-- table entries are unsigned. Convert them to signed and make them one bit larger
768
-- so that we have a home for the sign bit.
769
 
770
   sig_sin <= -signed(resize(piped_abs_sin, sine'length)) when piped_invert_the_sin = '1'
771
          else
772
               signed(resize(piped_abs_sin, sine'length));
773
 
774
 
775
   sig_cos <= -signed(resize(piped_abs_cos, cosine'length)) when piped_invert_the_cos = '1'
776
          else
777
               signed(resize(piped_abs_cos, cosine'length));
778
 
779
 
780
 
781
u_os:   entity work.signed_pipestage
782
generic map (
783
  n_stages      => out_pipe(pipestages)
784
)
785
Port map (
786
  clk => clk,
787
  ce  => ce,
788
  rst => rst,
789
 
790
  i   => sig_sin,
791
  o   => sine
792
);
793
 
794
 
795
u_oc:   entity work.signed_pipestage
796
generic map (
797
  n_stages      => out_pipe(pipestages)
798
)
799
Port map (
800
  clk => clk,
801
  ce  => ce,
802
  rst => rst,
803
 
804
  i   => sig_cos,
805
  o   => cosine
806
);
807
 
808
END ARCHITECTURE rtl;
809
 
810
-------------------------------------------------------------------------------
811
-- That could be driven further to 4 or even 8 phases, so that we could support
812
-- downconverters for 4 and 8 lane GigaSample ADCs with polyphase filters to
813
-- combine the lanes, without spending more on the ROM. It remains to be seen 
814
-- if the resulting routing congestion is worth the ROM bits conserved. 
815
-- But then, at these clock rates, the neccessary number of bits per bus shrinks 
816
-- because ADC makers have their own little problems, too ;-)
817
-- And it has the potential drawback for very fast frequency chirps, that the
818
-- instantaneous frequency jumps for groups of 8 samples at a time.
819
-- (Ignore these musings if you are in math or robotics!)

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.