1--test bench written by Alban Bourge @ TIMA 2library ieee; 3use ieee.std_logic_1164.all; 4use ieee.numeric_std.all; 5use std.textio.all; 6library work; 7use work.pkg_tb.all; 8 9entity fsm is 10 port( 11 clock : in std_logic; 12 reset : in std_logic; 13 --prog interface 14 instr_next : in instruction; 15 step : out std_logic; 16 --uut interface 17 cp_ok : in std_logic; 18 stdin_rdy : in std_logic; 19 stdin_ack : in std_logic; 20 reset_fsm : out std_logic; 21 start : out std_logic; 22 cp_en : out std_logic; 23 cp_rest : out std_logic; 24 --ram interface 25 ram_1 : out ram_instruction; 26 ram_2 : out ram_instruction; 27 --assert_uut interface 28 context_uut : out context_t; 29 en_feed : out std_logic; 30 en_check : out std_logic; 31 vecs_found : in std_logic; 32 vec_read : in std_logic; 33 --tb interface 34 stopped : out std_logic 35 ); 36end fsm; 37 38architecture rtl of fsm is 39 40 -- read output 41 signal step_sig : std_logic; 42 -- FSM signals 43 signal instr_c : instruction := instr_rst; 44 signal instr_n : instruction := instr_rst; 45 -- TIMER signal 46 signal times_en : std_logic := '0'; 47 signal times_z : std_logic := '0'; 48 signal times : unsigned(ARG_WIDTH - 1 downto 0); 49 signal times_max : unsigned(ARG_WIDTH - 1 downto 0); 50 signal times_ok : std_logic := '0'; 51 -- COUNTER signal 52 signal count_en : std_logic := '0'; 53 signal count_z : std_logic := '0'; 54 signal count : unsigned(ARG_WIDTH - 1 downto 0); 55 signal count_max : unsigned(ARG_WIDTH - 1 downto 0); 56 signal count_ok : std_logic := '0'; 57 -- runtime counter 58 signal runtime_en : std_logic := '0'; 59 signal runtime : integer range 0 to 99999999; --100 million cycles 60 61begin 62 63 -- FSM 64 state_reg : process (clock, reset) is 65 begin 66 if (reset = '1') then 67 instr_c <= instr_rst; 68 elsif rising_edge(clock) then 69 instr_c <= instr_n; 70 end if; 71 end process state_reg; 72 73 comb_logic: process(instr_next, instr_c, stdin_rdy, count_ok, times_ok, cp_ok, stdin_ack, vecs_found, vec_read) 74 begin 75 --default definition for fsm control signals 76 instr_n <= instr_rst; 77 step_sig <= '0'; 78 --top 79 reset_fsm <= '0'; 80 start <= '0'; 81 cp_en <= '0'; 82 cp_rest <= '0'; 83 --counter & timer 84 times_en <= '0'; 85 times_max <= (others => '0'); 86 count_en <= '0'; 87 count_max <= (others => '0'); 88 --runtime counter 89 runtime_en <= '0'; 90 --ram 91 ram_1 <= ram_instr_z; 92 ram_2 <= ram_instr_z; 93 --assert_uut 94 en_feed <= '0'; 95 en_check <= '0'; 96 --tb interface 97 stopped <= '0'; 98 99 case instr_c.state is 100 when Rst => 101 --signals 102 reset_fsm <= '1'; 103 ram_1.addr_z <= '1'; 104 ram_2.addr_z <= '1'; 105 step_sig <= '1'; --demand for next instruction 106 --transition 107 instr_n <= instr_next; 108 109 when Sig_start => 110 --signals 111 start <= '1'; 112 step_sig <= '1'; --demand for next instruction 113 --transition 114 instr_n <= instr_next; 115 --if (instr_next.state = Ack_data) then 116 --en_feed <= '1'; 117 --end if; 118 119 when Ack_data => 120 times_max <= instr_c.arg - 1; 121 --signals 122 en_feed <= '1'; 123 --transition 124 if (stdin_rdy = '1' and stdin_ack = '1') then 125 times_en <= '1'; 126 end if; 127 if (times_ok = '1') then 128 en_feed <= '0'; 129 step_sig <= '1'; 130 instr_n <= instr_next; 131 else 132 instr_n <= instr_c; 133 end if; 134 135 when Running => 136 --signals 137 count_max <= instr_c.arg; 138 count_en <= '1'; 139 --en_check <= '1'; 140 --runtime counter 141 if(vecs_found = '0') then 142 runtime_en <= '1'; 143 end if; 144 --transition 145 if (count_ok = '1') then 146 step_sig <= '1'; 147 instr_n <= instr_next; 148 else 149 instr_n <= instr_c; 150 end if; 151 152 when Waitfor => 153 --signals 154 count_max <= instr_c.arg; 155 en_check <= '1'; 156 if(vec_read = '1') then 157 count_en <= '1'; 158 end if; 159 --runtime counter 160 if(vecs_found = '0') then 161 runtime_en <= '1'; 162 end if; 163 --transition 164 if (count_ok = '1') then 165 step_sig <= '1'; 166 instr_n <= instr_next; 167 else 168 instr_n <= instr_c; 169 end if; 170 171 when Cp_search => 172 --signals 173 cp_en <= '1'; 174 --transition 175 if (cp_ok = '1') then 176 case instr_c.context_uut is 177 when "01" => 178 ram_1.we <= '1'; 179 ram_1.addr_up <= '1'; 180 ram_1.sel <= '1'; 181 when "10" => 182 ram_2.we <= '1'; 183 ram_2.addr_up <= '1'; 184 ram_2.sel <= '1'; 185 when others => 186 end case; 187 instr_n <= (state => Cp_save, context_uut => instr_c.context_uut, arg => (others => '0')); --hard coded 188 else 189 instr_n <= instr_c; 190 end if; 191 192 when Cp_save => 193 --signals 194 cp_en <= '1'; 195 case instr_c.context_uut is 196 when "01" => 197 ram_1.we <= '1'; 198 ram_1.addr_up <= '1'; 199 ram_1.sel <= '1'; 200 when "10" => 201 ram_2.we <= '1'; 202 ram_2.addr_up <= '1'; 203 ram_2.sel <= '1'; 204 when others => 205 end case; 206 --transition 207 if (cp_ok = '0') then 208 case instr_c.context_uut is 209 when "01" => 210 ram_1.we <= '0'; 211 ram_1.addr_up <= '0'; 212 when "10" => 213 ram_2.we <= '0'; 214 ram_2.addr_up <= '0'; 215 when others => 216 end case; 217 step_sig <= '1'; 218 instr_n <= instr_next; 219 else 220 instr_n <= instr_c; 221 end if; 222 223 when Idle => 224 --signals 225 count_max <= instr_c.arg; 226 count_en <= '1'; 227 --transition 228 if (count_ok = '1') then 229 step_sig <= '1'; 230 instr_n <= instr_next; 231 else 232 instr_n <= instr_c; 233 end if; 234 235 when Rst_uut => 236 --signals 237 reset_fsm <= '1'; 238 ram_1.addr_z <= '1'; 239 ram_2.addr_z <= '1'; 240 --transition 241 step_sig <= '1'; 242 instr_n <= instr_next; 243 244 when Rest_ini0 => 245 --signals 246 start <= '1'; 247 cp_en <= '1'; 248 cp_rest <= '1'; 249 --this is for restoration : reading the first word of the right memory 250 case instr_c.context_uut is 251 when "01" => 252 ram_1.sel <= '1'; 253 when "10" => 254 ram_2.sel <= '1'; 255 when others => 256 end case; 257 --transition 258 instr_n <= (state => Rest_ini1, context_uut => instr_c.context_uut, arg => (others => '0')); --hard coded 259 260 when Rest_ini1 => 261 --signals 262 cp_en <= '1'; 263 cp_rest <= '1'; 264 case instr_c.context_uut is 265 when "01" => 266 ram_1.addr_up <= '1'; 267 ram_1.sel <= '1'; 268 when "10" => 269 ram_2.addr_up <= '1'; 270 ram_2.sel <= '1'; 271 when others => 272 end case; 273 --transition 274 instr_n <= (state => Rest, context_uut => instr_c.context_uut, arg => (others => '0')); --hard coded 275 276 when Rest => 277 --signals 278 cp_en <= '1'; 279 cp_rest <= '1'; 280 case instr_c.context_uut is 281 when "01" => 282 ram_1.addr_up <= '1'; 283 ram_1.sel <= '1'; 284 when "10" => 285 ram_2.addr_up <= '1'; 286 ram_2.sel <= '1'; 287 when others => 288 end case; 289 --transition 290 if (cp_ok = '0') then 291 step_sig <= '1'; 292 instr_n <= instr_next; 293 else 294 instr_n <= instr_c; 295 end if; 296 297 when Stop => 298 --signals 299 stopped <= '1'; 300 reset_fsm <= '1'; 301 report "RUNTIME:" & integer'image(runtime); 302 assert (vecs_found = '0') 303 report "END_OF_SIM ---> Stop state reached, some output vectors were read." severity note; 304 --transition 305 instr_n <= (state => Stop, context_uut => "00", arg => (others => '0')); --hard coded 306 307 when others => 308 end case; 309 end process comb_logic; 310 311 --*ER reset combo logic 312 --if a step_sig signal is sent, it means a instr_next will be consumed 313 reseter : process(step_sig) 314 begin 315 if (step_sig = '0') then 316 times_z <= '0'; 317 count_z <= '0'; 318 else 319 times_z <= '1'; 320 count_z <= '1'; 321 end if; 322 end process reseter; 323 324 --TIMER 325 timer : process(clock, reset) 326 begin 327 if (reset = '1') then 328 times <= (others => '0'); 329 times_ok <= '0'; 330 elsif rising_edge(clock) then 331 if (times_z = '1') then 332 times <= (others => '0'); 333 times_ok <= '0'; 334 else 335 if (times_en = '1') then 336 times <= times + 1; 337 if (times = times_max) then 338 times_ok <= '1'; 339 else 340 times_ok <= '0'; 341 end if; 342 end if; 343 end if; 344 end if; 345 end process timer; 346 347 --COUNTER 348 counter : process(clock, reset) 349 begin 350 if (reset = '1') then 351 count <= (others => '0'); 352 count_ok <= '0'; 353 elsif rising_edge(clock) then 354 --count_ok driving if 355 if (count_z = '1') then 356 count_ok <= '0'; 357 count <= (others => '0'); 358 else 359 if (count = count_max) then 360 count_ok <= '1'; 361 else 362 count_ok <= '0'; 363 if (count_en = '1') then 364 count <= count + 1; 365 end if; 366 end if; 367 end if; 368 end if; 369 end process counter; 370 371 --Runtime counter 372 runtime_counter : process(clock, reset) 373 begin 374 if (reset = '1') then 375 runtime <= 0; 376 elsif rising_edge(clock) then 377 if (runtime_en = '1') then 378 runtime <= runtime + 1; 379 if ((runtime mod 1000) = 0) then 380 report "Running since:" & integer'image(runtime) severity note; 381 end if; 382 end if; 383 end if; 384 end process runtime_counter; 385 386 -- process only used for reporting current instruction 387 reporter : process(instr_c) 388 begin 389 --report "Instruction: " & state_t'image(instr_c.state) severity note; 390 report "Instruction: " & state_t'image(instr_c.state) & " (context " & integer'image(to_integer(unsigned(instr_c.context_uut))) & ")" severity note; 391 end process reporter; 392 393 --Combinational 394 step <= step_sig; 395 context_uut <= instr_c.context_uut; 396end rtl; 397