writeback_stage: differenzieren zwischen memory und extension geht ( btw wer sich...
[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
12 architecture behav of writeback_stage is
13
14 signal data_ram_read, data_ram_read_ext : word_t;
15 signal data_addr : word_t;
16
17 signal wb_reg, wb_reg_nxt : writeback_rec;
18
19 signal ext_uart,ext_timer,ext_gpmp :  extmod_rec;
20
21 signal sel_nxt, dmem_we, bus_rx :std_logic;
22
23
24
25 begin
26
27
28         data_ram : r_w_ram
29                 generic map (
30                         DATA_ADDR_WIDTH,
31                         WORD_WIDTH
32                 )
33                 
34                 port map (
35                         clk,
36                         data_addr(DATA_ADDR_WIDTH+1 downto 2),
37                         data_addr(DATA_ADDR_WIDTH+1 downto 2),
38                         dmem_we,
39                         ram_data,
40                         data_ram_read
41                 );
42
43 uart : extension_uart 
44         generic map(
45                 RESET_VALUE
46                 )
47         port map(
48                         clk ,
49                         reset,
50                         ext_uart,
51                         data_ram_read_ext,
52                         bus_rx,
53                         bus_tx
54                 );
55
56         
57 syn: process(clk, reset)
58
59 begin
60
61         if (reset = RESET_VALUE) then
62                 wb_reg.address <= (others => '0');
63                 wb_reg.dmem_en <= '0';
64                 wb_reg.dmem_write_en <= '0';
65                 wb_reg.hword <= '0';
66                 wb_reg.byte_s <= '0';
67                 bus_rx <= '1';
68         elsif rising_edge(clk) then
69                 wb_reg <= wb_reg_nxt;
70                 bus_rx <= '1';
71         end if;
72         
73 end process; 
74
75 --      type writeback_rec is record
76 --              address : in word_t;            --ureg 
77 --              dmem_en : in std_logic;         --ureg (jump addr in mem or in address)
78 --              dmem_write_en : in std_logic;   --ureg
79 --              hword_hl : in std_logic         --ureg
80 --      end record;
81
82
83
84 shift_input: process(data_ram_read, address, dmem_en, dmem_write_en, hword, wb_reg, result, byte_s, alu_jmp, br_pred, write_en)
85
86 begin
87         wb_reg_nxt.address <= address;
88         wb_reg_nxt.dmem_en <= dmem_en;
89         wb_reg_nxt.dmem_write_en <= dmem_write_en;
90         wb_reg_nxt.hword <= hword;
91         wb_reg_nxt.byte_s <= byte_s;
92
93         regfile_val <= result; --(others => '0');
94
95         if (wb_reg.dmem_en = '1' and wb_reg.dmem_write_en = '0') then   -- ram read operation --alu_jmp = '0' and 
96                 regfile_val <= data_ram_read;
97                 if (wb_reg.hword = '1') then
98                         regfile_val <= (others => '0');
99                         if (wb_reg.address(1) = '1') then
100                                 regfile_val(15 downto 0) <= data_ram_read(31 downto 16);
101                         else
102                                 regfile_val(15 downto 0) <= data_ram_read(15 downto 0);
103                         end if;
104                 end if;
105                 if (wb_reg.byte_s = '1') then
106                         regfile_val <= (others => '0');
107                         case wb_reg.address(1 downto 0) is
108                                 when "00" => regfile_val(7 downto 0) <= data_ram_read(7 downto 0);
109                                 when "01" => regfile_val(7 downto 0) <= data_ram_read(15 downto 8);
110                                 when "10" => regfile_val(7 downto 0) <= data_ram_read(23 downto 16);
111                                 when "11" => regfile_val(7 downto 0) <= data_ram_read(31 downto 24);
112                                 when others => null;
113                         end case;
114                 end if; 
115         end if;
116
117         --jump <= (alu_jmp xor br_pred) and (write_en or wb_reg.dmem_en);
118         jump <= (alu_jmp xor br_pred);-- and (write_en or wb_reg.dmem_en);
119
120         if (alu_jmp = '1' and wb_reg.dmem_en = '1' and wb_reg.dmem_write_en = '0' and write_en = '0') then
121                 jump_addr <= data_ram_read;
122         else
123                 jump_addr <= result;    
124         end if;
125
126 --      if alu_jmp = '0' and br_pred = '1' and write_en = '0' then
127 --              jump <= '1';
128 --      end if;
129
130 --      if ((alu_jmp and wb_reg.dmem_en) = '1') then
131 --              jump_addr <= data_ram_read;
132 --      end if;
133
134 end process;
135
136 --                      result : in gp_register_t;      --reg  (alu result or jumpaddr)
137 --                      result_addr : in gp_addr_t;     --reg
138 --                      address : in word_t;            --ureg 
139 --                      alu_jmp : in std_logic;         --reg
140 --                      br_pred : in std_logic;         --reg
141 --                      write_en : in std_logic;        --reg  (register file)
142 --                      dmem_en : in std_logic;         --ureg (jump addr in mem or in result)
143 --                      dmem_write_en : in std_logic;   --ureg
144 --                      hword : in std_logic            --ureg
145
146
147
148 out_logic: process(write_en, result_addr, wb_reg, alu_jmp, wb_reg_nxt)
149
150 begin   
151         reg_we <= (write_en or (wb_reg.dmem_en and not(wb_reg.dmem_write_en))) and not(alu_jmp);
152         reg_addr <= result_addr;
153
154         data_addr <= (others => '0');
155         dmem_we <= '0';
156         
157         if (wb_reg_nxt.address(DATA_ADDR_WIDTH+2) /= '1') then
158                 data_addr(DATA_ADDR_WIDTH+1 downto 0) <= wb_reg_nxt.address(DATA_ADDR_WIDTH+1 downto 0);
159                 dmem_we <= wb_reg_nxt.dmem_write_en;
160         end if;
161 end process;
162
163
164 addr_de_mult: process(wb_reg_nxt.address, ram_data, wb_reg,sel_nxt,wb_reg_nxt.dmem_write_en)
165
166 begin
167   ext_uart.sel <='0';
168   ext_uart.wr_en <= wb_reg_nxt.dmem_write_en;
169   ext_uart.byte_en <= (others => '0');
170   ext_uart.data <= (others => '0');
171   ext_uart.addr <= (others => '0');
172
173   ext_timer.sel <='0';
174   ext_timer.wr_en <= wb_reg_nxt.dmem_write_en;
175   ext_timer.byte_en <= (others => '0');
176   ext_timer.data <= (others => '0');
177   ext_timer.addr <= (others => '0');
178
179   ext_gpmp.sel <='0';
180   ext_gpmp.wr_en <= wb_reg_nxt.dmem_write_en;
181   ext_gpmp.byte_en <= (others => '0');
182   ext_gpmp.data <= (others => '0');
183   ext_gpmp.addr <= (others => '0');
184    -- wenn ich hier statt dem 4rer die konstante nehme dann gibts an fehler wegen nicht lokaler variable -.-
185  case wb_reg_nxt.address(31 downto 4) is
186         when EXT_UART_ADDR => 
187                 ext_uart.sel <='1';
188                 ext_timer.wr_en <= wb_reg_nxt.dmem_write_en;
189                 ext_uart.data <= ram_data;
190                 ext_uart.addr <= wb_reg_nxt.address(31 downto 2);
191                 case wb_reg.address(1 downto 0) is
192                                 when "00" => ext_uart.byte_en <= "0001";
193                                 when "01" => ext_uart.byte_en <= "0010";
194                                 when "10" => ext_uart.byte_en <= "0100";
195                                 --when "11" => ext_uart.byte_en <= "1000";
196                                 when "11" => ext_uart.byte_en <= "1111";
197                                 when others => null;
198                         end case;
199                         
200                         
201         when EXT_TIMER_ADDR => 
202                 ext_timer.sel <='1';
203                 ext_timer.wr_en <= wb_reg_nxt.dmem_write_en;
204                 ext_timer.data <= ram_data;
205                 ext_timer.addr <= wb_reg_nxt.address(wb_reg_nxt.address'high downto BYTEADDR);
206                 case wb_reg.address(1 downto 0) is
207                                 when "00" => ext_timer.byte_en <= "0001";
208                                 when "01" => ext_timer.byte_en <= "0010";
209                                 when "10" => ext_timer.byte_en <= "0100";
210                                 when "11" => ext_timer.byte_en <= "1000";
211                                 when others => null;
212                         end case;
213         when EXT_GPMP_ADDR => 
214                 ext_gpmp.sel <='1';
215                 ext_gpmp.wr_en <= wb_reg_nxt.dmem_write_en;
216                 ext_gpmp.data <= ram_data;
217                 ext_gpmp.addr <= wb_reg_nxt.address(wb_reg_nxt.address'high downto BYTEADDR);
218                 case wb_reg.address(1 downto 0) is
219                                 when "00" => ext_gpmp.byte_en <= "0001";
220                                 when "01" => ext_gpmp.byte_en <= "0010";
221                                 when "10" => ext_gpmp.byte_en <= "0100";
222                                 when "11" => ext_gpmp.byte_en <= "1000";
223                                 when others => null;
224                         end case;
225         -- hier kann man weiter extensions adden :) Konstanten sind im extension pkg definiert 
226         when others => null;
227  end case;
228
229 end process;
230
231 end behav;
232