2 use IEEE.std_logic_1164.all;
3 use IEEE.numeric_std.all;
5 use work.common_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;
15 architecture behav of writeback_stage is
17 signal data_ram_read, data_ram_read_ext : word_t;
18 signal data_addr : word_t;
20 signal wb_reg, wb_reg_nxt : writeback_rec;
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;
25 --signal int_req : interrupt_t;
26 signal uart_int : std_logic;
29 signal sel_nxt, dmem_we, ext_anysel : std_logic;
31 signal calc_mem_res : gp_register_t;
34 ext_gpmp_out <= (others => '0'); --TODO: delete when gpm is connected
36 spartan3e: if FPGATYPE = "s3e" generate
43 data_addr(DATA_ADDR_WIDTH+1 downto 2),
44 data_addr(DATA_ADDR_WIDTH+1 downto 2),
47 wb_reg_nxt.data, --ram_data,
51 -- else generate gibt es erst mit vhdl 2008 ...
52 altera: if FPGATYPE /= "s3e" generate
60 data_addr(DATA_ADDR_WIDTH+1 downto 2),
61 data_addr(DATA_ADDR_WIDTH+1 downto 2),
64 wb_reg_nxt.data, --ram_data,
98 altera_7seg: if FPGATYPE /= "s3e" generate
114 interrupt : extension_interrupt
130 timer : extension_timer
131 generic map(RESET_VALUE)
132 port map(clk, reset, ext_timer, ext_timer_out);
134 syn: process(clk, reset)
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';
143 wb_reg.byte_s <= '0';
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;
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
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);
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;
172 calc_mem_res <= result; --(others => '0');
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
179 -- case address(BYTEADDR-1 downto 0) is
182 byte_en(1 downto 0) := "11";
184 byte_en(3 downto 2) := "11";
185 wb_reg_nxt.data(31 downto 16) <= ram_data(15 downto 0);
188 elsif byte_s = '1' then
189 -- case address(BYTEADDR-1 downto 0) is
191 when "00" => byte_en(0) := '1';
194 wb_reg_nxt.data(15 downto 8) <= ram_data(7 downto 0);
197 wb_reg_nxt.data(23 downto 16) <= ram_data(7 downto 0);
200 wb_reg_nxt.data(31 downto 24) <= ram_data(7 downto 0);
204 byte_en := (others => '1');
207 wb_reg_nxt.byte_en <= byte_en;
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);
216 -- calc_mem_res(15 downto 0) <= data_ram_read(15 downto 0);
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;
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);
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;
240 -- if alu_jmp = '0' and br_pred = '1' and write_en = '0' then
244 -- if ((alu_jmp and wb_reg.dmem_en) = '1') then
245 -- jump_addr <= data_ram_read;
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
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;
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;
269 data_addr <= (others => '0');
272 if (wb_reg.address(DATA_ADDR_WIDTH+2) /= '1') then
273 data_out := data_ram_read;
275 reg_we_v := reg_we_v and ext_anysel;
276 data_out := data_ram_read_ext;
279 if wb_reg.byte_en(0) = '0' then
280 data_out(byte_t'range) := (others => '0');
282 if wb_reg.byte_en(1) = '0' then
283 data_out(2*byte_t'length-1 downto byte_t'length) := (others => '0');
285 if wb_reg.byte_en(2) = '0' then
286 data_out(3*byte_t'length-1 downto 2*byte_t'length) := (others => '0');
288 if wb_reg.byte_en(3) = '0' then
289 data_out(4*byte_t'length-1 downto 3*byte_t'length) := (others => '0');
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));
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));
302 -- data_out(hword_t'high downto (hword_t'length/2)) := (others => '0');
307 data_out := to_stdlogicvector(to_bitvector(data_out) srl to_integer(unsigned(wb_reg.address(BYTEADDR-1 downto 0)))*byte_t'length);
309 if (wb_reg_nxt.address(DATA_ADDR_WIDTH+2) /= '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;
314 regfile_val <= data_out;
316 if wb_reg.dmem_en = '0' then
317 regfile_val <= result;
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;
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);
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;
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;
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;
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;
376 -- wenn ich hier statt dem 4rer die konstante nehme dann gibts an fehler wegen nicht lokaler variable -.-
378 when EXT_UART_ADDR =>
379 ext_uart.sel <= enable;
380 ext_anysel <= enable;
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;
394 ext_imp.sel <= enable;
395 ext_anysel <= enable;
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;
410 ext_int.sel <= enable;
411 ext_anysel <= enable;
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;
425 when EXT_7SEG_ADDR =>
426 ext_7seg.sel <= enable;
427 ext_anysel <= enable;
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);
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;
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;
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;
469 -- hier kann man weiter extensions adden :) Konstanten sind im extension pkg definiert
470 when others => ext_anysel <= '0';
473 data_ram_read_ext <= ext_uart_out or ext_gpmp_out or ext_timer_out;