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