copyleft: gplv3 added and set repo to public
[calu.git] / cpu / src / fetch_stage_b.vhd
1 --   `Deep Thought', a softcore CPU implemented on a FPGA
2 --
3 --  Copyright (C) 2010 Markus Hofstaetter <markus.manrow@gmx.at>
4 --  Copyright (C) 2010 Martin Perner <e0725782@student.tuwien.ac.at>
5 --  Copyright (C) 2010 Stefan Rebernig <stefan.rebernig@gmail.com>
6 --  Copyright (C) 2010 Manfred Schwarz <e0725898@student.tuwien.ac.at>
7 --  Copyright (C) 2010 Bernhard Urban <lewurm@gmail.com>
8 --
9 --  This program is free software: you can redistribute it and/or modify
10 --  it under the terms of the GNU General Public License as published by
11 --  the Free Software Foundation, either version 3 of the License, or
12 --  (at your option) any later version.
13 --
14 --  This program is distributed in the hope that it will be useful,
15 --  but WITHOUT ANY WARRANTY; without even the implied warranty of
16 --  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 --  GNU General Public License for more details.
18 --
19 --  You should have received a copy of the GNU General Public License
20 --  along with this program.  If not, see <http://www.gnu.org/licenses/>.
21
22 library IEEE;
23 use IEEE.std_logic_1164.all;
24 use IEEE.numeric_std.all;
25
26 use work.core_pkg.all;
27 use work.common_pkg.all;
28 use work.mem_pkg.all;
29
30 architecture behav of fetch_stage is
31
32 signal instr_w_addr      : instruction_addr_t;
33 signal instr_r_addr      : instruction_addr_t;
34 signal instr_r_addr_nxt  : instruction_addr_t;
35 signal instr_we          : std_logic;
36 signal instr_wr_data     : instruction_word_t;
37 signal instr_rd_data_rom, instr_rd_data          : instruction_word_t;
38 signal rom_ram, rom_ram_nxt : std_logic;
39
40 begin
41
42         instruction_ram : r_w_ram --rom
43                 generic map (
44                         PHYS_INSTR_ADDR_WIDTH,
45                         WORD_WIDTH
46                 )
47                 
48                 port map (
49                         clk,
50                         im_addr(PHYS_INSTR_ADDR_WIDTH-1 downto 0),
51                         instr_r_addr_nxt(PHYS_INSTR_ADDR_WIDTH-1 downto 0),
52                         new_im_data_in,
53                         im_data,
54                         instr_rd_data
55                 );
56                 
57         instruction_rom : rom
58                 generic map (
59                         ROM_INSTR_ADDR_WIDTH,
60                         WORD_WIDTH
61                 )
62                 
63                 port map (
64                         clk,
65                         instr_r_addr_nxt(ROM_INSTR_ADDR_WIDTH-1 downto 0),
66                         instr_rd_data_rom
67                 );
68                 
69
70 syn: process(clk, reset)
71
72 begin
73
74         if (reset = RESET_VALUE) then
75                 instr_r_addr <= (others => '0');
76                 rom_ram <= ROM_USE;
77                 led2 <= '0';
78         elsif rising_edge(clk) then
79                 instr_r_addr <= instr_r_addr_nxt;               
80                 rom_ram <= rom_ram_nxt;
81                 led2 <= rom_ram; --rom_ram_nxt;
82         end if;
83         
84 end process; 
85
86
87 asyn: process(reset, s_reset, instr_r_addr, jump_result, prediction_result, branch_prediction_bit, alu_jump_bit, instr_rd_data, rom_ram, instr_rd_data_rom, int_req)
88 variable instr_pc  : instruction_addr_t;
89 begin
90         rom_ram_nxt <= rom_ram;
91         
92         case rom_ram is
93                 when ROM_USE =>
94                         instruction <= instr_rd_data_rom;
95                 when RAM_USE =>
96                         instruction <= instr_rd_data;
97                 when others => 
98                         instruction <= x"F0000000";
99         end case;
100         instr_pc := std_logic_vector(unsigned(instr_r_addr) + 1);
101         instr_r_addr_nxt <= instr_pc;
102
103         if (instr_pc = x"0000007f" and rom_ram = ROM_USE) then
104                 rom_ram_nxt <= RAM_USE;
105                 instr_r_addr_nxt <= (others => '0');
106         end if;
107
108         if (reset = RESET_VALUE) then
109                 instr_r_addr_nxt <= (others => '0');
110         end if;
111
112         if (alu_jump_bit = LOGIC_ACT and int_req = IDLE) then
113                 instr_r_addr_nxt <= jump_result;
114                 instruction(31 downto 28) <= "1111";    
115         elsif (branch_prediction_bit = LOGIC_ACT) then
116                 instr_r_addr_nxt <= prediction_result;
117         end if; 
118
119         case int_req is
120                 when UART =>
121                         instruction(31 downto 0) <= (others => '0');
122                         instruction(31 downto 28) <= "1110";
123                         instruction(27 downto 23) <= "10110";
124                         instruction(PHYS_INSTR_ADDR_WIDTH + 7 - 1 downto 7) <= UART_INT_VECTOR;
125                         instruction(6 downto 4) <= "001";
126                         instruction(3 downto 2) <= "01";
127                         instruction(1 downto 0) <= "10";
128
129 --                      instr_r_addr_nxt <= instr_r_addr; 
130                 when others => null;
131         end case;
132
133         if (s_reset = RESET_VALUE) then
134                 rom_ram_nxt <= RAM_USE;
135                 instr_r_addr_nxt <= (others => '0');
136         end if; 
137
138 end process;
139
140 out_logic : process (instr_r_addr, alu_jump_bit, int_req, jump_result)
141
142 begin
143         prog_cnt(PHYS_INSTR_ADDR_WIDTH-1 downto 0) <= std_logic_vector(unsigned(instr_r_addr(PHYS_INSTR_ADDR_WIDTH-1 downto 0)));
144         prog_cnt(INSTR_ADDR_WIDTH-1 downto PHYS_INSTR_ADDR_WIDTH) <= (others => '0');
145
146         if (int_req /= IDLE and alu_jump_bit = LOGIC_ACT ) then
147                 prog_cnt(PHYS_INSTR_ADDR_WIDTH-1 downto 0) <= jump_result(PHYS_INSTR_ADDR_WIDTH-1 downto 0);
148         end if;
149
150 end process;
151
152 end behav;
153