]> rtime.felk.cvut.cz Git - fpga/plasma.git/blob - vhdl/mlite_cpu.vhd
Local copy of Plasma MIPS project.
[fpga/plasma.git] / vhdl / mlite_cpu.vhd
1 ---------------------------------------------------------------------
2 -- TITLE: Plasma CPU core
3 -- AUTHOR: Steve Rhoads (rhoadss@yahoo.com)
4 -- DATE CREATED: 2/15/01
5 -- FILENAME: mlite_cpu.vhd
6 -- PROJECT: Plasma CPU core
7 -- COPYRIGHT: Software placed into the public domain by the author.
8 --    Software 'as is' without warranty.  Author liable for nothing.
9 -- NOTE:  MIPS(tm) and MIPS I(tm) are registered trademarks of MIPS 
10 --    Technologies.  MIPS Technologies does not endorse and is not 
11 --    associated with this project.
12 -- DESCRIPTION:
13 --    Top level VHDL document that ties the nine other entities together.
14 --
15 -- Executes all MIPS I(tm) opcodes but exceptions and non-aligned
16 -- memory accesses.  Based on information found in:
17 --    "MIPS RISC Architecture" by Gerry Kane and Joe Heinrich
18 --    and "The Designer's Guide to VHDL" by Peter J. Ashenden
19 --
20 -- The CPU is implemented as a two or three stage pipeline.
21 -- An add instruction would take the following steps (see cpu.gif):
22 -- Stage #0:
23 --    1.  The "pc_next" entity passes the program counter (PC) to the 
24 --        "mem_ctrl" entity which fetches the opcode from memory.
25 -- Stage #1:
26 --    2.  The memory returns the opcode.
27 -- Stage #2:
28 --    3.  "Mem_ctrl" passes the opcode to the "control" entity.
29 --    4.  "Control" converts the 32-bit opcode to a 60-bit VLWI opcode
30 --        and sends control signals to the other entities.
31 --    5.  Based on the rs_index and rt_index control signals, "reg_bank" 
32 --        sends the 32-bit reg_source and reg_target to "bus_mux".
33 --    6.  Based on the a_source and b_source control signals, "bus_mux"
34 --        multiplexes reg_source onto a_bus and reg_target onto b_bus.
35 -- Stage #3 (part of stage #2 if using two stage pipeline):
36 --    7.  Based on the alu_func control signals, "alu" adds the values
37 --        from a_bus and b_bus and places the result on c_bus.
38 --    8.  Based on the c_source control signals, "bus_bux" multiplexes
39 --        c_bus onto reg_dest.
40 --    9.  Based on the rd_index control signal, "reg_bank" saves
41 --        reg_dest into the correct register.
42 -- Stage #3b:
43 --   10.  Read or write memory if needed.
44 --
45 -- All signals are active high. 
46 -- Here are the signals for writing a character to address 0xffff
47 -- when using a two stage pipeline:
48 --
49 -- Program:
50 -- addr     value  opcode 
51 -- =============================
52 --   3c: 00000000  nop
53 --   40: 34040041  li $a0,0x41
54 --   44: 3405ffff  li $a1,0xffff
55 --   48: a0a40000  sb $a0,0($a1)
56 --   4c: 00000000  nop
57 --   50: 00000000  nop
58 --
59 --      intr_in                             mem_pause 
60 --  reset_in                               byte_we     Stages
61 --     ns         address     data_w     data_r        40 44 48 4c 50
62 --   3600  0  0  00000040   00000000   34040041  0  0   1  
63 --   3700  0  0  00000044   00000000   3405FFFF  0  0   2  1  
64 --   3800  0  0  00000048   00000000   A0A40000  0  0      2  1  
65 --   3900  0  0  0000004C   41414141   00000000  0  0         2  1
66 --   4000  0  0  0000FFFC   41414141   XXXXXX41  1  0         3  2  
67 --   4100  0  0  00000050   00000000   00000000  0  0               1
68 ---------------------------------------------------------------------
69 library ieee;
70 use work.mlite_pack.all;
71 use ieee.std_logic_1164.all;
72 use ieee.std_logic_unsigned.all;
73
74 entity mlite_cpu is
75    generic(memory_type     : string  := "XILINX_16X"; --ALTERA_LPM, or DUAL_PORT_
76            mult_type       : string  := "DEFAULT"; --AREA_OPTIMIZED
77            shifter_type    : string  := "DEFAULT"; --AREA_OPTIMIZED
78            alu_type        : string  := "DEFAULT"; --AREA_OPTIMIZED
79            pipeline_stages : natural := 2); --2 or 3
80    port(clk          : in std_logic;
81         reset_in     : in std_logic;
82         intr_in      : in std_logic;
83
84         address_next : out std_logic_vector(31 downto 2); --for synch ram
85         byte_we_next : out std_logic_vector(3 downto 0); 
86
87         address      : out std_logic_vector(31 downto 2);
88         byte_we      : out std_logic_vector(3 downto 0);
89         data_w       : out std_logic_vector(31 downto 0);
90         data_r       : in std_logic_vector(31 downto 0);
91         mem_pause    : in std_logic);
92 end; --entity mlite_cpu
93
94 architecture logic of mlite_cpu is
95    --When using a two stage pipeline "sigD <= sig".
96    --When using a three stage pipeline "sigD <= sig when rising_edge(clk)",
97    --  so sigD is delayed by one clock cycle.
98    signal opcode         : std_logic_vector(31 downto 0);
99    signal rs_index       : std_logic_vector(5 downto 0);
100    signal rt_index       : std_logic_vector(5 downto 0);
101    signal rd_index       : std_logic_vector(5 downto 0);
102    signal rd_indexD      : std_logic_vector(5 downto 0);
103    signal reg_source     : std_logic_vector(31 downto 0);
104    signal reg_target     : std_logic_vector(31 downto 0);
105    signal reg_dest       : std_logic_vector(31 downto 0);
106    signal reg_destD      : std_logic_vector(31 downto 0);
107    signal a_bus          : std_logic_vector(31 downto 0);
108    signal a_busD         : std_logic_vector(31 downto 0);
109    signal b_bus          : std_logic_vector(31 downto 0);
110    signal b_busD         : std_logic_vector(31 downto 0);
111    signal c_bus          : std_logic_vector(31 downto 0);
112    signal c_alu          : std_logic_vector(31 downto 0);
113    signal c_shift        : std_logic_vector(31 downto 0);
114    signal c_mult         : std_logic_vector(31 downto 0);
115    signal c_memory       : std_logic_vector(31 downto 0);
116    signal imm            : std_logic_vector(15 downto 0);
117    signal pc_future      : std_logic_vector(31 downto 2);
118    signal pc_current     : std_logic_vector(31 downto 2);
119    signal pc_plus4       : std_logic_vector(31 downto 2);
120    signal alu_func       : alu_function_type;
121    signal alu_funcD      : alu_function_type;
122    signal shift_func     : shift_function_type;
123    signal shift_funcD    : shift_function_type;
124    signal mult_func      : mult_function_type;
125    signal mult_funcD     : mult_function_type;
126    signal branch_func    : branch_function_type;
127    signal take_branch    : std_logic;
128    signal a_source       : a_source_type;
129    signal b_source       : b_source_type;
130    signal c_source       : c_source_type;
131    signal pc_source      : pc_source_type;
132    signal mem_source     : mem_source_type;
133    signal pause_mult     : std_logic;
134    signal pause_ctrl     : std_logic;
135    signal pause_pipeline : std_logic;
136    signal pause_any      : std_logic;
137    signal pause_non_ctrl : std_logic;
138    signal pause_bank     : std_logic;
139    signal nullify_op     : std_logic;
140    signal intr_enable    : std_logic;
141    signal intr_signal    : std_logic;
142    signal exception_sig  : std_logic;
143    signal reset_reg      : std_logic_vector(3 downto 0);
144    signal reset          : std_logic;
145 begin  --architecture
146
147    pause_any <= (mem_pause or pause_ctrl) or (pause_mult or pause_pipeline);
148    pause_non_ctrl <= (mem_pause or pause_mult) or pause_pipeline;
149    pause_bank <= (mem_pause or pause_ctrl or pause_mult) and not pause_pipeline;
150    nullify_op <= '1' when (pc_source = FROM_LBRANCH and take_branch = '0')
151                           or intr_signal = '1' or exception_sig = '1'
152                           else '0';
153    c_bus <= c_alu or c_shift or c_mult;
154    reset <= '1' when reset_in = '1' or reset_reg /= "1111" else '0';
155
156    --synchronize reset and interrupt pins
157    intr_proc: process(clk, reset_in, reset_reg, intr_in, intr_enable, 
158       pc_source, pc_current, pause_any)
159    begin
160       if reset_in = '1' then
161          reset_reg <= "0000";
162          intr_signal <= '0';
163       elsif rising_edge(clk) then
164          if reset_reg /= "1111" then
165             reset_reg <= reset_reg + 1;
166          end if;
167
168          --don't try to interrupt a multi-cycle instruction
169          if pause_any = '0' then
170             if intr_in = '1' and intr_enable = '1' and 
171                   pc_source = FROM_INC4 then
172                --the epc will contain pc+4
173                intr_signal <= '1';
174             else
175                intr_signal <= '0';
176             end if;
177          end if;
178
179       end if;
180    end process;
181
182    u1_pc_next: pc_next PORT MAP (
183         clk          => clk,
184         reset_in     => reset,
185         take_branch  => take_branch,
186         pause_in     => pause_any,
187         pc_new       => c_bus(31 downto 2),
188         opcode25_0   => opcode(25 downto 0),
189         pc_source    => pc_source,
190         pc_future    => pc_future,
191         pc_current   => pc_current,
192         pc_plus4     => pc_plus4);
193
194    u2_mem_ctrl: mem_ctrl 
195       PORT MAP (
196         clk          => clk,
197         reset_in     => reset,
198         pause_in     => pause_non_ctrl,
199         nullify_op   => nullify_op,
200         address_pc   => pc_future,
201         opcode_out   => opcode,
202
203         address_in   => c_bus,
204         mem_source   => mem_source,
205         data_write   => reg_target,
206         data_read    => c_memory,
207         pause_out    => pause_ctrl,
208         
209         address_next => address_next,
210         byte_we_next => byte_we_next,
211
212         address      => address,
213         byte_we      => byte_we,
214         data_w       => data_w,
215         data_r       => data_r);
216
217    u3_control: control PORT MAP (
218         opcode       => opcode,
219         intr_signal  => intr_signal,
220         rs_index     => rs_index,
221         rt_index     => rt_index,
222         rd_index     => rd_index,
223         imm_out      => imm,
224         alu_func     => alu_func,
225         shift_func   => shift_func,
226         mult_func    => mult_func,
227         branch_func  => branch_func,
228         a_source_out => a_source,
229         b_source_out => b_source,
230         c_source_out => c_source,
231         pc_source_out=> pc_source,
232         mem_source_out=> mem_source,
233         exception_out=> exception_sig);
234
235    u4_reg_bank: reg_bank 
236       generic map(memory_type => memory_type)
237       port map (
238         clk            => clk,
239         reset_in       => reset,
240         pause          => pause_bank,
241         rs_index       => rs_index,
242         rt_index       => rt_index,
243         rd_index       => rd_indexD,
244         reg_source_out => reg_source,
245         reg_target_out => reg_target,
246         reg_dest_new   => reg_destD,
247         intr_enable    => intr_enable);
248
249    u5_bus_mux: bus_mux port map (
250         imm_in       => imm,
251         reg_source   => reg_source,
252         a_mux        => a_source,
253         a_out        => a_bus,
254
255         reg_target   => reg_target,
256         b_mux        => b_source,
257         b_out        => b_bus,
258
259         c_bus        => c_bus,
260         c_memory     => c_memory,
261         c_pc         => pc_current,
262         c_pc_plus4   => pc_plus4,
263         c_mux        => c_source,
264         reg_dest_out => reg_dest,
265
266         branch_func  => branch_func,
267         take_branch  => take_branch);
268
269    u6_alu: alu 
270       generic map (alu_type => alu_type)
271       port map (
272         a_in         => a_busD,
273         b_in         => b_busD,
274         alu_function => alu_funcD,
275         c_alu        => c_alu);
276
277    u7_shifter: shifter
278       generic map (shifter_type => shifter_type)
279       port map (
280         value        => b_busD,
281         shift_amount => a_busD(4 downto 0),
282         shift_func   => shift_funcD,
283         c_shift      => c_shift);
284
285    u8_mult: mult 
286       generic map (mult_type => mult_type)
287       port map (
288         clk       => clk,
289         reset_in  => reset,
290         a         => a_busD,
291         b         => b_busD,
292         mult_func => mult_funcD,
293         c_mult    => c_mult,
294         pause_out => pause_mult);
295
296    pipeline2: if pipeline_stages <= 2 generate
297       a_busD <= a_bus;
298       b_busD <= b_bus;
299       alu_funcD <= alu_func;
300       shift_funcD <= shift_func;
301       mult_funcD <= mult_func;
302       rd_indexD <= rd_index;
303       reg_destD <= reg_dest;
304       pause_pipeline <= '0';
305    end generate; --pipeline2
306
307    pipeline3: if pipeline_stages > 2 generate
308       --When operating in three stage pipeline mode, the following signals
309       --are delayed by one clock cycle:  a_bus, b_bus, alu/shift/mult_func,
310       --c_source, and rd_index.
311    u9_pipeline: pipeline port map (
312         clk            => clk,
313         reset          => reset,
314         a_bus          => a_bus,
315         a_busD         => a_busD,
316         b_bus          => b_bus,
317         b_busD         => b_busD,
318         alu_func       => alu_func,
319         alu_funcD      => alu_funcD,
320         shift_func     => shift_func,
321         shift_funcD    => shift_funcD,
322         mult_func      => mult_func,
323         mult_funcD     => mult_funcD,
324         reg_dest       => reg_dest,
325         reg_destD      => reg_destD,
326         rd_index       => rd_index,
327         rd_indexD      => rd_indexD,
328
329         rs_index       => rs_index,
330         rt_index       => rt_index,
331         pc_source      => pc_source,
332         mem_source     => mem_source,
333         a_source       => a_source,
334         b_source       => b_source,
335         c_source       => c_source,
336         c_bus          => c_bus,
337         pause_any      => pause_any,
338         pause_pipeline => pause_pipeline);
339
340    end generate; --pipeline3
341
342 end; --architecture logic