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