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

Subversion Repositories simpcon

[/] [simpcon/] [trunk/] [vhdl/] [sc_sram16.vhd] - Blame information for rev 29

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

Line No. Rev Author Line
1 18 martin
--
2
--      sc_sram16.vhd
3
--
4
--      SimpCon compliant external memory interface
5
--      for 16-bit SRAM (e.g. Altera DE2 board)
6
--
7
--      High 16-bit word is at lower address
8
--
9
--      Connection between mem_sc and the external memory bus
10
--
11
--      memory mapping
12
--      
13
--              000000-x7ffff   external SRAM (w mirror)        max. 512 kW (4*4 MBit)
14
--
15
--      RAM: 16 bit word
16
--
17
--
18
--      2006-08-01      Adapted from sc_ram32.vhd
19
--      2006-08-16      Rebuilding the already working (lost) version
20
--                              Use wait_state, din register without MUX
21 21 martin
--      2007-06-04      changed SimpCon to records
22
--      2007-09-09      Additional input register for high data (correct SimpCon violation)
23 18 martin
--
24
 
25
Library IEEE;
26
use IEEE.std_logic_1164.all;
27
use ieee.numeric_std.all;
28
 
29
use work.jop_types.all;
30 21 martin
use work.sc_pack.all;
31 18 martin
 
32
entity sc_mem_if is
33
generic (ram_ws : integer; addr_bits : integer);
34
 
35
port (
36
 
37
        clk, reset      : in std_logic;
38
 
39 21 martin
--
40
--      SimpCon memory interface
41
--
42
        sc_mem_out              : in sc_mem_out_type;
43
        sc_mem_in               : out sc_in_type;
44 18 martin
 
45
-- memory interface
46
 
47
        ram_addr        : out std_logic_vector(addr_bits-1 downto 0);
48
        ram_dout        : out std_logic_vector(15 downto 0);
49
        ram_din         : in std_logic_vector(15 downto 0);
50
        ram_dout_en     : out std_logic;
51
        ram_ncs         : out std_logic;
52
        ram_noe         : out std_logic;
53
        ram_nwe         : out std_logic
54
 
55
);
56
end sc_mem_if;
57
 
58
architecture rtl of sc_mem_if is
59
 
60
--
61
--      signals for mem interface
62
--
63
        type state_type         is (
64
                                                        idl, rd1_h, rd2_h, rd1_l, rd2_l,
65
                                                        wr_h, wr_idl, wr_l
66
                                                );
67
        signal state            : state_type;
68
        signal next_state       : state_type;
69
 
70
        signal nwr_int          : std_logic;
71
        signal wait_state       : unsigned(3 downto 0);
72
        signal cnt                      : unsigned(1 downto 0);
73
 
74
        signal dout_ena         : std_logic;
75
        signal rd_data_ena_h    : std_logic;
76
        signal rd_data_ena_l    : std_logic;
77
        signal inc_addr                 : std_logic;
78
        signal wr_low                   : std_logic;
79
 
80 21 martin
        signal ram_dout_low             : std_logic_vector(15 downto 0);
81
        signal ram_din_high             : std_logic_vector(15 downto 0);
82 18 martin
 
83
        signal ram_din_reg      : std_logic_vector(31 downto 0);
84
 
85
begin
86
 
87
        ram_dout_en <= dout_ena;
88
 
89 21 martin
        sc_mem_in.rdy_cnt <= cnt;
90 18 martin
 
91
--
92
--      Register memory address, write data and read data
93
--
94
process(clk, reset)
95
begin
96
        if reset='1' then
97
 
98
                ram_addr <= (others => '0');
99
                ram_dout <= (others => '0');
100
                ram_dout_low <= (others => '0');
101
 
102
        elsif rising_edge(clk) then
103
 
104 21 martin
                if sc_mem_out.rd='1' or sc_mem_out.wr='1' then
105
                        ram_addr <= sc_mem_out.address(addr_bits-2 downto 0) & "0";
106 18 martin
                end if;
107
                if inc_addr='1' then
108
                        ram_addr(0) <= '1';
109
                end if;
110 21 martin
                if sc_mem_out.wr='1' then
111
                        ram_dout <= sc_mem_out.wr_data(31 downto 16);
112
                        ram_dout_low <= sc_mem_out.wr_data(15 downto 0);
113 18 martin
                end if;
114
                if wr_low='1' then
115
                        ram_dout <= ram_dout_low;
116
                end if;
117 21 martin
                -- use an addtional input register to adhire the SimpCon spec
118
                -- to not change rd_data untill the full new word is available
119
                -- results in input MUX at RAM data input
120 18 martin
                if rd_data_ena_h='1' then
121 21 martin
                        ram_din_high <= ram_din;
122 18 martin
                end if;
123
                if rd_data_ena_l='1' then
124
                        -- move first word to higher half
125 21 martin
                        ram_din_reg(31 downto 16) <= ram_din_high;
126 18 martin
                        -- read second word
127
                        ram_din_reg(15 downto 0) <= ram_din;
128
                end if;
129
 
130
        end if;
131
end process;
132
 
133 21 martin
        sc_mem_in.rd_data <= ram_din_reg;
134 18 martin
 
135
--
136
--      'delay' nwe 1/2 cycle -> change on falling edge
137
--
138
process(clk, reset)
139
 
140
begin
141
        if (reset='1') then
142
                ram_nwe <= '1';
143
        elsif falling_edge(clk) then
144
                ram_nwe <= nwr_int;
145
        end if;
146
 
147
end process;
148
 
149
 
150
--
151
--      next state logic
152
--
153 21 martin
process(state, sc_mem_out.rd, sc_mem_out.wr, wait_state)
154 18 martin
 
155
begin
156
 
157
        next_state <= state;
158
 
159
        case state is
160
 
161
                when idl =>
162 21 martin
                        if sc_mem_out.rd='1' then
163 18 martin
                                if ram_ws=0 then
164
                                        -- then we omit state rd1!
165
                                        next_state <= rd2_h;
166
                                else
167
                                        next_state <= rd1_h;
168
                                end if;
169 21 martin
                        elsif sc_mem_out.wr='1' then
170 18 martin
                                next_state <= wr_h;
171
                        end if;
172
 
173
                -- the WS state
174
                when rd1_h =>
175
                        if wait_state=2 then
176
                                next_state <= rd2_h;
177
                        end if;
178
 
179
                when rd2_h =>
180
                        -- go to read low word
181
                        if ram_ws=0 then
182
                                -- then we omit state rd1!
183
                                next_state <= rd2_l;
184
                        else
185
                                next_state <= rd1_l;
186
                        end if;
187
 
188
                -- the WS state
189
                when rd1_l =>
190
                        if wait_state=2 then
191
                                next_state <= rd2_l;
192
                        end if;
193
 
194
                -- last read state
195
                when rd2_l =>
196
                        next_state <= idl;
197
                        -- This should do to give us a pipeline
198
                        -- level of 2 for read
199 21 martin
                        if sc_mem_out.rd='1' then
200 18 martin
                                if ram_ws=0 then
201
                                        -- then we omit state rd1!
202
                                        next_state <= rd2_h;
203
                                else
204
                                        next_state <= rd1_h;
205
                                end if;
206 21 martin
                        elsif sc_mem_out.wr='1' then
207 18 martin
                                next_state <= wr_h;
208
                        end if;
209
 
210
                -- the WS state
211
                when wr_h =>
212
-- TODO: check what happens on ram_ws=0
213
-- TODO: do we need a write pipelining?
214
--      not at the moment, but parhaps later when
215
--      we write the stack content to main memory
216
                        if wait_state=1 then
217
                                next_state <= wr_idl;
218
                        end if;
219
 
220
                -- one idle state for nwr to go high
221
                when wr_idl =>
222
                        next_state <= wr_l;
223
 
224
                -- the WS state
225
                when wr_l =>
226
                        if wait_state=1 then
227
                                next_state <= idl;
228
                        end if;
229
 
230
        end case;
231
 
232
end process;
233
 
234
--
235
--      state machine register
236
--      output register
237
--
238
process(clk, reset)
239
 
240
begin
241
        if (reset='1') then
242
                state <= idl;
243
                dout_ena <= '0';
244
                ram_ncs <= '1';
245
                ram_noe <= '1';
246
                rd_data_ena_h <= '0';
247
                rd_data_ena_l <= '0';
248
                inc_addr <= '0';
249
                wr_low <= '0';
250
        elsif rising_edge(clk) then
251
 
252
                state <= next_state;
253
                dout_ena <= '0';
254
                ram_ncs <= '1';
255
                ram_noe <= '1';
256
                rd_data_ena_h <= '0';
257
                rd_data_ena_l <= '0';
258
                inc_addr <= '0';
259
                wr_low <= '0';
260
 
261
                case next_state is
262
 
263
                        when idl =>
264
 
265
                        -- the wait state
266
                        when rd1_h =>
267
                                ram_ncs <= '0';
268
                                ram_noe <= '0';
269
 
270
                        -- high word last read state
271
                        when rd2_h =>
272
                                ram_ncs <= '0';
273
                                ram_noe <= '0';
274
                                rd_data_ena_h <= '1';
275
                                inc_addr <= '1';
276
 
277
                        -- the wait state
278
                        when rd1_l =>
279
                                ram_ncs <= '0';
280
                                ram_noe <= '0';
281
 
282
                        -- low word last read state
283
                        when rd2_l =>
284
                                ram_ncs <= '0';
285
                                ram_noe <= '0';
286
                                rd_data_ena_l <= '1';
287
 
288
                        -- the WS state
289
                        when wr_h =>
290
                                ram_ncs <= '0';
291
                                dout_ena <= '1';
292
 
293
                        -- high word last write state
294
                        when wr_idl =>
295
                                ram_ncs <= '1';
296
                                dout_ena <= '1';
297
                                inc_addr <= '1';
298
                                wr_low <= '1';
299
 
300
                        -- the WS state
301
                        when wr_l =>
302
                                ram_ncs <= '0';
303
                                dout_ena <= '1';
304
 
305
                end case;
306
 
307
        end if;
308
end process;
309
 
310
--
311
--      nwr combinatorial processing
312
--      for the negativ edge
313
--
314
process(next_state, state)
315
begin
316
 
317
        nwr_int <= '1';
318
        -- this is the 'correct' version wich needs
319
        -- at minimum 2 cycles for the RAM access
320
--      if (state=wr_l and next_state=wr_l) or 
321
--              (state=wr_h and next_state=wr_h) then
322
        -- Slightly out of the SRAM spec. nwr goes
323
        -- low befor ncs to allow single cycle
324
        -- access
325
        if next_state=wr_l or next_state=wr_h then
326
 
327
                nwr_int <= '0';
328
        end if;
329
 
330
end process;
331
 
332
--
333
-- wait_state processing
334
--
335
process(clk, reset)
336
begin
337
        if (reset='1') then
338
                wait_state <= (others => '1');
339
                cnt <= "00";
340
        elsif rising_edge(clk) then
341
 
342
                wait_state <= wait_state-1;
343
 
344
                cnt <= "11";
345
                if next_state=idl then
346
                        cnt <= "00";
347
                end if;
348
 
349 21 martin
                if sc_mem_out.rd='1' or sc_mem_out.wr='1' then
350 18 martin
                        wait_state <= to_unsigned(ram_ws+1, 4);
351
                end if;
352
 
353
                if state=rd2_h or state=wr_idl then
354
                        wait_state <= to_unsigned(ram_ws+1, 4);
355
                        if ram_ws<3 then
356
                                cnt <= to_unsigned(ram_ws+1, 2);
357
                        else
358
                                cnt <= "11";
359
                        end if;
360
                end if;
361
 
362
                if state=rd1_l or state=rd2_l or state=wr_l then
363
                        -- take care for pipelined cach transfer
364
                        -- there is no idl state and cnt should
365
                        -- go back to "11"
366 21 martin
                        if sc_mem_out.rd='0' and sc_mem_out.wr='0' then
367 18 martin
                                -- if wait_state<4 then
368
                                if wait_state(3 downto 2)="00" then
369
                                        cnt <= wait_state(1 downto 0)-1;
370
                                end if;
371
                        end if;
372
                end if;
373
 
374
        end if;
375
end process;
376
 
377
end rtl;

powered by: WebSVN 2.1.0

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