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.storage/] [sdram2hibi/] [1.0/] [vhd/] [wra_16sdram_32hibi.vhd] - Blame information for rev 145

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 145 lanttu
-------------------------------------------------------------------------------
2
-- Title      : Adapter wrapper 16-bit sdram <-> 32-bit hibi
3
-- Project    : 
4
-------------------------------------------------------------------------------
5
-- File       : wra_16sdram_32hibi.vhd
6
-- Author     :   <alhonena@AHVEN>
7
-- Company    : 
8
-- Created    : 2012-01-26
9
-- Platform   : 
10
-- Standard   : VHDL'87
11
-------------------------------------------------------------------------------
12
-- Description: It was easier and more fail-safe to make an adapter block
13
-- to connect sdram2hibi to a 16-bit sdram, than trying to modify the
14
-- sdram2hibi to directly support 16-bit sdram.
15
-- This is connected between sdram_controller and sdram2hibi.
16
--
17
-- Converts the operations to two times longer/shorter operations,
18
-- transparently like it would be just a slower 32-bit sdram.
19
--
20
-- As of 2012-01-26, there still might be room for some optimization.
21
-------------------------------------------------------------------------------
22
-- Copyright (c) 2012 Tampere University of Technology
23
-------------------------------------------------------------------------------
24
-- Revisions  :
25
-- Date        Version  Author  Description
26
-- 2012-01-26  1.0      alhonena        Created
27
-- 2012-04-10  1.1      alhonena  PLEASE NOTE: The SDRAM controller block,
28
-- for some mysterious reason, ABORTS the read/write operation if fifo gets
29
-- full/empty. This weird behavior is a considered decision by the author,
30
-- so I didn't go and break the compatibility. This fact makes this adapter
31
-- block a way more complex than necessary. In fact it also makes the
32
-- hibi2sdram more complex. In the future we might want to simplify the whole
33
-- circus.
34
-------------------------------------------------------------------------------
35
 
36
library ieee;
37
use ieee.std_logic_1164.all;
38
use ieee.numeric_std.all;
39
 
40
entity wra_16sdram_32hibi is
41
 
42
  generic (
43
    mem_addr_width_g     : integer := 22
44
    );
45
 
46
  port (
47
    clk   : in std_logic;
48
    rst_n : in std_logic;
49
 
50
 
51
    -- FROM/TO SDRAM2HIBI: the 32-bit interface.
52
 
53
    sdram2hibi_write_on_out    : out std_logic;
54
    sdram2hibi_comm_in         : in  std_logic_vector(1 downto 0);
55
    sdram2hibi_addr_in         : in  std_logic_vector(21 downto 0);
56
    sdram2hibi_data_amount_in  : in  std_logic_vector(mem_addr_width_g-1 downto 0);
57
    sdram2hibi_input_one_d_in  : in  std_logic;
58
    sdram2hibi_input_empty_in  : in  std_logic;
59
    sdram2hibi_output_full_in  : in  std_logic;
60
    sdram2hibi_busy_out        : out std_logic;
61
    sdram2hibi_re_out          : out std_logic;
62
    sdram2hibi_we_out          : out std_logic;
63
 
64
    sdram2hibi_data_in         : in  std_logic_vector(31 downto 0);
65
    sdram2hibi_data_out        : out std_logic_vector(31 downto 0);
66
 
67
    -- FROM/TO SDRAM_CONTROLLER: the 16-bit interface.
68
 
69
    ctrl_command_out            : out std_logic_vector(1 downto 0);
70
    ctrl_address_out            : out std_logic_vector(21 downto 0);
71
    ctrl_data_amount_out        : out std_logic_vector(mem_addr_width_g-1 downto 0);
72
    ctrl_byte_select_out        : out std_logic_vector(1 downto 0);
73
    ctrl_input_empty_out        : out std_logic;
74
    ctrl_input_one_d_out        : out std_logic;
75
    ctrl_output_full_out        : out std_logic;
76
    ctrl_data_out               : out std_logic_vector(15 downto 0);
77
    ctrl_write_on_in            : in  std_logic;
78
    ctrl_busy_in                : in  std_logic;
79
    ctrl_output_we_in           : in  std_logic;
80
    ctrl_input_re_in            : in  std_logic;
81
    ctrl_data_in                : in  std_logic_vector(15 downto 0)
82
 
83
    );
84
 
85
end wra_16sdram_32hibi;
86
 
87
architecture rtl of wra_16sdram_32hibi is
88
 
89
  -- commands
90
  constant command_nop_c   : std_logic_vector(1 downto 0) := "00";
91
  constant command_read_c  : std_logic_vector(1 downto 0) := "01";
92
  constant command_write_c : std_logic_vector(1 downto 0) := "10";
93
 
94
  type state_t is (idle, read_1, read_2, read_stall, write_1, write_2);
95
  signal state_r : state_t;
96
 
97
  signal read_temp_r  : std_logic_vector(15 downto 0);
98
  signal write_temp_r : std_logic_vector(15 downto 0);
99
 
100
  signal data_cnt_r  : unsigned(mem_addr_width_g-1 downto 0);
101
  signal cur_addr_r : unsigned(mem_addr_width_g-1 downto 0);
102
 
103
  signal sdram2hibi_re_out_r : std_logic;
104
 
105
  signal ctrl_input_empty_out_r : std_logic;
106
 
107
begin  -- rtl
108
 
109
  -- Full signal for read operations gets propagated through.
110
  ctrl_output_full_out <= sdram2hibi_output_full_in;
111
 
112
  busy_proc: process (state_r, ctrl_busy_in)
113
  begin  -- process busy_proc
114
    if ctrl_busy_in = '1' or state_r /= idle then
115
      sdram2hibi_busy_out <= '1';
116
    else
117
      sdram2hibi_busy_out <= '0';
118
    end if;
119
  end process busy_proc;
120
 
121
  ctrl_byte_select_out <= "00";         -- not implemented in sdram2hibi.
122
 
123
  -- This dirty "write on" signal is used in sdram2hibi to count actual
124
  -- words written in sdram to know when the operation is finished.
125
  sdram2hibi_write_on_out <= sdram2hibi_re_out_r;
126
 
127
  sdram2hibi_re_out <= sdram2hibi_re_out_r;
128
  ctrl_input_empty_out <= ctrl_input_empty_out_r;
129
 
130
  -- Ask for double amount of words.
131
  -- Hence, amount is guaranteed to be even and is checked only at read_2 and write_2.
132
  ctrl_data_amount_out <= std_logic_vector(data_cnt_r(mem_addr_width_g-2 downto 0)) & '0';
133
  ctrl_address_out <= std_logic_vector(cur_addr_r);
134
 
135
  fsm: process (clk, rst_n)
136
  begin  -- process fsm
137
    if rst_n = '0' then                 -- asynchronous reset (active low)
138
      state_r <= idle;
139
      ctrl_command_out <= command_nop_c;
140
      ctrl_input_empty_out_r <= '1';
141
      ctrl_input_one_d_out <= '0';
142
 
143
    elsif clk'event and clk = '1' then  -- rising clock edge
144
 
145
      sdram2hibi_we_out   <= '0';
146
      sdram2hibi_re_out_r   <= '0';
147
 
148
      case state_r is
149
 
150
        ---------------------------------------------------------
151
        when idle =>
152
        ---------------------------------------------------------
153
 
154
          if ctrl_input_re_in = '1' then
155
            -- this happens when coming from write_2.
156
            ctrl_input_empty_out_r <= '1';
157
            ctrl_input_one_d_out   <= '0';
158
          end if;
159
 
160
          ctrl_command_out <= command_nop_c;
161
 
162
          if sdram2hibi_comm_in = command_read_c then
163
            ctrl_command_out <= command_read_c;
164
            -- multiply the address by 2 because it's a word address.
165
            cur_addr_r           <= unsigned(sdram2hibi_addr_in(20 downto 0) & '0');
166
            data_cnt_r           <= unsigned(sdram2hibi_data_amount_in);  -- count 32-bit words, it's easier.
167
            state_r <= read_1;
168
          end if;
169
 
170
          if sdram2hibi_comm_in = command_write_c then
171
            ctrl_command_out <= command_write_c;
172
            -- multiply the address by 2 because it's a word address.
173
            cur_addr_r          <= unsigned(sdram2hibi_addr_in(20 downto 0) & '0');
174
            data_cnt_r          <= unsigned(sdram2hibi_data_amount_in);  -- count 32-bit words, it's easier.
175
            state_r <= write_1;
176
          end if;
177
 
178
        ---------------------------------------------------------
179
        when read_1 =>
180
        ---------------------------------------------------------
181
 
182
          if ctrl_output_we_in = '1' then
183
            cur_addr_r <= cur_addr_r + to_unsigned(1, mem_addr_width_g);
184
            read_temp_r <= ctrl_data_in;
185
            state_r <= read_2;
186
          end if;
187
 
188
        ---------------------------------------------------------
189
        when read_2 =>
190
        ---------------------------------------------------------
191
 
192
          if ctrl_output_we_in = '1' then
193
            cur_addr_r <= cur_addr_r + to_unsigned(1, mem_addr_width_g);
194
            sdram2hibi_data_out <= ctrl_data_in & read_temp_r;
195
            if sdram2hibi_output_full_in = '0' then
196
              sdram2hibi_we_out   <= '1';
197
            else
198
              state_r <= read_stall;
199
            end if;
200
 
201
            if data_cnt_r = 1 then
202
              state_r <= idle;
203
              ctrl_command_out <= command_nop_c;
204
            else
205
              state_r <= read_1;
206
              data_cnt_r <= data_cnt_r - to_unsigned(1, mem_addr_width_g);
207
            end if;
208
          end if;
209
 
210
        ---------------------------------------------------------
211
        when read_stall =>
212
        ---------------------------------------------------------
213
          -- This should happen only in some very special occasions
214
          -- because full signal is propagated directly to the controller
215
          -- in advance, preventing the read operation. So, this happens
216
          -- when the full rises suddenly after the sdram read.
217
 
218
          -- Data is already written to sdram2hibi_data_out register,
219
          -- just assert we when possible.
220
          if sdram2hibi_output_full_in = '0' then
221
            sdram2hibi_we_out <= '1';
222
 
223
            if data_cnt_r = 1 then
224
              state_r <= idle;
225
              ctrl_command_out <= command_nop_c;
226
            else
227
              state_r <= read_1;
228
              data_cnt_r <= data_cnt_r - to_unsigned(1, mem_addr_width_g);
229
            end if;
230
 
231
          end if;
232
 
233
        ---------------------------------------------------------
234
        when write_1 =>
235
        ---------------------------------------------------------
236
 
237
          if ctrl_input_re_in = '1' then
238
            -- this happens when coming from write_2. This is
239
            -- overridden if there is something to write right
240
            -- away.
241
            cur_addr_r <= cur_addr_r + to_unsigned(1, mem_addr_width_g);
242
            ctrl_input_empty_out_r <= '1';
243
            ctrl_input_one_d_out   <= '0';
244
          end if;
245
 
246
          if sdram2hibi_input_empty_in = '0' then
247
            -- Here, assert sdram2hibi side re for one cycle but
248
            -- use a temp register for the next data. This way,
249
            -- sdram2hibi_input_empty_in has time to get to the
250
            -- new value before we are again in this state.
251
            sdram2hibi_re_out_r <= '1';
252
            write_temp_r  <= sdram2hibi_data_in(31 downto 16);
253
 
254
            ctrl_data_out <= sdram2hibi_data_in(15 downto 0);
255
            ctrl_input_empty_out_r <= '0';
256
            ctrl_input_one_d_out   <= '0';  -- tell that there are more words!
257
            state_r <= write_2;
258
          end if;
259
 
260
        ---------------------------------------------------------
261
        when write_2 =>
262
        ---------------------------------------------------------
263
 
264
          if ctrl_input_re_in = '1' then
265
            -- this re is from the write_1 state operation, for the first word.
266
            -- hence, it's possible to write the next 16 bits.
267
            ctrl_data_out <= write_temp_r;
268
            cur_addr_r <= cur_addr_r + to_unsigned(1, mem_addr_width_g);
269
            ctrl_input_empty_out_r <= '0';
270
 
271
            if data_cnt_r = 1 then
272
              ctrl_input_one_d_out   <= '1';  -- just one word left.
273
              state_r <= idle;
274
              ctrl_command_out <= command_nop_c;
275
            else
276
              state_r <= write_1;
277
              data_cnt_r <= data_cnt_r - to_unsigned(1, mem_addr_width_g);
278
            end if;
279
 
280
          end if;
281
 
282
 
283
        when others => null;
284
      end case;
285
    end if;
286
  end process fsm;
287
 
288
end rtl;

powered by: WebSVN 2.1.0

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