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