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

Subversion Repositories funbase_ip_library

[/] [funbase_ip_library/] [trunk/] [TUT/] [ip.hwp.communication/] [n2h2/] [1.0/] [vhd/] [n2h2_tx_vl.vhd] - Blame information for rev 145

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 145 lanttu
-------------------------------------------------------------------------------
2
-- Title      : N2H2 TX with variable latency support
3
-- Project    : 
4
-------------------------------------------------------------------------------
5
-- File       : n2h2_tx.vhd
6
-- Author     : kulmala3
7
-- Created    : 30.03.2005
8
-- Last update: 2011-02-02
9
-- Description: Bufferless transmitter for N2H2. new version to be used
10
-- with memories of all latencies.
11
--
12
-- REQUIRES:
13
-- step_counter2.vhd 
14
-------------------------------------------------------------------------------
15
-- Copyright (c) 2005 
16
-- New version of TX. uses step_counter2.vhd, supports streaming.
17
-------------------------------------------------------------------------------
18
-- Revisions  :
19
-- Date        Version  Author  Description
20
-- 30.03.2005  1.0      AK      Created
21
-------------------------------------------------------------------------------
22
 
23
library ieee;
24
use ieee.std_logic_1164.all;
25
use ieee.std_logic_arith.all;
26
use ieee.std_logic_unsigned.all;
27
 
28
entity n2h2_tx is
29
 
30
  generic (
31
    -- legal values because of SOPC Builder £@££@ crap.
32
    data_width_g   : integer := 32;
33
    addr_width_g   : integer := 32;
34
    amount_width_g : integer := 16);
35
 
36
  port (
37
    clk                     : in  std_logic;
38
    rst_n                   : in  std_logic;
39
    -- Avalon master read interface
40
    avalon_addr_out         : out std_logic_vector(addr_width_g-1 downto 0);
41
    avalon_re_out           : out std_logic;
42
    avalon_readdata_in      : in  std_logic_vector(data_width_g-1 downto 0);
43
    avalon_waitrequest_in   : in  std_logic;
44
    avalon_readdatavalid_in : in  std_logic;
45
 
46
    -- hibi write interface
47
    hibi_data_out           : out std_logic_vector(data_width_g-1 downto 0);
48
    hibi_av_out             : out std_logic;
49
    hibi_full_in            : in  std_logic;
50
    hibi_comm_out           : out std_logic_vector(4 downto 0);
51
    hibi_we_out             : out std_logic;
52
 
53
    -- DMA conf interface
54
    tx_start_in             : in  std_logic;
55
    tx_status_done_out      : out std_logic;
56
    tx_comm_in              : in  std_logic_vector(4 downto 0);
57
    tx_hibi_addr_in         : in  std_logic_vector(addr_width_g-1 downto 0);
58
    tx_ram_addr_in          : in  std_logic_vector(addr_width_g-1 downto 0);
59
    tx_amount_in            : in  std_logic_vector(amount_width_g-1 downto 0)
60
    );
61
 
62
end n2h2_tx;
63
 
64
architecture rtl of n2h2_tx is
65
 
66
  type control_states is (idle, transmit_addr, transmit, hfull);
67
  signal   control_r     : control_states;
68
  constant addr_offset_c : integer := data_width_g/8;
69
 
70
  component step_counter2
71
    generic (
72
      step_size_g :     integer;
73
      width_g     :     integer
74
      );
75
    port (
76
      clk         : in  std_logic;
77
      rst_n       : in  std_logic;
78
      en_in       : in  std_logic;
79
      value_in    : in  std_logic_vector(width_g-1 downto 0);
80
      load_in     : in  std_logic;
81
      value_out   : out std_logic_vector(width_g-1 downto 0));
82
  end component;
83
 
84
  signal addr_cnt_en_r      : std_logic;
85
  signal addr_cnt_value_r   : std_logic_vector(addr_width_g-1 downto 0);
86
  signal addr_cnt_load_r    : std_logic;
87
  signal addr_r             : std_logic_vector(addr_width_g-1 downto 0);
88
  signal amount_cnt_en_r    : std_logic;
89
  signal amount_cnt_value_r : std_logic_vector(addr_width_g-1 downto 0);
90
  signal amount_cnt_load_r  : std_logic;
91
  signal amount_r           : std_logic_vector(addr_width_g-1 downto 0);
92
 
93
  signal addr_amount_eq : std_logic;
94
 
95
  signal addr_to_stop_r : std_logic_vector(addr_width_g-1 downto 0);
96
  signal avalon_re_r    : std_logic;
97
  signal start_re_r     : std_logic;
98
 
99
  signal hibi_write_addr_r : std_logic;
100
  signal data_src_sel      : std_logic;
101
  signal hibi_we_r         : std_logic;
102
  signal hibi_stop_we_r    : std_logic;
103
 
104
 
105
begin  -- rtl
106
 
107
  -----------------------------------------------------------------------------
108
  -- 1) waitrequest affects the data reading
109
  -- 2) readdatavalid data write to hibi
110
  -- 3) avalon side read must control the amount of data
111
  -- 4) whenever readdatavalid is asserted, data is written to HIBI
112
  -- 5) HIBI full is problematic. A counter must be added to see from which
113
  --    address we have succesfully read the data so far. We cannot
114
  --    save the data to register, because we are unaware of the latency.
115
  --    So when full comes, the read process from avalon must be started
116
  --    again.
117
  -- 6) write and read signals should be asynchronously controlled by
118
  --    signals from hibi and avalon in order to react as fast as possible.
119
  -- 7) after full the write should be ceased. readdatavalid from older data
120
  --    should be taken care of. Write continues only after read enable has
121
  --    been asserted again?
122
  -- 8) read from avalon must proceed as fast as possible. for example,
123
  --    start already when writing address to hibi. (at least one clock
124
  --    cycle latency expected, should be safe). Or after full.
125
  -- 9) data to hibi comes from either register input (address) or
126
  --    straight from the memory. mux is needed.
127
  -----------------------------------------------------------------------------
128
 
129
  hibi_comm_out   <= tx_comm_in;
130
  -- minus here and and addition in first store? could reduce the
131
  -- cricital path...
132
  avalon_addr_out <= addr_r;
133
 
134
  addr_counter2_1 : step_counter2
135
    generic map (
136
      step_size_g => addr_offset_c,
137
      width_g     => addr_width_g)
138
    port map (
139
      clk         => clk,
140
      rst_n       => rst_n,
141
      en_in       => addr_cnt_en_r,
142
      value_in    => addr_cnt_value_r,
143
      load_in     => addr_cnt_load_r,
144
      value_out   => addr_r
145
      );
146
 
147
  addr_cnt_load_r      <= (tx_start_in or hibi_full_in);
148
  addr_cnt : process (tx_ram_addr_in, amount_r, tx_start_in)
149
  begin  -- process addr_cnt
150
    if tx_start_in = '1' then
151
      -- addr from input
152
      addr_cnt_value_r <= tx_ram_addr_in;
153
    else
154
      -- addr from counter
155
      addr_cnt_value_r <= amount_r;
156
    end if;
157
  end process addr_cnt;
158
 
159
 
160
 
161
  amount_counter2_1 : step_counter2
162
    generic map (
163
      step_size_g => addr_offset_c,
164
      width_g     => addr_width_g)
165
    port map (
166
      clk         => clk,
167
      rst_n       => rst_n,
168
      en_in       => amount_cnt_en_r,
169
      value_in    => amount_cnt_value_r,
170
      load_in     => amount_cnt_load_r,
171
      value_out   => amount_r
172
      );
173
-- amount counted only when data is written
174
  amount_cnt_en_r <= hibi_we_r and (not data_src_sel);
175
  -- hibi_we depends on readdatavalid and full + control signal for
176
  -- address writing
177
  -- start address writing right when the signal comes in.
178
  -- no old readdatavalids should be written if full is short.
179
  hibi_we_out     <= hibi_we_r;
180
  hibi_we_r       <= ((data_src_sel) or (avalon_readdatavalid_in and (not hibi_stop_we_r)))
181
                     and (not hibi_full_in);
182
 
183
  data_src_sel <= tx_start_in or hibi_write_addr_r;
184
  hibi_av_out  <= data_src_sel;
185
 
186
  addr_data : process (tx_hibi_addr_in, avalon_readdata_in, data_src_sel)
187
  begin  -- process addr_data
188
    if data_src_sel = '1' then
189
      hibi_data_out <= (others => '0');
190
      hibi_data_out(addr_width_g-1 downto 0) <= tx_hibi_addr_in;
191
    else
192
      hibi_data_out <= avalon_readdata_in;
193
    end if;
194
  end process addr_data;
195
 
196
  -- if we're reading and not forced to wait,
197
  -- increase the address. we want to cease reading if hibi goes full
198
  -- (reload address)
199
  addr_cnt_en_r <= (avalon_re_r and (not avalon_waitrequest_in)) and
200
                   (not hibi_full_in);
201
  avalon_re_out <= avalon_re_r;
202
  -- read enable depends on the amount transferred, if a 
203
  -- transmission is ongoing. shoot as soon as possible,
204
  -- whenever new transmission is assigned.
205
-- CHECK OUT THIS ONE! could be used to fasten n2h2 up!
206
    avalon_re_r   <= start_re_r;-- or (tx_start_in and (not hibi_full_in));
207
 
208
  comparison : process (addr_r, addr_to_stop_r)
209
  begin  -- process comparison
210
    -- addr_offset added here, because addr_to_stop process caused two
211
    -- back-to-back adders, now they should be in parallel
212
    if addr_r = addr_to_stop_r then
213
      addr_amount_eq <= '1';
214
    else
215
      addr_amount_eq <= '0';
216
    end if;
217
  end process comparison;
218
 
219
  addr_to_stop : process (tx_amount_in, tx_ram_addr_in)
220
  begin  -- process addr_to_stop
221
    addr_to_stop_r <= tx_ram_addr_in + conv_std_logic_vector(
222
      conv_integer(tx_amount_in)*addr_offset_c, addr_width_g);
223
-- conv_integer(tx_amount_in+1)*addr_offset_c, data_width_g);
224
  end process addr_to_stop;
225
 
226
  amount_cnt_value_r <= tx_ram_addr_in;
227
  amount_cnt_load_r  <= tx_start_in;
228
 
229
  main : process (clk, rst_n)
230
  begin  -- process main
231
    if rst_n = '0' then                 -- asynchronous reset (active low)
232
      control_r          <= idle;
233
      start_re_r         <= '0';
234
      hibi_write_addr_r  <= '0';
235
      tx_status_done_out <= '1';
236
      hibi_stop_we_r     <= '0';
237
 
238
    elsif clk'event and clk = '1' then  -- rising clock edge
239
      case control_r is
240
        when idle =>
241
          hibi_write_addr_r  <= '0';
242
          start_re_r         <= '0';
243
          tx_status_done_out <= '1';
244
          hibi_stop_we_r     <= '1';
245
 
246
          if tx_start_in = '1' then
247
            -- avalon read address
248
            -- address which contents written to hibi
249
            tx_status_done_out <= '0';
250
            hibi_stop_we_r     <= '0';
251
 
252
            if hibi_full_in = '0' then
253
              -- address will be transferred in this clock cycle
254
              control_r         <= transmit;
255
              start_re_r        <= '1';
256
            else
257
              hibi_write_addr_r <= '1';
258
              control_r         <= transmit_addr;
259
            end if;
260
          end if;
261
 
262
        when transmit_addr =>
263
          -- if we're here, hibi was full
264
          if hibi_full_in = '0' then
265
            -- we wrote the addr
266
            start_re_r        <= '1';
267
            control_r         <= transmit;
268
            hibi_write_addr_r <= '0';
269
          else
270
            start_re_r        <= '0';
271
            control_r         <= transmit_addr;
272
            hibi_write_addr_r <= '1';
273
          end if;
274
 
275
        when transmit =>
276
          if hibi_full_in = '1' then
277
            start_re_r     <= '0';
278
            control_r      <= hfull;
279
            hibi_stop_we_r <= '1';
280
          else
281
            start_re_r     <= '1';
282
            hibi_stop_we_r <= '0';
283
            control_r      <= transmit;
284
          end if;
285
 
286
--          if addr_amount_eq = '1' and hibi_full_in = '0' then
287
          if addr_amount_eq = '1' and hibi_we_r = '1' then
288
            control_r      <= idle;
289
            -- stopped transferring
290
            tx_status_done_out <= '1';
291
            hibi_stop_we_r <= '1';
292
          end if;
293
 
294
        when hfull =>
295
          if hibi_full_in = '0' and avalon_readdatavalid_in = '0' then
296
            -- datavalid has to go down before proceed.
297
            -- so we make sure that no invalid data is written
298
            -- when there's a short full.
299
            start_re_r     <= '1';
300
            hibi_stop_we_r <= '0';
301
            control_r      <= transmit;
302
          else
303
            start_re_r     <= '0';
304
            hibi_stop_we_r <= '1';
305
            control_r      <= hfull;
306
          end if;
307
 
308
        when others => null;
309
      end case;
310
    end if;
311
  end process main;
312
 
313
end rtl;

powered by: WebSVN 2.1.0

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