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