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

Subversion Repositories heap_sorter

[/] [heap_sorter/] [trunk/] [standard_version/] [src/] [sorter_ctrl.vhd] - Blame information for rev 7

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

Line No. Rev Author Line
1 2 wzab
-------------------------------------------------------------------------------
2
-- Title      : Sorting node controller for heap-sorter
3
-- Project    : heap-sorter
4
-------------------------------------------------------------------------------
5
-- File       : sorter_ctrl.vhd
6
-- Author     : Wojciech M. Zabolotny <wzab@ise.pw.edu.pl>
7
-- Company    : 
8
-- Created    : 2010-05-14
9 3 wzab
-- Last update: 2013-07-04
10 2 wzab
-- Platform   : 
11
-- Standard   : VHDL'93
12
-------------------------------------------------------------------------------
13
-- Description: 
14
-------------------------------------------------------------------------------
15
-- Copyright (c) 2010 Wojciech M. Zabolotny
16
-- This file is published under the BSD license, so you can freely adapt
17
-- it for your own purposes.
18
-- Additionally this design has been described in my article:
19
--    Wojciech M. Zabolotny, "Dual port memory based Heapsort implementation
20
--    for FPGA", Proc. SPIE 8008, 80080E (2011); doi:10.1117/12.905281
21
-- I'd be glad if you cite this article when you publish something based
22
-- on my design.
23
-------------------------------------------------------------------------------
24
-- Revisions  :
25
-- Date        Version  Author  Description
26
-- 2010-05-14  1.0      wzab    Created
27
-------------------------------------------------------------------------------
28
-------------------------------------------------------------------------------
29
-- The sorter controller is connected with three dual port memories.
30
-- The first dual port memory tm_... provides the "upstream data"
31
-- The second dual port memory lm_... provides the "left branch of downstream data"
32
-- The third dual port memory rm_... provides the "right branch of downstream data"
33
-- The controller is notified about availability of the new data by the
34
-- "update" signal.
35
-- However in this architecture we need to service two upstream memories!
36
-- That's because we want to save one cycle, and to be able to issue
37
--
38
-- Important feature of each controller is the ability to clear the memory
39
-- after reset.
40
-------------------------------------------------------------------------------
41
library ieee;
42
use ieee.std_logic_1164.all;
43
use ieee.numeric_std.all;
44
use ieee.std_logic_textio.all;
45
use std.textio.all;
46
library work;
47
use work.sorter_pkg.all;
48
use work.sys_config.all;
49
 
50
entity sorter_ctrl is
51
 
52
  generic (
53
    NLEVELS   : integer;                -- number of levels (max number of
54 3 wzab
                                        -- address bits
55 2 wzab
    NADDRBITS : integer                 -- number of used address bits
56
    );
57
 
58
  port (
59
    -- Top memory connections
60
    tm_din       : in  T_DATA_REC;
61
    tm_dout      : out T_DATA_REC;
62
    tm_addr      : out std_logic_vector(NLEVELS-1 downto 0);
63
    tm_we        : out std_logic;
64
    -- Left memory connections
65
    lm_din       : in  T_DATA_REC;
66
    lm_dout      : out T_DATA_REC;
67
    lm_addr      : out std_logic_vector(NLEVELS-1 downto 0);
68
    lm_we        : out std_logic;
69
    -- Right memory connections
70
    rm_din       : in  T_DATA_REC;
71
    rm_dout      : out T_DATA_REC;
72
    rm_addr      : out std_logic_vector(NLEVELS-1 downto 0);
73
    rm_we        : out std_logic;
74
    -- Upper level controller connections
75
    up_in        : in  std_logic;
76
    up_in_val    : in  T_DATA_REC;
77
    up_in_addr   : in  std_logic_vector(NLEVELS-1 downto 0);
78
    -- Upper level update notifier
79
    up_out       : out std_logic;
80
    up_out_val   : out T_DATA_REC;
81
    up_out_addr  : out std_logic_vector(NLEVELS-1 downto 0);
82
    -- Lower level controller connections
83
    low_out      : out std_logic;
84
    low_out_val  : out T_DATA_REC;
85
    low_out_addr : out std_logic_vector(NLEVELS-1 downto 0);
86
    low_in       : in  std_logic;
87
    low_in_val   : in  T_DATA_REC;
88
    low_in_addr  : in  std_logic_vector(NLEVELS-1 downto 0);
89
    -- Lower level update notifier
90
    -- System connections
91
    clk          : in  std_logic;
92
    clk_en       : in  std_logic;
93
    ready_in     : in  std_logic;
94
    ready_out    : out std_logic;       -- signals, when memory is cleared
95
                                        -- after reset
96
    rst_n        : in  std_logic);
97
end sorter_ctrl;
98
 
99
architecture sorter_ctrl_arch1 of sorter_ctrl is
100
 
101
  type T_CTRL_STATE is (CTRL_RESET, CTRL_CLEAR, CTRL_IDLE, CTRL_S1, CTRL_S0);
102
  signal ctrl_state, ctrl_state_next    : T_CTRL_STATE := CTRL_IDLE;
103
  signal addr, addr_i                   : std_logic_vector(NLEVELS-1 downto 0);
104
  signal s_low_in_addr, s_low_in_addr_i : std_logic_vector(NLEVELS-1 downto 0);
105
  signal s_up_in_addr, s_up_in_addr_i   : std_logic_vector(NLEVELS-1 downto 0);
106
  signal s_ready_out, s_ready_out_i     : std_logic;
107
  signal s_low_in, s_low_in_i           : std_logic;
108
  signal s_addr_out                     : std_logic_vector(NLEVELS-1 downto 0);
109
  signal s_tm_dout                      : T_DATA_REC;
110
  signal s_up_in_val_i, s_up_in_val     : T_DATA_REC   := DATA_REC_INIT_DATA;
111
  signal s_low_in_val_i, s_low_in_val   : T_DATA_REC   := DATA_REC_INIT_DATA;
112
 
113
 
114
  constant ADDR_MAX : std_logic_vector(NLEVELS-1 downto 0) := std_logic_vector(to_unsigned(2**NADDRBITS-1, NLEVELS));
115
 
116
begin
117
 
118
  tm_dout <= s_tm_dout;
119
-- We have the two-process state machine.
120
  p1 : process (addr, ctrl_state, lm_din, low_in, low_in_addr, low_in_val,
121
                ready_in, rm_din, s_addr_out, s_low_in, s_low_in_addr,
122
                s_low_in_val, s_ready_out, s_up_in_val, up_in, up_in_addr,
123
                up_in_val)
124
    variable rline : line;
125
    variable l_val : T_DATA_REC;
126
    variable r_val : T_DATA_REC;
127
 
128
  begin  -- process p1
129
    -- defaults
130
    ctrl_state_next <= ctrl_state;
131
    tm_we           <= '0';
132
    rm_we           <= '0';
133
    lm_we           <= '0';
134
    lm_addr         <= (others => '0');
135
    rm_addr         <= (others => '0');
136
    tm_addr         <= (others => '0');
137
    s_ready_out_i   <= s_ready_out;
138
    addr_i          <= addr;
139 3 wzab
    up_out_val      <= DATA_REC_INIT_DATA;  -- to avoid latches
140
    low_out_val     <= DATA_REC_INIT_DATA;  -- to avoid latches
141 2 wzab
    s_low_in_addr_i <= s_low_in_addr;
142
    s_low_in_i      <= low_in;
143
    low_out         <= '0';
144
    up_out          <= '0';
145
    up_out_addr     <= (others => '0');
146
    s_up_in_val_i   <= s_up_in_val;
147
    s_low_in_val_i  <= s_low_in_val;
148
    lm_dout         <= DATA_REC_INIT_DATA;
149
    rm_dout         <= DATA_REC_INIT_DATA;
150
    s_tm_dout       <= DATA_REC_INIT_DATA;
151
    s_addr_out      <= (others => '0');
152
    case ctrl_state is
153
      when CTRL_RESET =>
154
        addr_i          <= (others => '0');
155
        s_ready_out_i   <= '0';
156
        ctrl_state_next <= CTRL_CLEAR;
157
      when CTRL_CLEAR =>
158
        lm_addr <= addr;
159
        rm_addr <= addr;
160
        lm_dout <= DATA_REC_INIT_DATA;
161
        rm_dout <= DATA_REC_INIT_DATA;
162
        lm_we   <= '1';
163
        rm_we   <= '1';
164
        if addr = ADDR_MAX then
165
          if ready_in = '1' then
166
            s_ready_out_i   <= '1';
167
            ctrl_state_next <= CTRL_IDLE;
168
          end if;
169
        else
170
          addr_i <= std_logic_vector(unsigned(addr)+1);
171
        end if;
172
      when CTRL_IDLE =>
173
        -- We read "down" memories ("upper" value is provided by the ``bypass channel'')
174
        if up_in = '1' then
175
          ctrl_state_next <= CTRL_S1;
176
          tm_addr         <= up_in_addr;
177
          lm_addr         <= up_in_addr;
178
          rm_addr         <= up_in_addr;
179
          addr_i          <= up_in_addr;
180
          s_up_in_val_i   <= up_in_val;
181
          if low_in = '1' then
182
            s_low_in_val_i  <= low_in_val;
183
            s_low_in_addr_i <= low_in_addr;
184
          end if;
185
        end if;
186
      when CTRL_S1 =>
187
        -- In this cycle we can compare data
188
        -- Debug output!
189
        if SORT_DEBUG then
190
          write(rline, string'("CMP "));
191
          write(rline, NADDRBITS);
192
          write(rline, string'(" U:"));
193
          wrstlv(rline, tdrec2stlv(s_up_in_val));
194
        end if;
195
        l_val := lm_din;
196
        r_val := rm_din;
197
        -- Check, if we need to take value from lower ``bypass channel''
198
        if s_low_in = '1' then
199
          if SORT_DEBUG then
200
            write(rline, string'(" x! "));
201
          end if;
202
          if (addr(NADDRBITS-1 downto 0) = s_low_in_addr(NADDRBITS-1 downto 0)) then
203
            -- We are reading a value which was just updated, so we need to get it
204
            -- from ``bypass channel'' instead of memory
205
            if SORT_DEBUG then
206
              write(rline, string'(" y! "));
207
            end if;
208
            if s_low_in_addr(NADDRBITS) = '1' then
209
              l_val := s_low_in_val;
210
            else
211
              r_val := s_low_in_val;
212
            end if;
213
          end if;
214
        end if;
215
        if SORT_DEBUG then
216
          write(rline, string'(" L:"));
217
          wrstlv(rline, tdrec2stlv(l_val));
218
          write(rline, string'(" R:"));
219
          wrstlv(rline, tdrec2stlv(r_val));
220
          write(rline, string'(" A:"));
221
        end if;
222
        if sort_cmp_lt(l_val, s_up_in_val) and sort_cmp_lt(l_val, r_val) then
223
          -- The L-ram value is the smallest
224
          -- Output the value from the L-ram and put the new value into the L-ram
225
          s_tm_dout <= l_val;
226
          tm_addr   <= addr;
227
          tm_we     <= '1';
228
 
229
          up_out_val  <= l_val;
230
          up_out      <= '1';
231
          up_out_addr <= addr;
232
 
233
          lm_addr <= addr;
234
          lm_dout <= s_up_in_val;
235
          lm_we   <= '1';
236
 
237
          low_out               <= '1';
238
          low_out_val           <= s_up_in_val;
239
          s_addr_out(NADDRBITS) <= '1';
240
 
241
          if NADDRBITS > 0 then
242
            s_addr_out(NADDRBITS-1 downto 0) <= addr(NADDRBITS-1 downto 0);
243
          end if;
244
          wrstlv(rline, s_addr_out);
245
          ctrl_state_next <= CTRL_IDLE;
246
          if SORT_DEBUG then
247
            write(rline, string'(" T<->L"));
248
          end if;
249
        elsif sort_cmp_lt(r_val, s_up_in_val) then
250
          -- The R-ram value is the smallest
251
          -- Output the value from the R-ram and put the new value into the R-ram
252
          s_tm_dout <= r_val;
253
          tm_addr   <= addr;
254
          tm_we     <= '1';
255
 
256
          up_out_val  <= r_val;
257
          up_out      <= '1';
258
          up_out_addr <= addr;
259
 
260
          rm_addr <= addr;
261
          rm_dout <= s_up_in_val;
262
          rm_we   <= '1';
263
 
264
          low_out     <= '1';
265
          low_out_val <= s_up_in_val;
266
 
267
          s_addr_out(NADDRBITS) <= '0';
268
          if NADDRBITS > 0 then
269
            s_addr_out(NADDRBITS-1 downto 0) <= addr(NADDRBITS-1 downto 0);
270
          end if;
271
          ctrl_state_next <= CTRL_IDLE;
272
          if SORT_DEBUG then
273
            wrstlv(rline, s_addr_out);
274
            write(rline, string'(" T<->R"));
275
          end if;
276
        else
277
          -- The new value is the smallest
278
          -- Nothing to do, no update downstream
279
          s_tm_dout <= s_up_in_val;
280
          tm_we     <= '1';
281
          tm_addr   <= addr;
282
 
283
          up_out_val  <= s_up_in_val;
284
          up_out      <= '1';
285
          up_out_addr <= addr;
286
 
287
          ctrl_state_next <= CTRL_IDLE;
288
          wrstlv(rline, up_in_addr);
289
          if SORT_DEBUG then
290
            write(rline, string'(" T===T"));
291
          end if;
292
        end if;
293
        if SORT_DEBUG then
294
          writeline(reports, rline);
295
        end if;
296
      when others => null;
297
    end case;
298
  end process p1;
299
 
300
  p2 : process (clk, rst_n) is
301
  begin  -- process p2
302
    if rst_n = '0' then                 -- asynchronous reset (active low)
303
      ctrl_state    <= CTRL_RESET;
304
      s_ready_out   <= '0';
305
      addr          <= (others => '0');
306
      s_low_in_addr <= (others => '0');
307
      s_low_in      <= '0';
308
      s_low_in_val  <= DATA_REC_INIT_DATA;
309
      s_up_in_val   <= DATA_REC_INIT_DATA;
310
      --update_out  <= '0';
311
      --addr_out    <= (others => '0');
312
    elsif clk'event and clk = '1' then  -- rising clock edge
313
      s_ready_out   <= s_ready_out_i;
314
      ctrl_state    <= ctrl_state_next;
315
      addr          <= addr_i;
316
      s_low_in_addr <= s_low_in_addr_i;
317
      s_low_in_val  <= s_low_in_val_i;
318
      s_up_in_val   <= s_up_in_val_i;
319
      s_low_in      <= s_low_in_i;
320
    end if;
321
  end process p2;
322
  ready_out    <= s_ready_out;
323
  low_out_addr <= s_addr_out;
324
end sorter_ctrl_arch1;

powered by: WebSVN 2.1.0

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