copyleft: gplv3 added and set repo to public
[calu.git] / cpu / src / writeback_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.common_pkg.all;
27 use work.core_pkg.all;
28
29 use work.mem_pkg.all;
30 use work.extension_pkg.all;
31 use work.extension_uart_pkg.all;
32 use work.extension_7seg_pkg.all;
33 use work.extension_imp_pkg.all;
34 use work.extension_timer_pkg.all;
35
36 architecture behav of writeback_stage is
37
38 signal data_ram_read, data_ram_read_ext : word_t;
39 signal data_addr : word_t;
40
41 signal wb_reg, wb_reg_nxt : writeback_rec;
42
43 signal ext_uart,ext_timer,ext_gpmp,ext_7seg,ext_int,ext_imp :  extmod_rec;
44 signal ext_uart_out, ext_timer_out, ext_gpmp_out, ext_int_out,ext_imp_out : gp_register_t;
45
46 --signal int_req : interrupt_t;
47 signal uart_int : std_logic;
48
49
50 signal sel_nxt, dmem_we, ext_anysel : std_logic;
51
52 signal calc_mem_res : gp_register_t;
53
54 begin
55         ext_gpmp_out <= (others => '0'); --TODO: delete when gpm is connected
56
57         spartan3e: if FPGATYPE = "s3e" generate
58                 data_ram : ram_xilinx
59                 generic map (
60                         DATA_ADDR_WIDTH
61                 )
62                 port map (
63                         clk,
64                         data_addr(DATA_ADDR_WIDTH+1 downto 2),
65                         data_addr(DATA_ADDR_WIDTH+1 downto 2),
66                         wb_reg_nxt.byte_en,
67                         dmem_we,
68                         wb_reg_nxt.data, --ram_data,
69                         data_ram_read
70                 );
71         end generate;
72         -- else generate gibt es erst mit vhdl 2008 ...
73         altera: if FPGATYPE /= "s3e" generate
74         data_ram : r_w_ram_be
75                 generic map (
76                         DATA_ADDR_WIDTH
77                 )
78                 
79                 port map (
80                         clk,
81                         data_addr(DATA_ADDR_WIDTH+1 downto 2),
82                         data_addr(DATA_ADDR_WIDTH+1 downto 2),
83                         wb_reg_nxt.byte_en,
84                         dmem_we,
85                         wb_reg_nxt.data, --ram_data,
86                         data_ram_read
87                 );
88         end generate;
89
90 uart : extension_uart 
91         generic map(
92                 RESET_VALUE,
93                 CLK_BAUD
94                 )
95         port map(
96                         clk ,
97                         reset,
98                         ext_uart,
99                         ext_uart_out,
100                         uart_int,
101                         bus_rx,
102                         bus_tx
103                 );
104         
105 imp : extension_imp 
106         generic map(
107                 RESET_VALUE
108                 )
109         port map(
110                         clk ,
111                         reset,
112                         ext_imp,
113                         ext_imp_out,
114                         im_addr,
115                         im_data,
116                         new_im_data_out
117                 );
118         
119         rem7seg: if "a" /= "a" generate
120
121         altera_7seg: if FPGATYPE /= "s3e" generate
122 sseg : extension_7seg
123         generic map(
124                 RESET_VALUE
125                 )
126         port map(
127                 clk,
128                 reset,
129                 --ext_7seg,
130                 ext_7seg
131                 --sseg0,
132                 --sseg1,
133                 --sseg2,
134                 --sseg3
135                 );
136         end generate;
137         end generate;
138
139 interrupt : extension_interrupt
140         generic map(
141                 RESET_VALUE
142                 )
143         port map(
144                 clk,
145                 reset,
146                 ext_int,
147                 ext_int_out,
148
149                 uart_int,
150
151                 int_req
152
153                 );
154
155 timer : extension_timer
156         generic map(RESET_VALUE)
157         port map(clk, reset, ext_timer, ext_timer_out);
158         
159 syn: process(clk, reset)
160
161 begin
162
163         if (reset = RESET_VALUE) then
164                 wb_reg.address <= (others => '0');
165                 wb_reg.dmem_en <= '0';
166                 wb_reg.dmem_write_en <= '0';
167                 wb_reg.hword <= '0';
168                 wb_reg.byte_s <= '0';
169                 
170                 wb_reg.byte_en <= (others => '0');
171                 wb_reg.data <= (others =>'0');
172         elsif rising_edge(clk) then
173                 wb_reg <= wb_reg_nxt;
174         end if;
175         
176 end process; 
177
178 --      type writeback_rec is record
179 --              address : in word_t;            --ureg 
180 --              dmem_en : in std_logic;         --ureg (jump addr in mem or in address)
181 --              dmem_write_en : in std_logic;   --ureg
182 --              hword_hl : in std_logic         --ureg
183 --      end record;
184
185
186
187 shift_input: process(data_ram_read, address, dmem_en, dmem_write_en, hword, wb_reg, result, byte_s, alu_jmp, br_pred, write_en, ram_data)
188 variable byte_en : byte_en_t;
189 variable address_val : std_logic_vector(1 downto 0);
190 begin
191         wb_reg_nxt.address <= address;
192         wb_reg_nxt.dmem_en <= dmem_en;
193         wb_reg_nxt.dmem_write_en <= dmem_write_en;
194         wb_reg_nxt.hword <= hword;
195         wb_reg_nxt.byte_s <= byte_s;
196
197         calc_mem_res <= result; --(others => '0');
198         
199         wb_reg_nxt.data <= ram_data;
200         byte_en := (others => '0');
201         address_val := address(BYTEADDR-1 downto 0);
202         if dmem_en = '1' then
203                 if hword = '1' then
204 --                      case address(BYTEADDR-1 downto 0) is
205                         case address_val is
206                         when "00" => 
207                                 byte_en(1 downto 0) := "11";
208                         when "10" => 
209                                 byte_en(3 downto 2) := "11";
210                                 wb_reg_nxt.data(31 downto 16) <= ram_data(15 downto 0);
211                         when others => null;
212                         end case;
213                 elsif byte_s = '1' then
214 --                      case address(BYTEADDR-1 downto 0) is
215                         case address_val is
216                         when "00" => byte_en(0) := '1';
217                         when "01" => 
218                                 byte_en(1) := '1';
219                                 wb_reg_nxt.data(15 downto 8) <= ram_data(7 downto 0);
220                         when "10" => 
221                                 byte_en(2) := '1';
222                                 wb_reg_nxt.data(23 downto 16) <= ram_data(7 downto 0);
223                         when "11" => 
224                                 byte_en(3) := '1';
225                                 wb_reg_nxt.data(31 downto 24) <= ram_data(7 downto 0);
226                         when others => null;
227                         end case;
228                 else
229                         byte_en := (others => '1');
230                 end if;
231         end if;
232         wb_reg_nxt.byte_en <= byte_en;
233         
234         -- if (wb_reg.dmem_en = '1' and wb_reg.dmem_write_en = '0') then        -- ram read operation --alu_jmp = '0' and 
235                 -- calc_mem_res <= data_ram_read;
236                 -- if (wb_reg.hword = '1') then
237                         -- calc_mem_res <= (others => '0');
238                         -- if (wb_reg.address(1) = '1') then
239                                 -- calc_mem_res(15 downto 0) <= data_ram_read(31 downto 16);
240                         -- else
241                                 -- calc_mem_res(15 downto 0) <= data_ram_read(15 downto 0);
242                         -- end if;
243                 -- end if;
244                 -- if (wb_reg.byte_s = '1') then
245                         -- calc_mem_res <= (others => '0');
246                         -- case wb_reg.address(1 downto 0) is
247                                 -- when "00" => calc_mem_res(7 downto 0) <= data_ram_read(7 downto 0);
248                                 -- when "01" => calc_mem_res(7 downto 0) <= data_ram_read(15 downto 8);
249                                 -- when "10" => calc_mem_res(7 downto 0) <= data_ram_read(23 downto 16);
250                                 -- when "11" => calc_mem_res(7 downto 0) <= data_ram_read(31 downto 24);
251                                 -- when others => null;
252                         -- end case;
253                 -- end if;      
254         -- end if;
255
256         --jump <= (alu_jmp xor br_pred) and (write_en or wb_reg.dmem_en);
257         jump <= (alu_jmp xor br_pred);-- and (write_en or wb_reg.dmem_en);
258
259         if (alu_jmp = '1' and wb_reg.dmem_en = '1' and wb_reg.dmem_write_en = '0' and write_en = '0') then
260                 jump_addr <= data_ram_read;
261         else
262                 jump_addr <= result;
263         end if;
264
265 --      if alu_jmp = '0' and br_pred = '1' and write_en = '0' then
266 --              jump <= '1';
267 --      end if;
268
269 --      if ((alu_jmp and wb_reg.dmem_en) = '1') then
270 --              jump_addr <= data_ram_read;
271 --      end if; 
272
273 end process;
274
275 --                      result : in gp_register_t;      --reg  (alu result or jumpaddr)
276 --                      result_addr : in gp_addr_t;     --reg
277 --                      address : in word_t;            --ureg 
278 --                      alu_jmp : in std_logic;         --reg
279 --                      br_pred : in std_logic;         --reg
280 --                      write_en : in std_logic;        --reg  (register file)
281 --                      dmem_en : in std_logic;         --ureg (jump addr in mem or in result)
282 --                      dmem_write_en : in std_logic;   --ureg
283 --                      hword : in std_logic            --ureg
284
285
286
287 out_logic: process(write_en, result_addr, wb_reg, alu_jmp, wb_reg_nxt, data_ram_read_ext, calc_mem_res, data_ram_read, ext_anysel, result, hword, byte_s)
288 variable reg_we_v : std_logic;
289 variable data_out : gp_register_t;
290 begin
291     reg_we_v := (write_en or (wb_reg.dmem_en and not(wb_reg.dmem_write_en))) and not(alu_jmp);
292         reg_addr <= result_addr;
293
294         data_addr <= (others => '0');
295         dmem_we <= '0';
296         
297         if (wb_reg.address(DATA_ADDR_WIDTH+3) /= '1') then
298                 data_out := data_ram_read;
299         else
300                 reg_we_v := reg_we_v and (ext_anysel or not(wb_reg.dmem_en));
301                 data_out := data_ram_read_ext;
302         end if;
303         
304         if wb_reg.byte_en(0) = '0' then
305                 data_out(byte_t'range) := (others => '0');
306         end if;
307         if wb_reg.byte_en(1) = '0' then
308                 data_out(2*byte_t'length-1 downto byte_t'length) := (others => '0');
309         end if;
310         if wb_reg.byte_en(2) = '0' then
311                 data_out(3*byte_t'length-1 downto 2*byte_t'length) := (others => '0');
312         end if;
313         if wb_reg.byte_en(3) = '0' then
314                 data_out(4*byte_t'length-1 downto 3*byte_t'length) := (others => '0');
315         end if;
316         
317         
318 --      if wb_reg.hword = '1' or wb_reg.byte_s = '1' then
319 --              if wb_reg.address(1)='1' then
320 --                      data_out(hword_t'range) := data_out(data_out'high downto (data_out'length/2));
321 --              end if;
322 --              data_out(data_out'high downto (data_out'length/2)) := (others => '0');
323 --              if byte_s = '1' then
324 --                      if wb_reg.address(0) = '1' then
325 --                              data_out(byte_t'range) := data_out(hword_t'high downto (hword_t'length/2));
326 --                      end if;
327 --                      data_out(hword_t'high downto (hword_t'length/2)) := (others => '0');
328 --              end if;
329 --      end if;
330         
331         
332         data_out := to_stdlogicvector(to_bitvector(data_out) srl to_integer(unsigned(wb_reg.address(BYTEADDR-1 downto 0)))*byte_t'length); 
333         
334         if (wb_reg_nxt.address(DATA_ADDR_WIDTH+3) /= '1') then
335                 data_addr(DATA_ADDR_WIDTH+1 downto 0) <= wb_reg_nxt.address(DATA_ADDR_WIDTH+1 downto 0);
336                 dmem_we <= wb_reg_nxt.dmem_write_en;
337         end if;
338         
339         regfile_val <= data_out;
340         
341         if wb_reg.dmem_en = '0' then
342                 regfile_val <= result;
343         end if;
344         
345         reg_we <= reg_we_v;
346         
347 end process;
348
349
350 addr_de_mult: process(wb_reg, wb_reg_nxt, ram_data, sel_nxt, ext_uart_out, ext_gpmp_out, ext_timer_out)
351 variable wr_en, enable  : std_logic; -- these are all registered
352 variable byte_en : byte_en_t; -- if a module needs the nxt signals it has to manually select them
353 variable addr : ext_addr_t;   -- for example the data memory, because it already has input registers
354 variable addrid : std_logic_vector(27 downto 0);--ext_addrid_t;
355 variable data : gp_register_t;
356 begin
357
358  --if selecting enable is too slow, see alu_b
359   enable := wb_reg.dmem_en;
360   wr_en  := wb_reg.dmem_write_en;
361   byte_en := wb_reg.byte_en;
362   addr := wb_reg.address(gp_register_t'high downto BYTEADDR);
363   addrid := wb_reg.address(gp_register_t'high downto EXTWORDS);
364   data := wb_reg.data;
365
366   ext_uart.sel <='0';
367   ext_7seg.sel <='0';
368   ext_timer.sel <='0';
369   ext_gpmp.sel <='0';
370   ext_int.sel <= '0';
371   ext_imp.sel <= '0';
372   
373   ext_uart.wr_en <= wr_en;
374   ext_7seg.wr_en <= wr_en;
375   ext_timer.wr_en <= wr_en;
376   ext_gpmp.wr_en <= wr_en;
377   ext_int.wr_en <= wr_en;  
378   ext_imp.wr_en <= wr_en;  
379
380   ext_uart.byte_en <= byte_en;
381   ext_7seg.byte_en <= byte_en;
382   ext_timer.byte_en <= byte_en;
383   ext_gpmp.byte_en <= byte_en;
384   ext_int.byte_en <= byte_en;  
385   ext_imp.byte_en <= byte_en; 
386
387   ext_uart.addr <= addr;
388   ext_7seg.addr <= addr;
389   ext_timer.addr <= addr;
390   ext_gpmp.addr <= addr;
391   ext_int.addr <= addr;
392   ext_imp.addr <= addr;
393
394   ext_uart.data <= data;
395   ext_7seg.data <= data;
396   ext_timer.data <= data;
397   ext_gpmp.data <= data;
398   ext_int.data <= data;
399   ext_imp.data <= data;
400
401    -- wenn ich hier statt dem 4rer die konstante nehme dann gibts an fehler wegen nicht lokaler variable -.-
402  case addrid is
403     when EXT_UART_ADDR => 
404         ext_uart.sel <= enable;
405         ext_anysel <= enable;
406
407 --              ext_uart.wr_en <= wb_reg_nxt.dmem_write_en;
408 --              ext_uart.data <= ram_data;
409 --              ext_uart.addr <= wb_reg_nxt.address(31 downto 2);
410 --              case wb_reg_nxt.address(1 downto 0) is
411 --                              when "00" => ext_uart.byte_en <= "0001";
412 --                              when "01" => ext_uart.byte_en <= "0010";
413 --                              when "10" => ext_uart.byte_en <= "0100";
414 --                              --when "11" => ext_uart.byte_en <= "1000";
415 --                              when "11" => ext_uart.byte_en <= "1111";
416 --                              when others => null;
417 --                      end case;
418     when EXT_IMP_ADDR => 
419         ext_imp.sel <= enable;
420         ext_anysel <= enable;
421
422 --              ext_uart.wr_en <= wb_reg_nxt.dmem_write_en;
423 --              ext_uart.data <= ram_data;
424 --              ext_uart.addr <= wb_reg_nxt.address(31 downto 2);
425 --              case wb_reg_nxt.address(1 downto 0) is
426 --                              when "00" => ext_uart.byte_en <= "0001";
427 --                              when "01" => ext_uart.byte_en <= "0010";
428 --                              when "10" => ext_uart.byte_en <= "0100";
429 --                              --when "11" => ext_uart.byte_en <= "1000";
430 --                              when "11" => ext_uart.byte_en <= "1111";
431 --                              when others => null;
432 --                      end case;
433
434     when EXT_INT_ADDR => 
435         ext_int.sel <= enable;
436         ext_anysel <= enable;
437
438 --              ext_uart.wr_en <= wb_reg_nxt.dmem_write_en;
439 --              ext_uart.data <= ram_data;
440 --              ext_uart.addr <= wb_reg_nxt.address(31 downto 2);
441 --              case wb_reg_nxt.address(1 downto 0) is
442 --                              when "00" => ext_uart.byte_en <= "0001";
443 --                              when "01" => ext_uart.byte_en <= "0010";
444 --                              when "10" => ext_uart.byte_en <= "0100";
445 --                              --when "11" => ext_uart.byte_en <= "1000";
446 --                              when "11" => ext_uart.byte_en <= "1111";
447 --                              when others => null;
448 --                      end case;
449
450         when EXT_7SEG_ADDR => 
451                 ext_7seg.sel <= enable;
452                 ext_anysel <= enable;
453
454                 -- ext_7seg.wr_en <= wb_regdmem_write_en;
455                 -- ext_7seg.data <= ram_data;
456                 -- ext_7seg.addr <= wb_reg_nxt.address(31 downto 2);
457                 -- ext_7seg.byte_en(1 downto 0) <= wb_reg_nxt.address(1 downto 0);
458
459                 
460 --              case wb_reg_nxt.address(1 downto 0) is
461 --                      when "00" => ext_7seg.byte_en <= "0001";
462 --                      when "01" => ext_7seg.byte_en <= "0010";
463 --                      when "10" => ext_7seg.byte_en <= "0100";
464 --                      when "11" => ext_7seg.byte_en <= "1000";
465 --                      when others => null;
466 --              end case;
467                         
468         when EXT_TIMER_ADDR => 
469                 ext_timer.sel <= enable;
470                 ext_anysel <= enable;
471                 -- ext_timer.wr_en <= wb_reg_nxt.dmem_write_en;
472                 -- ext_timer.data <= ram_data;
473                 -- ext_timer.addr <= wb_reg_nxt.address(wb_reg_nxt.address'high downto BYTEADDR);
474                 -- case wb_reg.address(1 downto 0) is
475                                 -- when "00" => ext_timer.byte_en <= "0001";
476                                 -- when "01" => ext_timer.byte_en <= "0010";
477                                 -- when "10" => ext_timer.byte_en <= "0100";
478                                 -- when "11" => ext_timer.byte_en <= "1000";
479                                 -- when others => null;
480                         -- end case;
481 --      when EXT_GPMP_ADDR => 
482  --             ext_gpmp.sel <= enable;
483 --              ext_anysel <= enable;
484                 -- ext_gpmp.wr_en <= wb_reg_nxt.dmem_write_en;
485                 -- ext_gpmp.data <= ram_data;
486                 -- ext_gpmp.addr <= wb_reg_nxt.address(wb_reg_nxt.address'high downto BYTEADDR);
487                 -- case wb_reg.address(1 downto 0) is
488                                 -- when "00" => ext_gpmp.byte_en <= "0001";
489                                 -- when "01" => ext_gpmp.byte_en <= "0010";
490                                 -- when "10" => ext_gpmp.byte_en <= "0100";
491                                 -- when "11" => ext_gpmp.byte_en <= "1000";
492                                 -- when others => null;
493                         -- end case;
494         -- hier kann man weiter extensions adden :) Konstanten sind im extension pkg definiert 
495         when others => ext_anysel <= '0';
496         end case;
497         
498         data_ram_read_ext <= ext_uart_out or ext_gpmp_out or ext_timer_out;
499 end process;
500
501 end behav;
502