copyleft: gplv3 added and set repo to public
[calu.git] / cpu / src / extension_imp_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 use IEEE.STD_LOGIC_ARITH.ALL;
26 use IEEE.STD_LOGIC_UNSIGNED.ALL;
27
28 use work.common_pkg.all;
29 use work.core_pkg.all;
30
31
32 use work.mem_pkg.all;
33 use work.extension_pkg.all;
34 use work.extension_imp_pkg.all;
35
36 architecture behav of extension_imp is
37
38 signal w1_st_co, w1_st_co_nxt, w2_im_addr, w2_im_addr_nxt, w3_im_data, w3_im_data_nxt, w4_im_notused, w4_im_notused_nxt : gp_register_t;
39 signal new_im_data, new_im_data_nxt: std_logic;
40
41 begin
42
43
44 syn : process (clk, reset)
45 begin
46    if (reset = RESET_VALUE) then
47                         w1_st_co <= (others=>'0');
48                         w2_im_addr(31 downto 16) <= (others=>'0');
49                         -- todo mit einer konstante versehen
50                         w2_im_addr(15 downto 0) <= x"0003";
51                         w3_im_data <= (others=>'0');
52                         w4_im_notused <= (others=>'0');
53                         --im only
54                         new_im_data <= '0';
55
56
57         elsif rising_edge(clk) then            
58                         w1_st_co <= w1_st_co_nxt;
59                         w2_im_addr <= w2_im_addr_nxt;
60                         w3_im_data <= w3_im_data_nxt;
61                         w4_im_notused <= w4_im_notused_nxt;
62                         --im only
63                         new_im_data <= new_im_data_nxt;
64
65    end if;
66 end process syn;
67
68 -------------------------- LESEN UND SCHREIBEN ANFANG ------------------------------------------------------------
69
70 gwriten : process (ext_reg,w1_st_co,w2_im_addr,w3_im_data,w4_im_notused)
71
72 variable tmp_data  : gp_register_t;
73
74 begin
75
76                 w1_st_co_nxt <= w1_st_co;
77                 w2_im_addr_nxt <= w2_im_addr;
78                 w3_im_data_nxt <= w3_im_data;
79                 w4_im_notused_nxt <= w4_im_notused;
80
81         if ext_reg.sel = '1' and ext_reg.wr_en = '1' then
82                 tmp_data := (others =>'0');                     
83                 if ext_reg.byte_en(0) = '1' then
84                         tmp_data(byte_t'range) :=ext_reg.data(byte_t'range);
85                 end if;
86                 if ext_reg.byte_en(1) = '1' then
87                         tmp_data((2*byte_t'length-1) downto byte_t'length) := ext_reg.data((2*byte_t'length-1) downto byte_t'length);
88                 end if;
89                 if ext_reg.byte_en(2) = '1' then
90                         tmp_data((3*byte_t'length-1) downto 2*byte_t'length) := ext_reg.data((3*byte_t'length-1) downto 2*byte_t'length);
91                 end if;
92                 if ext_reg.byte_en(3) = '1' then
93                         tmp_data((4*byte_t'length-1) downto 3*byte_t'length) := ext_reg.data((4*byte_t'length-1) downto 3*byte_t'length);
94                 end if;
95
96                 case ext_reg.addr(1 downto 0) is
97                 when "00" => 
98                         w1_st_co_nxt <= tmp_data;
99                 when "01" =>
100                         -- -1 wegen increment des addr registers
101                         tmp_data := tmp_data - '1';
102                         w2_im_addr_nxt <= tmp_data;
103                 when "10" =>
104                         w1_st_co_nxt(0) <= '1'; -- busy flag set
105                         w2_im_addr_nxt <= w2_im_addr + '1';
106                         w3_im_data_nxt <= tmp_data;
107                 when "11" =>
108                         --w4_im_notused_nxt <= tmp_data; sollte nur gelesen werden
109                 when others => null;
110                 end case;
111         end if;
112
113 end process gwriten;
114
115 gread : process (clk,ext_reg,w1_st_co,w2_im_addr,w3_im_data,w4_im_notused)
116
117 variable tmp_data  : gp_register_t;
118
119 begin
120         if ext_reg.sel = '1' and ext_reg.wr_en = '0' then
121                 case ext_reg.addr(1 downto 0) is
122                 when "00" => 
123                         tmp_data := (others =>'0');                     
124                         if ext_reg.byte_en(0) = '1' then
125                                 tmp_data(byte_t'range) := w1_st_co(byte_t'range);
126                         end if;
127                         if ext_reg.byte_en(1) = '1' then
128                                 tmp_data((2*byte_t'length-1) downto byte_t'length) := w1_st_co((2*byte_t'length-1) downto byte_t'length);
129                         end if;
130                         if ext_reg.byte_en(2) = '1' then
131                                 tmp_data((3*byte_t'length-1) downto 2*byte_t'length) := w1_st_co((3*byte_t'length-1) downto 2*byte_t'length);
132                         end if;
133                         if ext_reg.byte_en(3) = '1' then
134                                 tmp_data((4*byte_t'length-1) downto 3*byte_t'length) := w1_st_co((4*byte_t'length-1) downto 3*byte_t'length);
135                         end if;
136                         data_out <= tmp_data;
137                 when "01" =>
138                         tmp_data := (others =>'0');                     
139                         if ext_reg.byte_en(0) = '1' then
140                                 tmp_data(byte_t'range) := w2_im_addr(byte_t'range);
141                         end if;
142                         if ext_reg.byte_en(1) = '1' then
143                                 tmp_data((2*byte_t'length-1) downto byte_t'length) := w2_im_addr((2*byte_t'length-1) downto byte_t'length);
144                         end if;
145                         if ext_reg.byte_en(2) = '1' then
146                                 tmp_data((3*byte_t'length-1) downto 2*byte_t'length) := w2_im_addr((3*byte_t'length-1) downto 2*byte_t'length);
147                         end if;
148                         if ext_reg.byte_en(3) = '1' then
149                                 tmp_data((4*byte_t'length-1) downto 3*byte_t'length) := w2_im_addr((4*byte_t'length-1) downto 3*byte_t'length);
150                         end if;
151                         data_out <= tmp_data;
152                 when "10" =>
153                         tmp_data := (others =>'0');                     
154                         if ext_reg.byte_en(0) = '1' then
155                                 tmp_data(byte_t'range) := w3_im_data(byte_t'range);
156                         end if;
157                         if ext_reg.byte_en(1) = '1' then
158                                 tmp_data((2*byte_t'length-1) downto byte_t'length) := w3_im_data((2*byte_t'length-1) downto byte_t'length);
159                         end if;
160                         if ext_reg.byte_en(2) = '1' then
161                                 tmp_data((3*byte_t'length-1) downto 2*byte_t'length) := w3_im_data((3*byte_t'length-1) downto 2*byte_t'length);
162                         end if;
163                         if ext_reg.byte_en(3) = '1' then
164                                 tmp_data((4*byte_t'length-1) downto 3*byte_t'length) := w3_im_data((4*byte_t'length-1) downto 3*byte_t'length);
165                         end if;
166                         data_out <= tmp_data;
167                 when "11" =>
168                         tmp_data := (others =>'0');     
169                         if ext_reg.byte_en(0) = '1' then
170                                 tmp_data(byte_t'range) := w4_im_notused(byte_t'range);
171                         end if;
172                         if ext_reg.byte_en(1) = '1' then
173                                 tmp_data((2*byte_t'length-1) downto byte_t'length) := w4_im_notused((2*byte_t'length-1) downto byte_t'length);
174                         end if;
175                         if ext_reg.byte_en(2) = '1' then
176                                 tmp_data((3*byte_t'length-1) downto 2*byte_t'length) := w4_im_notused((3*byte_t'length-1) downto 2*byte_t'length);
177                         end if;
178                         if ext_reg.byte_en(3) = '1' then
179                                 tmp_data((4*byte_t'length-1) downto 3*byte_t'length) := w4_im_notused((4*byte_t'length-1) downto 3*byte_t'length);
180                         end if;
181                         data_out <= tmp_data;
182                 when others => null;
183                 end case;
184         else
185                 data_out  <= (others=>'0');             
186         end if;
187 end process gread;
188
189
190 -------------------------- LESEN UND SCHREIBEN ENDE ---------------------------------------------------------------
191
192 -------------------------- INTERNE VERARBEITUNG ANFANG ------------------------------------------------------------
193
194 dataprocess : process (ext_reg)
195
196
197 begin
198 new_im_data_nxt <= '0';
199 if ext_reg.sel = '1' and ext_reg.wr_en = '1' then
200                 case ext_reg.addr(1 downto 0) is
201                 when "00" => 
202
203                 when "01" =>
204
205                 when "10" =>
206                         new_im_data_nxt <= '1';
207                 when "11" =>
208                 
209                 when others => null;
210                 end case;
211         end if;
212
213 end process dataprocess;
214 -- asyncrone verarbeitung
215 im_addr <= w2_im_addr;
216 im_data <= w3_im_data;
217 new_im_data_out <= new_im_data;
218
219
220
221
222 -------------------------- INTERNE VERARBEITUNG ENDE --------------------------------------------------------------
223
224 end behav;
225