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

Subversion Repositories yac

[/] [yac/] [trunk/] [rtl/] [vhdl/] [cordic_iterative_wb.vhd] - Blame information for rev 5

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 5 feddischso
----------------------------------------------------------------------------
2
----                                                                    ----
3
----  File           : cordic_iterative_wb.vhd                         ----
4
----  Project        : YAC (Yet Another CORDIC Core)                    ----
5
----  Creation       : Feb. 2014                                        ----
6
----  Limitations    :                                                  ----
7
----  Synthesizer    :                                                  ----
8
----  Target         :                                                  ----
9
----                                                                    ----
10
----  Author(s):     : Christian Haettich                               ----
11
----  Email          : feddischson@opencores.org                        ----
12
----                                                                    ----
13
----                                                                    ----
14
-----                                                                  -----
15
----                                                                    ----
16
----  Description                                                       ----
17
----        wb bus interface for the YAC                                ----
18
----                                                                    ----
19
----                                                                    ----
20
----                                                                    ----
21
-----                                                                  -----
22
----                                                                    ----
23
----     Memory organization:                                           ----
24
----  -----------------------------------------------------------       ----
25
----  |   word        |     description                         |       ----
26
----  |   index       |                                         |       ----
27
----  -----------------------------------------------------------       ----
28
----  |             0 |   x_0             \                     |       ----
29
----  |             1 |   y_0              \  1'st entry        |       ----
30
----  |             2 |   a_0              /                    |       ----
31
----  |             3 |   mode_0          /                     |       ----
32
----  |             4 |   x_1             \                     |       ----
33
----  |             5 |   y_1              \  2'nd entry        |       ----
34
----  |             6 |   a_1              /                    |       ----
35
----  |             7 |   mode_1          /                     |       ----
36
----  |             8 |   .                                     |       ----
37
----  |               |   ...                                   |       ----
38
----  | N_ENTRIES*4-4 |   x_n             \                     |       ----
39
----  | N_ENTRIES*4-3 |   y_n              \  n'th entry        |       ----
40
----  | N_ENTRIES*4-2 |   a_n              /                    |       ----
41
----  | N_ENTRIES*4-1 |   mode_n          /                     |       ----
42
----  | N_ENTRIES*4   |   status-register                       |       ----
43
----  -----------------------------------------------------------       ----
44
----                                                                    ----
45
----                                                                    ----
46
----      Status register bit fields:                                   ----
47
----                                                                    ----
48
----       bit 0: ==>> start/idle flag:                                 ----
49
----       ------------------------------                               ----
50
----                  write 1: start                                    ----
51
----                  read  1: busy                                     ----
52
----                  read  0: idle                                     ----
53
----              the flag is set by SW and cleared automatically       ----
54
----              after processing.                                     ----
55
----                                                                    ----
56
----       bit 1: ==>> IRQ flag:                                        ----
57
----       ------------------------------                               ----
58
----                  write 1: sets the IRQ                             ----
59
----                  write 0: clears the IRQ                           ----
60
----              the flag is set automatically by HW and is mapped     ----
61
----              to irq_o. The software can clear the flag/irq by      ----
62
----              writing a 0 to this bit.                              ----
63
----                                                                    ----
64
----                                                                    ----
65
----                                                                    ----
66
----       bit 16...ceil(log2(N_ENTRIES)): ==>> item-count              ----
67
----       -----------------------------------------------              ----
68
----           defines, how much items are processed,                   ----
69
----           the processing works from the higher part to the lower   ----
70
----           part of the memory.                                      ---
71
----                                                                    ----
72
----                                                                    ----
73
----                                                                    ----
74
----                                                                    ----
75
---------                                                       ------------
76
----  TODO:                                                             ----
77
----        - further testing                                           ----
78
----        - err_o: error output generation                            ----
79
----                                                                    ----
80
----                                                                    ----
81
----                                                                    ----
82
----                                                                    ----
83
----------------------------------------------------------------------------
84
----                                                                    ----
85
----                  Copyright Notice                                  ----
86
----                                                                    ----
87
---- This file is part of YAC - Yet Another CORDIC Core                 ----
88
---- Copyright (c) 2014, Author(s), All rights reserved.                ----
89
----                                                                    ----
90
---- YAC is free software; you can redistribute it and/or               ----
91
---- modify it under the terms of the GNU Lesser General Public         ----
92
---- License as published by the Free Software Foundation; either       ----
93
---- version 3.0 of the License, or (at your option) any later version. ----
94
----                                                                    ----
95
---- YAC is distributed in the hope that it will be useful,             ----
96
---- but WITHOUT ANY WARRANTY; without even the implied warranty of     ----
97
---- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU  ----
98
---- Lesser General Public License for more details.                    ----
99
----                                                                    ----
100
---- You should have received a copy of the GNU Lesser General Public   ----
101
---- License along with this library. If not, download it from          ----
102
---- http://www.gnu.org/licenses/lgpl                                   ----
103
----                                                                    ----
104
----------------------------------------------------------------------------
105
 
106
 
107
 
108
library ieee;
109
library std;
110
use std.textio.all;
111
use ieee.std_logic_1164.ALL;
112
use ieee.numeric_std.ALL;
113
use ieee.std_logic_textio.all; -- I/O for logic types
114
use work.cordic_pkg.ALL;
115
 
116
 
117
entity cordic_iterative_wb is
118
 generic(
119
   WB_ADR_WIDTH   : natural := 32; -- wishbone address bus width
120
   N_ENTRIES      : natural := 16; -- number of calculation entries, 
121
                                   -- which can be stored
122
   A_WIDTH        : natural := 12; -- \  
123
   XY_WIDTH       : natural := 12; --  | Cordic setup
124
   GUARD_BITS     : natural := 2;  --  |  
125
   RM_GAIN        : natural := 3   -- /
126
 );
127
 port(
128
   clk_i :  in std_logic;
129
   rst_i :  in std_logic;
130
   dat_i :  in std_logic_vector( 32-1 downto 0 );
131
   dat_o : out std_logic_vector( 32-1 downto 0 );
132
   adr_i :  in std_logic_vector( WB_ADR_WIDTH-1 downto 0 );
133
   we_i  :  in std_logic;
134
   sel_i :  in std_logic_vector( 4-1 downto 0 );
135
   cyc_i :  in std_logic;
136
   stb_i :  in std_logic;
137
   ack_o : out std_logic;
138
   cti_i :  in std_logic_vector( 3-1 downto 0 );
139
   bte_i :  in std_logic_vector( 2-1 downto 0 );
140
   irq_o : out std_logic
141
 );
142
 end entity;
143
 
144
architecture IMP of cordic_iterative_wb is
145
 
146
  constant STATUS_REG_I   : natural := N_ENTRIES*4;
147
 
148
 
149
 
150
  function ceil_log2(N: natural) return positive is
151
  begin
152
     if N <= 2 then
153
        return 1;
154
     else
155
        if N mod 2 = 0 then
156
           return 1 + ceil_log2( N/2 );
157
        else
158
           return 1 + ceil_log2( (N+1) / 2 );
159
        end if;
160
     end if;
161
  end;
162
 
163
  constant MEM_SIZE : natural := 32;
164
  --
165
  -- memory blocks:
166
  --    N_ENTRIES * ( x, y, a, mode) + status-register
167
  --
168
  type mem_t  is array ( 0 to 4*N_ENTRIES+1-1 ) of std_logic_vector( MEM_SIZE-1 downto 0 );
169
  signal MEM : mem_t;
170
 
171
  -- address size  (in words)
172
  constant ADR_WIDTH : natural := ceil_log2( 4*N_ENTRIES+1 );
173
 
174
  type B3_TRANS_T is ( WB_BURST, WB_NO_BURST );
175
  signal b3_trans       : B3_TRANS_T;
176
  signal addr           : std_logic_vector( ADR_WIDTH-1  downto 0 );
177
  signal addr_burst     : std_logic_vector( ADR_WIDTH-1  downto 0 );
178
  signal cti_r          : std_logic_vector( cti_i'range );
179
  signal bte_r          : std_logic_vector( bte_i'range );
180
  signal dat_o_tmp      : std_logic_vector( dat_o'range );
181
  signal wr_data        : std_logic_vector( dat_i'range );
182
  signal ack_r          : std_logic;
183
  signal ack            : std_logic;
184
 
185
  signal burst_start   : std_logic;
186
  signal burst_end     : std_logic;
187
 
188
 
189
 
190
  component cordic_iterative_int is
191
  generic(
192
     XY_WIDTH    : natural := 12;
193
     A_WIDTH     : natural := 12;
194
     GUARD_BITS  : natural :=  2;
195
     RM_GAIN     : natural :=  4
196
         );
197
  port(
198
     clk, rst  : in  std_logic;
199
     en        : in  std_logic;
200
     start     : in  std_logic;
201
     done      : out std_logic;
202
     mode_i    : in  std_logic_vector( 4-1 downto 0 );
203
     x_i       : in  std_logic_vector( XY_WIDTH-1  downto 0 );
204
     y_i       : in  std_logic_vector( XY_WIDTH-1  downto 0 );
205
     a_i       : in  std_logic_vector( A_WIDTH+2-1 downto 0 );
206
     x_o       : out std_logic_vector( XY_WIDTH+GUARD_BITS-1  downto 0 );
207
     y_o       : out std_logic_vector( XY_WIDTH+GUARD_BITS-1  downto 0 );
208
     a_o       : out std_logic_vector( A_WIDTH+2-1 downto 0 )
209
      );
210
  end component cordic_iterative_int;
211
  signal cordic_en      : std_logic;
212
  signal cordic_start   : std_logic;
213
  signal cordic_done    : std_logic;
214
  signal cordic_mode_i  : std_logic_vector( 4-1 downto 0 );
215
  signal cordic_x_i     : std_logic_vector( XY_WIDTH-1  downto 0 );
216
  signal cordic_y_i     : std_logic_vector( XY_WIDTH-1  downto 0 );
217
  signal cordic_a_i     : std_logic_vector( A_WIDTH+2-1 downto 0 );
218
  signal cordic_x_o     : std_logic_vector( XY_WIDTH+GUARD_BITS-1  downto 0 );
219
  signal cordic_y_o     : std_logic_vector( XY_WIDTH+GUARD_BITS-1  downto 0 );
220
  signal cordic_a_o     : std_logic_vector( A_WIDTH+2-1 downto 0 );
221
 
222
 
223
  type state_T_st  is (ST_IDLE, ST_START, ST_WAIT);
224
  type state_T     is
225
  record
226
    st    : state_T_st;
227
    cnt   : unsigned( ceil_log2( N_ENTRIES ) -1 downto 0 );
228
  end record;
229
  signal state : state_T;
230
 
231
 
232
begin
233
 
234
 
235
  -- start of burst signal
236
  burst_start <= '1' when ( cti_i = "001" or cti_i = "010" )
237
                              and stb_i = '1'
238
                              and b3_trans /= WB_BURST
239
                  else '0';
240
 
241
  -- end of burst signal
242
  burst_end   <= '1' when cti_i = "111"
243
                              and stb_i = '1'
244
                              and b3_trans = WB_BURST
245
                              and ack      = '1'
246
                  else '0';
247
 
248
 
249
 
250
 
251
  ------
252
  --  Burst address generation: this depends on the number of entries
253
  --  and the internal address bus width
254
  --
255
  BURST_GEN_ALL : if ADR_WIDTH > 4 generate
256
  addr_burst <=                              std_logic_vector(  unsigned( addr               ) + 1 ) when bte_r = "00" else
257
                addr( addr'high downto 2 ) & std_logic_vector(  unsigned( addr( 1 downto 0 ) ) + 1 ) when bte_r = "01" else
258
                addr( addr'high downto 3 ) & std_logic_vector(  unsigned( addr( 2 downto 0 ) ) + 1 ) when bte_r = "10" else
259
                addr( addr'high downto 4 ) & std_logic_vector(  unsigned( addr( 3 downto 0 ) ) + 1 ) when bte_r = "11";
260
 
261
  end generate;
262
 
263
 
264
  BURST_GEN_4 : if ADR_WIDTH = 4 generate
265
  addr_burst <=                              std_logic_vector(  unsigned( addr               ) + 1 ) when bte_r = "00" else
266
                addr( addr'high downto 2 ) & std_logic_vector(  unsigned( addr( 1 downto 0 ) ) + 1 ) when bte_r = "01" else
267
                addr( addr'high downto 3 ) & std_logic_vector(  unsigned( addr( 2 downto 0 ) ) + 1 ) when bte_r = "10" else
268
                                             std_logic_vector(  unsigned( addr( 3 downto 0 ) ) + 1 ) when bte_r = "11";
269
  end generate;
270
 
271
 
272
  BURST_GEN_3 : if ADR_WIDTH = 3 generate
273
  addr_burst <=                              std_logic_vector(  unsigned( addr               ) + 1 ) when bte_r = "00" else
274
                addr( addr'high downto 2 ) & std_logic_vector(  unsigned( addr( 1 downto 0 ) ) + 1 ) when bte_r = "01" else
275
                                             std_logic_vector(  unsigned( addr( 2 downto 0 ) ) + 1 ) when bte_r = "10";
276
  end generate;
277
 
278
 
279
  BURST_GEN_2 : if ADR_WIDTH = 2 generate
280
  addr_burst <=                              std_logic_vector(  unsigned( addr               ) + 1 ) when bte_r = "00" else
281
                                             std_logic_vector(  unsigned( addr( 1 downto 0 ) ) + 1 ) when bte_r = "01";
282
  end generate;
283
 
284
 
285
  ------
286
  --
287
  --  wishbone bus transaction handling
288
  --    - ack generation
289
  --    - burst handling
290
  --    - address handling
291
  --
292
  p : process( clk_i, rst_i )
293
 
294
  begin
295
 
296
    if clk_i'event and clk_i='1' then
297
      if rst_i = '1' then
298
        addr           <= ( others => '0' );
299
        b3_trans       <= WB_NO_BURST;
300
        ack_r          <= '0';
301
      else
302
 
303
        cti_r <= cti_i;
304
        bte_r <= bte_i;
305
 
306
 
307
        if    burst_start = '1' then
308
          addr  <= adr_i( ADR_WIDTH+2-1 downto 2 );
309
 
310
        elsif cti_r = "010" and  ack = '1' and b3_trans = WB_BURST then
311
          addr <=  addr_burst;
312
        else
313
          addr  <= adr_i( ADR_WIDTH+2-1 downto 2 );
314
        end if;
315
 
316
 
317
        if    burst_start = '1' then
318
 
319
          -- start of burst
320
          b3_trans    <= WB_BURST;
321
 
322
        elsif burst_end = '1' then
323
 
324
          -- end of burst
325
          b3_trans <= WB_NO_BURST;
326
 
327
        elsif b3_trans = WB_BURST then
328
 
329
          -- during burst
330
 
331
        end if;
332
 
333
 
334
 
335
        -- ack generation
336
        if cyc_i  = '1' then
337
 
338
          if cti_i = "000" then
339
 
340
            if stb_i = '1' then
341
              ack_r <= not ack_r;
342
            end if;
343
 
344
          elsif cti_i = "010" or cti_i = "001" then
345
            ack_r <= stb_i;
346
 
347
          elsif cti_i = "111" then
348
            if ack_r = '0' then
349
              ack_r <= '1';
350
            else
351
              ack_r <= '0';
352
            end if;
353
 
354
          end if;
355
        else
356
          ack_r <= '0';
357
        end if;
358
 
359
      end if;
360
    end if;
361
 
362
  end process;
363
 
364
 
365
  ack <= ack_r and stb_i;
366
  ack_o <= ack;
367
 
368
  wr_data( 31 downto 24 ) <=  dat_i( 31 downto 24 ) when sel_i(3) = '1' else dat_o_tmp( 31 downto 24 );
369
  wr_data( 23 downto 16 ) <=  dat_i( 23 downto 16 ) when sel_i(2) = '1' else dat_o_tmp( 23 downto 16 );
370
  wr_data( 15 downto  8 ) <=  dat_i( 15 downto 8  ) when sel_i(1) = '1' else dat_o_tmp( 15 downto 8  );
371
  wr_data(  7 downto  0 ) <=  dat_i( 7  downto 0  ) when sel_i(0) = '1' else dat_o_tmp( 7  downto 0  );
372
 
373
 
374
  --dat_o_tmp( dat_o_tmp'high downto MEM_SIZE ) <= ( others => '0' );
375
  dat_o_tmp( MEM_SIZE-1 downto 0 ) <= MEM( to_integer( unsigned( addr ) ) );
376
  dat_o <= dat_o_tmp;
377
 
378
 
379
 
380
 
381
 
382
  -- 
383
  --  this includes a small state machine, the IRQ generation
384
  --  and the memory handling
385
  -- 
386
  wr_p : process( clk_i, rst_i )
387
    variable MEM_START : integer;
388
  begin
389
 
390
    if clk_i'event and clk_i='1' then
391
      if rst_i = '1' then
392
        MEM <= ( others => ( others => '0' ) );
393
        state <= ( st  => ST_IDLE,
394
                    cnt => ( others => '0' ) );
395
 
396
        cordic_start  <= '0';
397
        cordic_x_i    <= ( others => '0' );
398
        cordic_y_i    <= ( others => '0' );
399
        cordic_a_i    <= ( others => '0' );
400
        cordic_mode_i <= ( others => '0' );
401
 
402
      else
403
 
404
        -- default values (get changed below)
405
        cordic_start    <= '0';
406
        cordic_x_i      <= ( others => '0' );
407
        cordic_y_i      <= ( others => '0' );
408
        cordic_a_i      <= ( others => '0' );
409
        cordic_mode_i   <= ( others => '0' );
410
 
411
 
412
 
413
        -- writing to memory
414
        if we_i = '1' and  ack = '1' then
415
          MEM( to_integer( unsigned( addr ) ) ) <= wr_data( MEM_SIZE-1 downto 0 );
416
        end if;
417
 
418
 
419
 
420
 
421
        -- start of all calculations
422
        if MEM( STATUS_REG_I )(0) = '1' and state.st = ST_IDLE then
423
          state.st   <= ST_START;
424
          state.cnt  <= unsigned( MEM( STATUS_REG_I )( 16+state.cnt'length-1 downto 16 ) )-1;
425
        end if;
426
 
427
 
428
        -- start of a single cordic calculation
429
        if state.st = ST_START then
430
          MEM_START := to_integer( state.cnt & "00" ); -- state.cnt * 4
431
          cordic_x_i    <= MEM( MEM_START+0 )( cordic_x_i'range );
432
          cordic_y_i    <= MEM( MEM_START+1 )( cordic_y_i'range );
433
          cordic_a_i    <= MEM( MEM_START+2 )( cordic_a_i'range );
434
          cordic_mode_i <= MEM( MEM_START+3 )( cordic_mode_i'range );
435
          cordic_start  <= '1';
436
 
437
          state.st     <= ST_WAIT;
438
        end if;
439
 
440
 
441
        -- single cordic calculation is done:
442
        -- save the result and start the next one or
443
        -- go back to idle
444
        if state.st = ST_WAIT and cordic_done = '1' then
445
          MEM_START := to_integer( state.cnt & "00" ); -- state.cnt * 4
446
          MEM( MEM_START+0 ) <= ( others => '0' );
447
          MEM( MEM_START+1 ) <= ( others => '0' );
448
          MEM( MEM_START+2 ) <= ( others => '0' );
449
          MEM( MEM_START+0 )( cordic_x_o'range ) <= cordic_x_o;
450
          MEM( MEM_START+1 )( cordic_y_o'range ) <= cordic_y_o;
451
          MEM( MEM_START+2 )( cordic_a_o'range ) <= cordic_a_o;
452
 
453
 
454
          if state.cnt = 0 then
455
 
456
            -- go back to IDLE
457
            state.st <= ST_IDLE;
458
 
459
            -- clear busy flag
460
            MEM( STATUS_REG_I )( 0 ) <= '0';
461
 
462
            -- set IRQ flag
463
            MEM( STATUS_REG_I )( 1 ) <= '1';
464
          else
465
            state.st <= ST_START;
466
            state.cnt <= state.cnt-1;
467
          end if;
468
 
469
        end if;
470
 
471
      end if;
472
    end if;
473
  end process;
474
 
475
  -- disable the cordic when there is nothing to do
476
  cordic_en <= '0' when state.st = ST_IDLE else '1';
477
 
478
  irq_o <= MEM( STATUS_REG_I )( 1 );
479
 
480
 
481
 
482
  -- the cordic instance
483
  cordic_inst : cordic_iterative_int
484
  generic map (
485
     XY_WIDTH       => XY_WIDTH  ,
486
     A_WIDTH        => A_WIDTH   ,
487
     GUARD_BITS     => GUARD_BITS,
488
     RM_GAIN        => RM_GAIN
489
         )
490
  port map(
491
     clk         => clk_i           ,
492
     rst         => rst_i           ,
493
     en          => cordic_en       ,
494
     start       => cordic_start    ,
495
     done        => cordic_done     ,
496
     mode_i      => cordic_mode_i   ,
497
     x_i         => cordic_x_i      ,
498
     y_i         => cordic_y_i      ,
499
     a_i         => cordic_a_i      ,
500
     x_o         => cordic_x_o      ,
501
     y_o         => cordic_y_o      ,
502
     a_o         => cordic_a_o
503
      );
504
 
505
 
506
 
507
 
508
 
509
 
510
end architecture IMP;

powered by: WebSVN 2.1.0

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