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

Subversion Repositories lxp32

[/] [lxp32/] [trunk/] [rtl/] [lxp32_fetch.vhd] - Blame information for rev 9

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 9 ring0_mipt
---------------------------------------------------------------------
2
-- Instruction fetch
3
--
4
-- Part of the LXP32 CPU
5
--
6
-- Copyright (c) 2016 by Alex I. Kuznetsov
7
--
8
-- The first stage of the LXP32 pipeline.
9
---------------------------------------------------------------------
10
 
11
library ieee;
12
use ieee.std_logic_1164.all;
13
use ieee.numeric_std.all;
14
 
15
entity lxp32_fetch is
16
        generic(
17
                START_ADDR: std_logic_vector(31 downto 0)
18
        );
19
        port(
20
                clk_i: in std_logic;
21
                rst_i: in std_logic;
22
 
23
                lli_re_o: out std_logic;
24
                lli_adr_o: out std_logic_vector(29 downto 0);
25
                lli_dat_i: in std_logic_vector(31 downto 0);
26
                lli_busy_i: in std_logic;
27
 
28
                word_o: out std_logic_vector(31 downto 0);
29
                current_ip_o: out std_logic_vector(29 downto 0);
30
                next_ip_o: out std_logic_vector(29 downto 0);
31
                valid_o: out std_logic;
32
                ready_i: in std_logic;
33
 
34
                jump_valid_i: in std_logic;
35
                jump_dst_i: in std_logic_vector(29 downto 0);
36
                jump_ready_o: out std_logic
37
        );
38
end entity;
39
 
40
architecture rtl of lxp32_fetch is
41
 
42
signal init: std_logic:='1';
43
signal init_cnt: unsigned(7 downto 0):=(others=>'0');
44
 
45
signal fetch_addr: std_logic_vector(29 downto 0):=START_ADDR(31 downto 2);
46
 
47
signal next_word: std_logic;
48
signal suppress_re: std_logic:='0';
49
signal re: std_logic;
50
signal requested: std_logic:='0';
51
 
52
signal fifo_rst: std_logic;
53
signal fifo_we: std_logic;
54
signal fifo_din: std_logic_vector(31 downto 0);
55
signal fifo_re: std_logic;
56
signal fifo_dout: std_logic_vector(31 downto 0);
57
signal fifo_empty: std_logic;
58
signal fifo_full: std_logic;
59
 
60
signal jr: std_logic:='0';
61
 
62
signal next_ip: std_logic_vector(fetch_addr'range);
63
signal current_ip: std_logic_vector(fetch_addr'range);
64
 
65
begin
66
 
67
-- INIT state machine (to initialize all registers)
68
 
69
-- All CPU registers are expected to be zero-initialized after reset.
70
-- Since these registers are implemented as a RAM block, we perform
71
-- the initialization sequentially by generating "mov rN, 0" instructions
72
-- for each N from 0 to 255.
73
--
74
-- With SRAM-based FPGAs, flip-flops and RAM blocks have deterministic
75
-- state after configuration. On these technologies the CPU can operate
76
-- without reset and the initialization procedure described above is not
77
-- needed. However, the initialization is still performed as usual when
78
-- external reset signal is asserted.
79
 
80
process (clk_i) is
81
begin
82
        if rising_edge(clk_i) then
83
                if rst_i='1' then
84
                        init<='0';
85
                        init_cnt<=(others=>'0');
86
                else
87
                        if init='0' and ready_i='1' then
88
                                init_cnt<=init_cnt+1;
89
                                if init_cnt=X"FF" then
90
                                        init<='1';
91
                                end if;
92
                        end if;
93
                end if;
94
        end if;
95
end process;
96
 
97
-- FETCH state machine
98
 
99
process (clk_i) is
100
begin
101
        if rising_edge(clk_i) then
102
                if rst_i='1' then
103
                        fetch_addr<=START_ADDR(31 downto 2);
104
                        requested<='0';
105
                        jr<='0';
106
                        suppress_re<='0';
107
                        next_ip<=(others=>'-');
108
                else
109
                        jr<='0';
110
-- Suppress LLI request if jump signal is active but will not be processed
111
-- in this cycle. Helps to reduce jump latency with high-latency LLI slaves.
112
-- Note: gating "re" with "jump_valid_i and not jr" asynchronously would
113
-- reduce jump latency even more, but we really want to avoid too large
114
-- clock-to-out on LLI outputs.
115
                        suppress_re<=jump_valid_i and not jr and not next_word;
116
                        if lli_busy_i='0' then
117
                                requested<=re and not (jump_valid_i and not jr);
118
                        end if;
119
                        if next_word='1' then
120
-- It's not immediately obvious why, but current_ip and next_ip will contain
121
-- the addresses of the current instruction and the next instruction to be
122
-- fetched, respectively, by the time the instruction is passed to the decode
123
-- stage. Basically, this is because when either the decoder or the IBUS
124
-- stalls, the fetch_addr counter will also stop incrementing.
125
                                next_ip<=fetch_addr;
126
                                current_ip<=next_ip;
127
                                if jump_valid_i='1' and jr='0' then
128
                                        fetch_addr<=jump_dst_i;
129
                                        jr<='1';
130
                                else
131
                                        fetch_addr<=std_logic_vector(unsigned(fetch_addr)+1);
132
                                end if;
133
                        end if;
134
                end if;
135
        end if;
136
end process;
137
 
138
next_word<=(fifo_empty or ready_i) and not lli_busy_i and init;
139
re<=(fifo_empty or ready_i) and init and not suppress_re;
140
lli_re_o<=re;
141
lli_adr_o<=fetch_addr;
142
 
143
jump_ready_o<=jr;
144
 
145
-- Small instruction buffer
146
 
147
fifo_rst<=rst_i or (jump_valid_i and not jr);
148
fifo_we<=requested and not lli_busy_i;
149
fifo_din<=lli_dat_i;
150
fifo_re<=ready_i and not fifo_empty;
151
 
152
ubuf_inst: entity work.lxp32_ubuf(rtl)
153
        generic map(
154
                DATA_WIDTH=>32
155
        )
156
        port map(
157
                clk_i=>clk_i,
158
                rst_i=>fifo_rst,
159
 
160
                we_i=>fifo_we,
161
                d_i=>fifo_din,
162
                re_i=>fifo_re,
163
                d_o=>fifo_dout,
164
 
165
                empty_o=>fifo_empty,
166
                full_o=>fifo_full
167
        );
168
 
169
next_ip_o<=next_ip;
170
current_ip_o<=current_ip;
171
word_o<=fifo_dout when init='1' else X"40"&std_logic_vector(init_cnt)&X"0000";
172
valid_o<=not fifo_empty or not init;
173
 
174
-- Note: the following code contains a few simulation-only assertions
175
-- to check that current_ip and next_ip signals, used in procedure calls
176
-- and interrupts, are correct. 
177
-- This code should be ignored by a synthesizer since it doesn't drive
178
-- any signals, but we also surround it by metacomments, just in case.
179
 
180
-- synthesis translate_off
181
 
182
process (clk_i) is
183
        type Pair is record
184
                addr: std_logic_vector(fetch_addr'range);
185
                data: std_logic_vector(31 downto 0);
186
        end record;
187
        type Pairs is array (7 downto 0) of Pair;
188
        variable buf: Pairs;
189
        variable count: integer range buf'range:=0;
190
        variable current_pair: Pair;
191
begin
192
        if rising_edge(clk_i) then
193
                if fifo_rst='1' then -- jump
194
                        count:=0;
195
                elsif fifo_we='1' then -- LLI returned data
196
                        current_pair.data:=fifo_din;
197
                        buf(count):=current_pair;
198
                        count:=count+1;
199
                end if;
200
                if re='1' and lli_busy_i='0' then -- data requested
201
                        current_pair.addr:=fetch_addr;
202
                end if;
203
                if fifo_empty='0' and fifo_rst='0' then -- fetch output is valid
204
                        assert count>0
205
                                report "Fetch: buffer should be empty"
206
                                severity failure;
207
                        assert buf(0).data=fifo_dout
208
                                report "Fetch: incorrect data"
209
                                severity failure;
210
                        assert buf(0).addr=current_ip
211
                                report "Fetch: incorrect current_ip"
212
                                severity failure;
213
                        assert std_logic_vector(unsigned(buf(0).addr)+1)=next_ip
214
                                report "Fetch: incorrect next_ip"
215
                                severity failure;
216
                        if ready_i='1' then
217
                                buf(buf'high-1 downto 0):=buf(buf'high downto 1); -- we don't care about the highest item
218
                                count:=count-1;
219
                        end if;
220
                end if;
221
        end if;
222
end process;
223
 
224
-- synthesis translate_on
225
 
226
end architecture;

powered by: WebSVN 2.1.0

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