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