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