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