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

Subversion Repositories potato

[/] [potato/] [trunk/] [src/] [pp_csr_unit.vhd] - Blame information for rev 58

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 skordal
-- The Potato Processor - A simple processor for FPGAs
2
-- (c) Kristian Klomsten Skordal 2014 - 2015 <kristian.skordal@wafflemail.net>
3 3 skordal
-- Report bugs and issues on <http://opencores.org/project,potato,bugtracker>
4 2 skordal
 
5
library ieee;
6
use ieee.std_logic_1164.all;
7
use ieee.numeric_std.all;
8
 
9
use work.pp_csr.all;
10 58 skordal
use work.pp_utilities.all;
11 2 skordal
 
12
entity pp_csr_unit is
13
        generic(
14
                PROCESSOR_ID : std_logic_vector(31 downto 0)
15
        );
16
        port(
17
                clk, timer_clk : in std_logic;
18
                reset : in std_logic;
19
 
20 58 skordal
                -- IRQ signals:
21
                irq : in std_logic_vector(7 downto 0);
22
 
23 2 skordal
                -- Count retired instruction:
24
                count_instruction : in std_logic;
25
 
26
                -- HTIF interface:
27
                fromhost_data    : in  std_logic_vector(31 downto 0);
28
                fromhost_updated : in  std_logic;
29
                tohost_data      : out std_logic_vector(31 downto 0);
30
                tohost_updated   : out std_logic;
31
 
32
                -- Read port:
33
                read_address   : in csr_address;
34
                read_data_out  : out std_logic_vector(31 downto 0);
35
                read_writeable : out boolean;
36
 
37
                -- Write port:
38
                write_address : in csr_address;
39
                write_data_in : in std_logic_vector(31 downto 0);
40
                write_mode    : in csr_write_mode;
41
 
42
                -- Exception context write port:
43
                exception_context       : in csr_exception_context;
44
                exception_context_write : in std_logic;
45
 
46 58 skordal
                -- Interrupts originating from this unit:
47
                software_interrupt_out : out std_logic;
48
                timer_interrupt_out    : out std_logic;
49
 
50 2 skordal
                -- Registers needed for exception handling, always read:
51 58 skordal
                mie_out         : out std_logic_vector(31 downto 0);
52
                mtvec_out       : out std_logic_vector(31 downto 0);
53
                ie_out, ie1_out : out std_logic
54 2 skordal
        );
55
end entity pp_csr_unit;
56
 
57
architecture behaviour of pp_csr_unit is
58
 
59 58 skordal
        -- Counters:
60 2 skordal
        signal counter_time    : std_logic_vector(63 downto 0);
61
        signal counter_cycle   : std_logic_vector(63 downto 0);
62
        signal counter_instret : std_logic_vector(63 downto 0);
63
 
64 58 skordal
        -- Machine time counter:
65
        signal counter_mtime : std_logic_vector(31 downto 0);
66
        signal mtime_compare : std_logic_vector(31 downto 0);
67 2 skordal
 
68 58 skordal
        -- Machine-mode registers:
69
        signal mcause   : csr_exception_cause;
70
        signal mbadaddr : std_logic_vector(31 downto 0);
71
        signal mscratch : std_logic_vector(31 downto 0);
72
        signal mepc     : std_logic_vector(31 downto 0);
73
        signal mtvec    : std_logic_vector(31 downto 0) := x"00000100";
74
        signal mie      : std_logic_vector(31 downto 0) := (others => '0');
75
 
76
        -- Interrupt enable bits:
77
        signal ie, ie1    : std_logic;
78
 
79 2 skordal
        -- HTIF FROMHOST register:
80
        signal fromhost: std_logic_vector(31 downto 0);
81
 
82 58 skordal
        -- Interrupt signals:
83
        signal timer_interrupt    : std_logic;
84
        signal software_interrupt : std_logic;
85 2 skordal
 
86
begin
87
 
88 58 skordal
        -- Interrupt signals:
89
        software_interrupt_out <= software_interrupt;
90
        timer_interrupt_out <= timer_interrupt;
91
        ie_out <= ie;
92
        ie1_out <= ie1;
93
        mie_out <= mie;
94 2 skordal
 
95 58 skordal
        -- The two upper bits of the CSR address encodes the accessibility of the CSR:
96
        read_writeable <= read_address(11 downto 10) /= b"11";
97
 
98 2 skordal
        --! Updates the FROMHOST register when new data is available.
99
        htif_fromhost: process(clk)
100
        begin
101
                if rising_edge(clk) then
102
                        if fromhost_updated = '1' then
103
                                fromhost <= fromhost_data;
104
                        end if;
105
                end if;
106
        end process htif_fromhost;
107
 
108
        --! Sends a word to the host over the HTIF interface.
109
        htif_tohost: process(clk)
110
        begin
111
                if rising_edge(clk) then
112
                        if reset = '1' then
113
                                tohost_data <= (others => '0');
114
                                tohost_updated <= '0';
115
                        else
116 58 skordal
                                if write_mode /= CSR_WRITE_NONE and write_address = CSR_MTOHOST then
117 2 skordal
                                        tohost_data <= write_data_in;
118
                                        tohost_updated <= '1';
119
                                else
120
                                        tohost_updated <= '0';
121
                                end if;
122
                        end if;
123
                end if;
124
        end process htif_tohost;
125
 
126 58 skordal
        mtime_counter: process(timer_clk, reset)
127
        begin
128
                if reset = '1' then -- Asynchronous reset because timer_clk is slower than clk
129
                        counter_mtime <= (others => '0');
130
                elsif rising_edge(timer_clk) then
131
                        counter_mtime <= std_logic_vector(unsigned(counter_mtime) + 1);
132
                end if;
133
        end process mtime_counter;
134
 
135
        mtime_interrupt: process(clk)
136
        begin
137
                if rising_edge(clk) then
138
                        if reset = '1' then
139
                                timer_interrupt <= '0';
140
                        else
141
                                if write_mode /= CSR_WRITE_NONE and write_address = CSR_MTIMECMP then
142
                                        timer_interrupt <= '0';
143
                                elsif counter_mtime = mtime_compare then
144
                                        timer_interrupt <= '1';
145
                                end if;
146
                        end if;
147
                end if;
148
        end process mtime_interrupt;
149
 
150 2 skordal
        write: process(clk)
151
        begin
152
                if rising_edge(clk) then
153
                        if reset = '1' then
154 58 skordal
                                software_interrupt <= '0';
155
                                mtvec <= x"00000100";
156
                                mepc <= x"00000100";
157
                                mie <= (others => '0');
158
                                ie <= '0';
159
                                ie1 <= '0';
160 2 skordal
                        else
161
                                if exception_context_write = '1' then
162 58 skordal
                                        ie <= exception_context.ie;
163
                                        ie1 <= exception_context.ie1;
164
                                        mcause <= exception_context.cause;
165
                                        mbadaddr <= exception_context.badaddr;
166 2 skordal
                                end if;
167
 
168
                                if write_mode /= CSR_WRITE_NONE then
169
                                        case write_address is
170 58 skordal
                                                when CSR_MSTATUS => -- Status register
171
                                                        ie1 <= write_data_in(CSR_SR_IE1);
172
                                                        ie <= write_data_in(CSR_SR_IE);
173
                                                when CSR_MSCRATCH => -- Scratch register
174
                                                        mscratch <= write_data_in;
175
                                                when CSR_MEPC => -- Exception return address
176
                                                        mepc <= write_data_in;
177
                                                --when CSR_MCAUSE => -- Exception cause
178
                                                --      mcause <= write_data_in(31) & write_data_in(4 downto 0);
179
                                                when CSR_MTVEC => -- Exception vector address
180
                                                        mtvec <= write_data_in;
181
                                                when CSR_MTIMECMP => -- Time compare register
182
                                                        mtime_compare <= write_data_in;
183
                                                when CSR_MIE => -- Interrupt enable register:
184
                                                        mie <= write_data_in;
185
                                                when CSR_MIP => -- Interrupt pending register:
186
                                                        software_interrupt <= write_data_in(CSR_MIP_MSIP);
187 2 skordal
                                                when others =>
188
                                                        -- Ignore writes to invalid or read-only registers
189
                                        end case;
190
                                end if;
191
                        end if;
192
                end if;
193
        end process write;
194
 
195
        read: process(clk)
196
        begin
197
                if rising_edge(clk) then
198
 
199 58 skordal
                        if write_mode /= CSR_WRITE_NONE and write_address = CSR_MTVEC then
200
                                mtvec_out <= write_data_in;
201 2 skordal
                        else
202 58 skordal
                                mtvec_out <= mtvec;
203 2 skordal
                        end if;
204
 
205
                        if write_mode /= CSR_WRITE_NONE and write_address = read_address then
206
                                read_data_out <= write_data_in;
207
                        else
208
                                case read_address is
209 58 skordal
 
210
                                        -- Machine mode registers:
211
                                        when CSR_MCPUID => -- CPU features register
212
                                                read_data_out <= (
213
                                                                8 => '1', -- Set the bit corresponding to I
214
                                                                others => '0');
215
                                        when CSR_MIMPID => -- Implementation/Implementor ID
216
                                                read_data_out <= (31 downto 16 => '0') & x"8000";
217
                                                -- The anonymous source ID, 0x8000 is used until an open-source implementation ID
218
                                                -- is available for use.
219
                                        when CSR_MHARTID => -- Hardware thread ID
220 2 skordal
                                                read_data_out <= PROCESSOR_ID;
221 58 skordal
                                        when CSR_MFROMHOST => -- Data from a host environment
222 2 skordal
                                                read_data_out <= fromhost;
223 58 skordal
                                        when CSR_MSTATUS => -- Status register
224
                                                read_data_out <= csr_make_mstatus(ie, ie1);
225
                                        when CSR_MSCRATCH => -- Scratch register
226
                                                read_data_out <= mscratch;
227
                                        when CSR_MEPC => -- Exception PC value
228
                                                read_data_out <= mepc;
229
                                        when CSR_MTVEC => -- Exception vector address
230
                                                read_data_out <= mtvec;
231
                                        when CSR_MTDELEG => -- Exception vector delegation register, unsupported
232
                                                read_data_out <= (others => '0');
233
                                        when CSR_MIP => -- Interrupt pending
234
                                                read_data_out <= irq & (CSR_MIP_MTIP => timer_interrupt, CSR_MIP_MSIP => software_interrupt,
235
                                                        23 downto 8 => '0', 6 downto 4 => '0', 2 downto 0 => '0');
236
                                        when CSR_MIE => -- Interrupt enable register
237
                                                read_data_out <= mie;
238
                                        when CSR_MBADADDR => -- Bad memory address
239
                                                read_data_out <= mbadaddr;
240
                                        when CSR_MCAUSE => -- Exception cause
241
                                                read_data_out <= mcause(5) & (30 downto 5 => '0') & mcause(4 downto 0); --to_std_logic_vector(mcause);
242 2 skordal
 
243
                                        -- Timers and counters:
244 58 skordal
                                        when CSR_MTIME => -- Machine time counter register
245
                                                read_data_out <= counter_mtime;
246
                                        when CSR_MTIMECMP => -- Machine time compare register
247
                                                read_data_out <= mtime_compare;
248
 
249 2 skordal
                                        when CSR_TIME =>
250
                                                read_data_out <= counter_time(31 downto 0);
251
                                        when CSR_TIMEH =>
252
                                                read_data_out <= counter_time(63 downto 32);
253
                                        when CSR_CYCLE =>
254
                                                read_data_out <= counter_cycle(31 downto 0);
255
                                        when CSR_CYCLEH =>
256
                                                read_data_out <= counter_cycle(63 downto 32);
257
                                        when CSR_INSTRET =>
258
                                                read_data_out <= counter_instret(31 downto 0);
259
                                        when CSR_INSTRETH =>
260
                                                read_data_out <= counter_instret(63 downto 32);
261
 
262
                                        -- Return zero from write-only registers and invalid register addresses:
263
                                        when others =>
264
                                                read_data_out <= (others => '0');
265
                                end case;
266
                        end if;
267
                end if;
268
        end process read;
269
 
270
        timer_counter: entity work.pp_counter
271
                port map(
272
                        clk => timer_clk,
273
                        reset => reset,
274
                        count => counter_time,
275
                        increment => '1'
276
                );
277
 
278
        cycle_counter: entity work.pp_counter
279
                port map(
280
                        clk => clk,
281
                        reset => reset,
282
                        count => counter_cycle,
283
                        increment => '1'
284
                );
285
 
286
        instret_counter: entity work.pp_counter
287
                port map(
288
                        clk => clk,
289
                        reset => reset,
290
                        count => counter_instret,
291
                        increment => count_instruction
292
                );
293
 
294
end architecture behaviour;

powered by: WebSVN 2.1.0

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