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