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