1 -----------------------------------------------------------------------------
2 -- Title : Pipe-line architecture of RCU. Allows com with control GUI
3 -- Project : ALICE FMD Digitizer Board Controller
4 ------------------------------------------------------------------------------
5 -- File : rcu_pipe.vhd
6 -- Author : Christian Holm Christensen <cholm@nbi.dk>
7 -- Company : Niels Bohr Institute
8 -- Last update: 2006/10/18
9 -- Platform :
10 ------------------------------------------------------------------------------
11 -- ALICE FMD Digitiser Board Controller firmware.
12 --
13 -- This code takes care of
14 -- * monitoring voltages, currents, and temperatures.
15 -- * handle L0 triggers, and sends the appropriate control
16 -- signals to the VA1 pre-amplifier chips on the FMD hybrid
17 -- cards.
18 -- * controls the GTL bus transceivers for the ALTRO's on the
19 -- card, and of course for it self.
20 --
21 -- The code is based on the TPC FEC BC code. The original
22 -- authors were
23 -- * Carmen Gonzalez <Carmen.Gonzalez.Gutierrez@cern.ch>
24 -- * Roberto Campagnolo <Roberto.Campagnolo@cern.ch>.
25 --
26 -- Some initial development, and a lot of guidance was given by
27 -- * Daniel Kirschner <daniel.kirschner@nbi.dk>
28 -- * Tiago Perez <Tiago.Perez@exp2.physik.uni-giessen.de>
29 ------------------------------------------------------------------------------
30 -- Description:
31 ------------------------------------------------------------------------------
32 -- Revisions :
33 -- Date Version Author Description
34 -- 2006/10/02 1.0 cholm Created
35 ------------------------------------------------------------------------------
36 library rcu_model;
37 use rcu_model.rcu_pack.all;
38
39 ------------------------------------------------------------------------------
40 architecture pipe_stim of rcu is
41 constant PERIOD : time := 25 ns;
42 constant SIZE : integer := 8;
43 signal clk_i : std_logic := '1';
44 signal sclk_i : std_logic := '1';
45 signal scl_i : std_logic := '1';
46 signal grst_i : std_logic := '0';
47 signal l0_i : std_logic;
48 signal l1_i : std_logic;
49 signal l2_i : std_logic;
50 signal l1_ii : std_logic;
51 signal l2_ii : std_logic;
52 signal done_i : boolean := false;
53
54 ----------------------------------------------------------------------------
55 type wr_state_t is (idle, got_address, got_data);
56 type rd_state_t is (idle, got_address, start, output, endit);
57 type ctrl_t is (idle, start, wait_for_write, wait_for_read);
58 type exec_st_t is (idle, start, next_instr, rcu_instr, wait_clk,
59 altro_instr, altro_instr2, set_bus, strobe,
60 wait_strobe, wait_ack, take_data);
61 type tr_st_t is (idle, gen_l0, wait_to_l1, gen_l1, wait_to_l2, gen_l2);
62 signal trg_st_i : tr_st_t;
63 signal exec_st_i : exec_st_t;
64 signal wr_st_i : wr_state_t;
65 signal rd_st_i : rd_state_t;
66 signal ctrl_st_i : ctrl_t;
67 signal enable_rd_i : std_logic := '0';
68 signal enable_wr_i : std_logic := '0';
69 signal finish_rd_i : std_logic := '0';
70 signal finish_wr_i : std_logic := '0';
71 signal enable_out_i : std_logic := '0';
72 signal timeout_i : std_logic := '0';
73
74 ----------------------------------------------------------------------------
75 signal ioaddr_i : std_logic_vector(19 downto 0) := (others => '-');
76 signal idata_i : std_logic_vector(31 downto 0) := (others => '-');
77
78 ----------------------------------------------------------------------------
79 constant add_errst : integer := 16#7800#;
80 constant add_trcfg : integer := 16#7801#;
81 constant add_trcnt : integer := 16#7802#;
82 constant add_lwadd : integer := 16#7803#;
83 constant add_iradd : integer := 16#7804#;
84 constant add_irdat : integer := 16#7805#;
85 constant add_pmcfg : integer := 16#7806#;
86 constant add_chadd : integer := 16#7807#;
87 constant add_afl : integer := 16#8000#;
88 signal errst_i : std_logic_vector(31 downto 0) := (others => '0');
89 signal trcfg_i : std_logic_vector(31 downto 0) := (others => '0');
90 signal trcnt_i : std_logic_vector(31 downto 0) := (others => '0');
91 signal lwadd_i : std_logic_vector(17 downto 0) := (others => '0');
92 signal iradd_i : std_logic_vector(19 downto 0) := (others => '0');
93 signal irdat_i : std_logic_vector(19 downto 0) := (others => '0');
94 signal pmcfg_i : std_logic_vector(19 downto 0) := (others => '0');
95 signal chadd_i : std_logic_vector(23 downto 0) := (others => '0');
96 signal afl_i : std_logic_vector(31 downto 0) := (others => '0');
97 signal load_trcfg_i : std_logic := '0';
98 signal load_pmcfg_i : std_logic := '0';
99 signal load_afl_i : std_logic := '0';
100
101 ----------------------------------------------------------------------------
102 constant add_rs_status : integer := 16#6C01#;
103 constant add_rs_trcfg : integer := 16#6C02#;
104 constant add_rs_trcnt : integer := 16#6C03#;
105 constant add_rs_buf1 : integer := 16#6C04#;
106 constant add_rs_buf2 : integer := 16#6C05#;
107 constant add_exec : integer := 16#0000#;
108 constant add_abort : integer := 16#0800#;
109 constant add_dcs_on : integer := 16#E000#;
110 constant add_dll_on : integer := 16#F000#;
111 constant add_l1_ttc : integer := 16#E800#;
112 constant add_l1_i2c : integer := 16#F800#;
113 constant add_l1_cmd : integer := 16#D800#;
114 constant add_l1 : integer := 16#D000#;
115 constant add_glb_reset : integer := 16#2000#;
116 constant add_fec_reset : integer := 16#2001#;
117 constant add_rcu_reset : integer := 16#2002#;
118 signal exec_addr_i : integer := 0;
119 signal cmd_rs_status_i : std_logic := '0';
120 signal cmd_rs_trcfg_i : std_logic := '0';
121 signal cmd_rs_trcnt_i : std_logic := '0';
122 signal cmd_rs_buf1_i : std_logic := '0';
123 signal cmd_rs_buf2_i : std_logic := '0';
124 signal cmd_exec_i : std_logic := '0';
125 signal cmd_abort_i : std_logic := '0';
126 signal exec_busy_i : std_logic := '0';
127 signal cmd_dcs_on_i : std_logic := '0';
128 signal cmd_dll_on_i : std_logic := '0';
129 signal cmd_l1_ttc_i : std_logic := '0';
130 signal cmd_l1_i2c_i : std_logic := '0';
131 signal cmd_l1_cmd_i : std_logic := '0';
132 signal cmd_l1_i : std_logic := '0';
133 signal cmd_glb_reset_i : std_logic := '0';
134 signal cmd_fec_reset_i : std_logic := '0';
135 signal cmd_rcu_reset_i : std_logic := '0';
136
137 ----------------------------------------------------------------------------
138 signal icmd_rs_trcfg_i : std_logic := '0';
139 signal icmd_rs_status_i : std_logic := '0';
140 signal icmd_rs_trcnt_i : std_logic := '0';
141 signal icmd_trigger_i : std_logic := '0';
142
143 ----------------------------------------------------------------------------
144 constant add_imem : integer := 16#7000#;
145 constant add_pmem : integer := 16#6800#;
146 constant add_rmem : integer := 16#6000#;
147 constant add_acl : integer := 16#6400#;
148 constant add_dm1l : integer := 16#7400#;
149 constant add_dm1h : integer := 16#7500#;
150 constant add_dm2l : integer := 16#7C00#;
151 constant add_dm2h : integer := 16#7D00#;
152 constant add_head : integer := 16#4001#;
153 constant sz_imem : integer := 256;
154 constant sz_pmem : integer := 1024;
155 constant sz_rmem : integer := 128;
156 constant sz_acl : integer := 256;
157 constant sz_dmem : integer := 256;
158 constant sz_head : integer := 8;
159 type imem_t is array (0 to sz_imem-1) of std_logic_vector(23 downto 0);
160 type pmem_t is array (0 to sz_pmem-1) of std_logic_vector(9 downto 0);
161 type rmem_t is array (0 to sz_rmem-1) of std_logic_vector(19 downto 0);
162 type acl_t is array (0 to sz_acl-1) of std_logic_vector(15 downto 0);
163 type dmem_t is array (0 to sz_dmem-1) of std_logic_vector(19 downto 0);
164 type head_t is array (0 to sz_head-1) of std_logic_vector(31 downto 0);
165 signal imem_i : imem_t := (others => (others => '0'));
166 signal pmem_i : pmem_t := (others => (others => '0'));
167 signal rmem_i : rmem_t := (others => (others => '0'));
168 signal acl_i : acl_t := (others => (others => '0'));
169 signal dm1l_i : dmem_t := (others => (others => '0'));
170 signal dm1h_i : dmem_t := (others => (others => '0'));
171 signal dm2l_i : dmem_t := (others => (others => '0'));
172 signal dm2h_i : dmem_t := (others => (others => '0'));
173 signal head_i : head_t := (others => (others => '0'));
174
175 ----------------------------------------------------------------------------
176 -- purpose: Read leading character
177 procedure read_what (
178 file input : text;
179 variable what : out character)
180 is
181 variable line_i : line;
182 variable good_i : boolean;
183 begin -- function read_what
184 what := ' ';
185 readline(input, line_i);
186 if not endfile(input) then
187 read(line_i, what, good_i);
188 end if;
189 if not good_i then
190 what := ' ';
191 end if;
192 end procedure read_what;
193
194 ----------------------------------------------------------------------------
195 -- purpose: Read a real line
196 procedure read_addr_data (
197 file input : text; -- File
198 variable what : out character; -- What to do
199 variable addr : out string(1 to 7); -- Address
200 variable data : out string(1 to 10))
201 is
202 variable line_i : line;
203 variable good_i : boolean;
204 variable blnk_i : character := ' ';
205 variable what_i : character := ' ';
206 variable addr_i : string(1 to 7) := (others => ' ');
207 variable data_i : string(1 to 10) := (others => ' ');
208 begin -- procedure read_addr_data
209 what := ' ';
210 addr := (others => ' ');
211 data := (others => ' ');
212 readline(input, line_i);
213 if not endfile(input) then
214 read(line_i, what_i, good_i);
215 what := what_i;
216 if good_i and what_i /= 'e' then
217 read(line_i, blnk_i, good_i);
218 read(line_i, addr_i, good_i);
219 addr := addr_i;
220 if good_i then
221 read(line_i, blnk_i, good_i);
222 read(line_i, data_i, good_i);
223 data := data_i;
224 end if;
225 end if;
226 end if;
227 if not good_i then
228 what := ' ';
229 addr := (others => ' ');
230 data := (others => ' ');
231 end if;
232 end procedure read_addr_data;
233
234 ----------------------------------------------------------------------------
235 -- purpose: Convert std_logic_vector to a string
236 function slv2str (
237 constant v : std_logic_vector)
238 return string
239 is
240 variable ret : string(v'length downto 1);
241 variable i : integer;
242 begin -- function slv2str
243 ret := (others => 'X');
244
245 for i in v'range loop
246 case v(i) is
247 when 'U' => ret(i+1) := 'U';
248 when 'X' => ret(i+1) := 'X';
249 when '0' => ret(i+1) := '0';
250 when '1' => ret(i+1) := '1';
251 when 'Z' => ret(i+1) := 'Z';
252 when 'W' => ret(i+1) := 'W';
253 when 'L' => ret(i+1) := 'L';
254 when 'H' => ret(i+1) := 'H';
255 when '-' => ret(i+1) := '-';
256 when others => ret(i+1) := 'X';
257 end case;
258 end loop; -- i
259 return ret;
260 end function slv2str;
261
262 ----------------------------------------------------------------------------
263 -- purpose: Convert hex character to std_logic_vector (quad)
264 function hex2quad (
265 constant x : character)
266 return std_logic_vector
267 is
268 variable ret : std_logic_vector(0 to 3);
269 begin -- function hex2quad
270 ret := (others => '0');
271 case x is
272 when '0' => ret := X"0";
273 when '1' => ret := X"1";
274 when '2' => ret := X"2";
275 when '3' => ret := X"3";
276 when '4' => ret := X"4";
277 when '5' => ret := X"5";
278 when '6' => ret := X"6";
279 when '7' => ret := X"7";
280 when '8' => ret := X"8";
281 when '9' => ret := X"9";
282 when 'A'|'a' => ret := X"A";
283 when 'B'|'b' => ret := X"B";
284 when 'C'|'c' => ret := X"C";
285 when 'D'|'d' => ret := X"D";
286 when 'E'|'e' => ret := X"E";
287 when 'F'|'f' => ret := X"F";
288 when others =>
289 report "Bad hex character: '" & x & "'" severity warning;
290 end case;
291 return ret;
292 end function hex2quad;
293
294 -- purpose Convert a string (with hex numbers) to a std_logic_vector
295 function hstr2slv (
296 constant x : string)
297 return std_logic_vector
298 is
299 variable j : integer;
300 variable ns : integer := x'length - 3;
301 variable ret : std_logic_vector(0 to 4 * ns + 4 - 1);
302 begin
303 ret := (others => '0');
304 assert x(1) = '0' and (x(2) = 'x' or x(2) = 'X')
305 report "Bad hex prefix on: '" & x & "'" severity warning;
306 for i in 0 to ns loop
307 j := 4 * i;
308 ret(j to j + 3) := hex2quad(x(i+3));
309 end loop; -- i
310 return ret;
311 end function hstr2slv;
312
313 ----------------------------------------------------------------------------
314 -- purpose: Convert a quad of std_logic to a character
315 function quad2hex (
316 constant q : std_logic_vector(0 to 3))
317 return character
318 is
319 variable ret : character := '0';
320 variable x : integer := 0;
321 begin -- function quad2str
322 for i in q'range loop
323 case q(i) is
324 when 'H' | '1' => x := x + 2**(3-i);
325 when 'L' | '0' => null;
326 when others =>
327 report "Unrepresentable bit value " & std_logic'image(q(i)) &
328 " in " & slv2str(q) severity warning;
329 end case;
330 end loop; -- i
331 case x is
332 when 16#0# => ret := '0';
333 when 16#1# => ret := '1';
334 when 16#2# => ret := '2';
335 when 16#3# => ret := '3';
336 when 16#4# => ret := '4';
337 when 16#5# => ret := '5';
338 when 16#6# => ret := '6';
339 when 16#7# => ret := '7';
340 when 16#8# => ret := '8';
341 when 16#9# => ret := '9';
342 when 16#A# => ret := 'A';
343 when 16#B# => ret := 'B';
344 when 16#C# => ret := 'C';
345 when 16#D# => ret := 'D';
346 when 16#E# => ret := 'E';
347 when 16#F# => ret := 'F';
348 when others => null;
349 end case;
350 return ret;
351 end function quad2hex;
352
353 -- purpose: Turn a std_logic_vector into a string
354 function slv2hstr (
355 constant v : std_logic_vector)
356 return string
357 is
358 variable ns : natural := v'length / 4;
359 variable ret : string(1 to 2 + ns);
360 variable j : integer;
361 variable q : std_logic_vector(0 to 3);
362 begin -- function slv2hstr
363 assert v'length mod 4 = 0 report
364 "Vector length is not a multiplum of 4" severity warning;
365 ret := (others => '0');
366 ret(2) := 'x';
367 for i in 0 to ns - 1 loop
368 j := 4 * i;
369 q := v(j+3 downto j);
370 ret(ret'length - i) := quad2hex(q);
371 end loop; -- i
372 return ret;
373 end function slv2hstr;
374
375 ----------------------------------------------------------------------------
376 -- purpose: Turn a std_logic_vector into an integer
377 function slv2int (
378 constant x : std_logic_vector)
379 return integer is
380 begin -- function slv2int
381 return to_integer(unsigned(x));
382 end function slv2int;
383
384 -- purpose: Turn an integer into a std_logic_vector
385 function int2slv (
386 constant x : integer;
387 constant l : natural)
388 return std_logic_vector
389 is
390 variable ret : std_logic_vector(l - 1 downto 0) := (others => '0');
391 begin
392 ret := std_logic_vector(to_unsigned(x, l));
393 return ret;
394 end function int2slv;
395
396 ---------------------------------------------------------------------------
397 -- purpose: calculate parity
398 function parity (constant x : std_logic_vector) return std_logic is
399 variable tmp : std_logic := '0';
400 begin -- function parity
401 for j in x'range loop
402 tmp := tmp xor x(j);
403 end loop; -- j
404 return tmp;
405 end function parity;
406 begin -- architecture pipe_stim
407
408 -- purpose: Combinatorics
409 combi : block is
410 begin -- block combi
411 lvl0 <= l0_i;
412 lvl1 <= l1_i;
413 lvl2 <= l2_i;
414 rclk <= clk_i;
415 sclk <= sclk_i;
416 -- grst <= grst_i;
417 end block combi;
418
419 -- purpose: Provide stimuli
420 stimuli : process is
421 begin -- process stimuli
422 -- wait for 100 ns;
423 -- grst_i <= '1';
424 wait;
425 end process stimuli;
426
427 -- purpose: Read one line
428 -- type : combinational
429 -- inputs :
430 -- outputs:
431 control : process(clk_i, grst_i)
432 file input_i : text open read_mode is "/dev/stdin"; -- Input pipe
433 variable what_i : character;
434 variable addr_i : string(1 to 7);
435 variable data_i : string(1 to 10);
436 begin -- process read_in
437
438 if grst_i = '0' then
439 ctrl_st_i <= idle;
440 done_i <= false;
441
442 elsif clk_i'event and clk_i = '1' then
443 enable_wr_i <= '0';
444 enable_rd_i <= '0';
445 -- idata_i <= (others => '0');
446 -- ioaddr_i <= (others => '0');
447 ctrl_st_i <= ctrl_st_i;
448
449 case ctrl_st_i is
450 when idle =>
451 if not done_i then
452 read_what(input_i, what_i);
453 case what_i is
454 when ' ' =>
455 report "At end of file in state " &
456 ctrl_t'image(ctrl_st_i) severity error;
457 done_i <= true;
458 when 's' => -- Start condition
459 report "Got start" severity note;
460 ctrl_st_i <= start;
461 when others =>
462 report "Unexpected control character '" & what_i &
463 "' while in state " & ctrl_t'image(ctrl_st_i)
464 severity warning;
465 end case;
466 end if;
467
468 when start =>
469 read_addr_data(input_i, what_i, addr_i, data_i);
470 case what_i is
471 when 'w' =>
472 -- report "Writing" severity note;
473 ioaddr_i <= hstr2slv(addr_i);
474 idata_i <= hstr2slv(data_i);
475 enable_wr_i <= '1';
476 enable_rd_i <= '0';
477 ctrl_st_i <= wait_for_write;
478
479 when 'r' =>
480 -- report "Reading" severity note;
481 ioaddr_i <= hstr2slv(addr_i);
482 idata_i <= hstr2slv(data_i);
483 enable_wr_i <= '0';
484 enable_rd_i <= '1';
485 ctrl_st_i <= wait_for_read;
486
487 when 'e' =>
488 report "Got end" severity note;
489 enable_wr_i <= '0';
490 enable_rd_i <= '0';
491 ctrl_st_i <= idle;
492
493 when ' ' =>
494 report "at end of file in state " & ctrl_t'image(ctrl_st_i)
495 severity error;
496 done_i <= true;
497 ctrl_st_i <= idle;
498
499 when others =>
500 report "Unexpected control character '" & what_i &
501 "' while in state " & ctrl_t'image(ctrl_st_i)
502 severity warning;
503 ctrl_st_i <= idle;
504 end case;
505
506 when wait_for_write =>
507 if finish_wr_i = '1' then
508 ctrl_st_i <= start;
509 end if;
510
511 when wait_for_read =>
512 if finish_rd_i = '1' then
513 ctrl_st_i <= start;
514 end if;
515
516 when others =>
517 ctrl_st_i <= idle;
518
519 end case;
520 end if;
521 end process control;
522
523 -- purpose: Write to registers
524 -- type : sequential
525 -- inputs : clk_i, grst_i
526 -- outputs:
527 writer : process (clk_i, grst_i)
528 variable addr_i : integer := 0;
529 begin -- process writer
530 if grst_i = '0' then -- asynchronous reset (active low)
531 wr_st_i <= idle;
532 finish_wr_i <= '0';
533 cmd_l1_ttc_i <= '0';
534 cmd_l1_i2c_i <= '0';
535 cmd_l1_cmd_i <= '1';
536 cmd_rs_status_i <= '0';
537 cmd_rs_trcfg_i <= '0';
538 cmd_rs_trcnt_i <= '0';
539 cmd_rs_buf1_i <= '0';
540 cmd_rs_buf2_i <= '0';
541 cmd_exec_i <= '0';
542 cmd_abort_i <= '0';
543 cmd_dcs_on_i <= '0';
544 cmd_dll_on_i <= '0';
545 cmd_l1_i <= '0';
546 cmd_glb_reset_i <= '0';
547 cmd_fec_reset_i <= '0';
548 cmd_rcu_reset_i <= '0';
549 load_trcfg_i <= '0';
550 load_pmcfg_i <= '0';
551 load_afl_i <= '0';
552 elsif clk_i'event and clk_i = '1' then -- rising clock edge
553 wr_st_i <= wr_st_i;
554 finish_wr_i <= '0';
555
556 case wr_st_i is
557 when idle =>
558 if enable_wr_i = '1' then
559 wr_st_i <= got_address;
560 end if;
561
562 when got_address =>
563 addr_i := slv2int(ioaddr_i);
564 wr_st_i <= got_data;
565
566 -- report "Writing to " & slv2hstr(ioaddr_i) &
567 -- ": " & slv2hstr(idata_i) severity note;
568 case addr_i is
569 when add_errst => -- errst
570 report "Register errst is read-only" severity warning;
571 when add_trcfg => -- trcfg
572 load_trcfg_i <= '1';
573 when add_trcnt => -- trcnt
574 report "Register trcnt is read-only" severity warning;
575 when add_lwadd => -- lwadd
576 report "Register lwadd is read-only" severity warning;
577 when add_iradd => -- iradd
578 report "Register iradd is read-only" severity warning;
579 when add_irdat => -- irdat
580 report "Register irdat is read-only" severity warning;
581 when add_pmcfg => -- pmcfg
582 load_pmcfg_i <= '1';
583 when add_chadd => -- chadd
584 report "Register chadd is read-only" severity warning;
585 when add_afl =>
586 load_afl_i <= '1';
587
588 when add_rs_status => -- rs_status
589 cmd_rs_status_i <= '1';
590 when add_rs_trcfg => -- rs_trcfg
591 cmd_rs_trcfg_i <= '1';
592 when add_rs_trcnt => -- rs_trcnt
593 cmd_rs_trcnt_i <= '1';
594 when add_rs_buf1 => -- rs_buf1
595 cmd_rs_buf1_i <= '1';
596 when add_rs_buf2 => -- rs_buf2
597 cmd_rs_buf2_i <= '1';
598 when add_exec to add_exec + 127 => -- exec
599 cmd_exec_i <= '1';
600 exec_addr_i <= slv2int(ioaddr_i(7 downto 0));
601 when add_abort => -- abort
602 cmd_abort_i <= '1';
603 when add_dcs_on => -- dcs_on
604 cmd_dcs_on_i <= '1';
605 when add_dll_on => -- dll_on
606 cmd_dll_on_i <= '1';
607 when add_l1_ttc => -- l1_ttc
608 cmd_l1_ttc_i <= '1';
609 cmd_l1_i2c_i <= '0';
610 cmd_l1_cmd_i <= '0';
611 when add_l1_i2c => -- l1_i2c
612 cmd_l1_ttc_i <= '0';
613 cmd_l1_i2c_i <= '1';
614 cmd_l1_cmd_i <= '0';
615 when add_l1_cmd => -- l1_cmd
616 cmd_l1_ttc_i <= '0';
617 cmd_l1_i2c_i <= '0';
618 cmd_l1_cmd_i <= '1';
619 when add_l1 => -- l1
620 cmd_l1_i <= '1';
621 when add_glb_reset => -- glb_reset
622 cmd_glb_reset_i <= '1';
623 when add_fec_reset => -- fec_reset
624 cmd_fec_reset_i <= '1';
625 when add_rcu_reset => -- rcu_reset
626 cmd_rcu_reset_i <= '1';
627
628 when add_imem to add_imem+sz_imem-1 => -- IMEM
629 imem_i(addr_i - add_imem) <= idata_i(23 downto 0);
630 when add_pmem to add_pmem+sz_pmem-1 => -- PMEM
631 pmem_i(addr_i - add_pmem) <= idata_i(9 downto 0);
632 when add_rmem to add_rmem+sz_rmem-1 => -- RMEM
633 null;
634 -- rmem_i(addr_i - add_rmem) <= idata_i(19 downto 0);
635 when add_acl to add_acl+sz_acl => -- ACL
636 acl_i(addr_i - add_acl) <= idata_i(15 downto 0);
637 when add_dm1l to add_dm1l+sz_dmem-1 => -- DM1L
638 dm1l_i(addr_i - add_dm1l) <= idata_i(19 downto 0);
639 when add_dm1h to add_dm1h+sz_dmem-1 => -- DM1H
640 dm1h_i(addr_i - add_dm1h) <= idata_i(19 downto 0);
641 when add_dm2l to add_dm2l+sz_dmem-1 => -- DM2L
642 dm2l_i(addr_i - add_dm2l) <= idata_i(19 downto 0);
643 when add_dm2h to add_dm2h+sz_dmem-1 => -- DM2H
644 dm2h_i(addr_i - add_dm2h) <= idata_i(19 downto 0);
645 when add_head to add_head+sz_head-1 => -- HEAD
646 head_i(addr_i - add_head) <= idata_i(31 downto 0);
647
648 when others =>
649 report "Invalid address " & integer'image(addr_i)
650 severity warning;
651 end case;
652
653 when got_data =>
654 cmd_rs_status_i <= '0';
655 cmd_rs_trcfg_i <= '0';
656 cmd_rs_trcnt_i <= '0';
657 cmd_rs_buf1_i <= '0';
658 cmd_rs_buf2_i <= '0';
659 cmd_exec_i <= '0';
660 cmd_abort_i <= '0';
661 cmd_dcs_on_i <= '0';
662 cmd_dll_on_i <= '0';
663 cmd_l1_i <= '0';
664 cmd_glb_reset_i <= '0';
665 cmd_fec_reset_i <= '0';
666 cmd_rcu_reset_i <= '0';
667 load_trcfg_i <= '0';
668 load_pmcfg_i <= '0';
669 load_afl_i <= '0';
670 if cmd_exec_i = '1' or exec_busy_i = '1' then
671 wr_st_i <= got_data;
672 else
673 finish_wr_i <= '1';
674 exec_addr_i <= 0;
675 wr_st_i <= idle;
676 end if;
677
678 when others =>
679 wr_st_i <= idle;
680
681 end case;
682 end if;
683 end process writer;
684
685 -- purpose: Read from registers
686 -- type : sequential
687 -- inputs : clk_i, grst_i
688 -- outputs:
689 reader : process (clk_i, grst_i)
690 file output_i : text open write_mode is "/dev/stdout"; -- Input pipe
691 variable str_i : string(1 to 10) := (others => ' ');
692 variable line_i : line;
693 variable data_i : std_logic_vector(31 downto 0);
694 variable addr_i : integer := 0;
695 variable cnt_i : integer := 0; -- Count
696 variable cur_i : integer := 0;
697 variable en_out_i : boolean := false;
698 begin -- process reader
699
700 if grst_i = '0' then -- asynchronous reset (active low)
701 rd_st_i <= idle;
702 finish_rd_i <= '0';
703 cnt_i := 0;
704 cur_i := 0;
705 data_i := (others => '0');
706 elsif clk_i'event and clk_i = '1' then -- rising clock edge
707 rd_st_i <= rd_st_i;
708 finish_rd_i <= '0';
709 enable_out_i <= '0';
710
711 case rd_st_i is
712 when idle =>
713 cnt_i := 0;
714 cur_i := 0;
715 data_i := (others => '0');
716 en_out_i := true;
717 if enable_rd_i = '1' then
718 rd_st_i <= got_address;
719 end if;
720
721 when got_address =>
722 addr_i := slv2int(ioaddr_i);
723 cur_i := addr_i;
724 cnt_i := slv2int(idata_i);
725
726 case addr_i is
727 when add_rs_status => -- rs_status
728 report "rs_status is a command" severity warning;
729 when add_rs_trcfg => -- rs_trcfg
730 report "rs_trcfg is a command" severity warning;
731 when add_rs_trcnt => -- rs_trcnt
732 report "rs_trcnt is a command" severity warning;
733 when add_rs_buf1 => -- rs_buf1
734 report "rs_buf1 is a command" severity warning;
735 when add_rs_buf2 => -- rs_buf2
736 report "rs_buf2 is a command" severity warning;
737 when add_exec to add_exec + 127 => -- exec
738 report "exec is a command" severity warning;
739 when add_abort => -- abort
740 report "abort is a command" severity warning;
741 when add_dcs_on => -- dcs_on
742 report "dcs_on is a command" severity warning;
743 when add_dll_on => -- dll_on
744 report "dll_on is a command" severity warning;
745 when add_l1_ttc => -- l1_ttc
746 report "l1_ttc is a command" severity warning;
747 when add_l1_i2c => -- l1_i2c
748 report "l1_i2c is a command" severity warning;
749 when add_l1_cmd => -- l1_cmd
750 report "l1_cmd is a command" severity warning;
751 when add_l1 => -- l1
752 report "l1 is a command" severity warning;
753 when add_glb_reset => -- glb_reset
754 report "glb_reset is a command" severity warning;
755 when add_fec_reset => -- fec_reset
756 report "fec_reset is a command" severity warning;
757 when add_rcu_reset => -- rcu_reset
758 report "rcu_reset is a command" severity warning;
759 when
760 add_errst | add_trcfg | add_trcnt | add_lwadd |
761 add_iradd | add_irdat | add_pmcfg | add_chadd | add_afl |
762 add_imem to add_imem+sz_imem-1 |
763 add_pmem to add_pmem+sz_pmem-1 |
764 add_rmem to add_rmem+sz_rmem-1 |
765 add_acl to add_acl+sz_acl |
766 add_dm1l to add_dm1l+sz_dmem-1 |
767 add_dm1h to add_dm1h+sz_dmem-1 |
768 add_dm2l to add_dm2l+sz_dmem-1 |
769 add_dm2h to add_dm2h+sz_dmem-1 |
770 add_head to add_head+sz_head-1 =>
771 en_out_i := true;
772 when others =>
773 report "Invalid address " & integer'image(addr_i)
774 severity warning;
775 end case;
776 if en_out_i then
777 rd_st_i <= start;
778 else
779 rd_st_i <= idle;
780 end if;
781
782 when start =>
783 -- report "Writing an s" severity note;
784 write(line_i, 's');
785 writeline(output_i, line_i);
786 rd_st_i <= output;
787
788 when output =>
789 if cur_i < addr_i or cur_i >= addr_i + cnt_i then
790 rd_st_i <= endit;
791 else
792 data_i := (others => '0');
793
794 case cur_i is
795 when add_errst => -- errst
796 data_i(31 downto 0) := errst_i;
797 when add_trcfg => -- trcfg
798 data_i(31 downto 0) := trcfg_i;
799 when add_trcnt => -- trcnt
800 data_i(31 downto 0) := trcnt_i;
801 when add_lwadd => -- lwadd
802 data_i(17 downto 0) := lwadd_i;
803 when add_iradd => -- iradd
804 data_i(19 downto 0) := iradd_i;
805 when add_irdat => -- irdat
806 data_i(19 downto 0) := irdat_i;
807 when add_pmcfg => -- pmcfg
808 data_i(19 downto 0) := pmcfg_i;
809 when add_chadd => -- chadd
810 data_i(23 downto 0) := chadd_i;
811 when add_afl => -- afl
812 data_i(31 downto 0) := afl_i;
813
814 when add_imem to add_imem+sz_imem-1 => -- IMEM
815 data_i(23 downto 0) := imem_i(cur_i - add_imem);
816 when add_pmem to add_pmem+sz_pmem-1 => -- PMEM
817 data_i(9 downto 0) := pmem_i(cur_i - add_pmem);
818 when add_rmem to add_rmem+sz_rmem-1 => -- RMEM
819 data_i(19 downto 0) := rmem_i(cur_i - add_rmem);
820 when add_acl to add_acl+sz_acl => -- ACL
821 data_i(15 downto 0) := acl_i(cur_i - add_acl);
822 when add_dm1l to add_dm1l+sz_dmem-1 => -- DM1L
823 data_i(19 downto 0) := dm1l_i(cur_i - add_dm1l);
824 when add_dm1h to add_dm1h+sz_dmem-1 => -- DM1H
825 data_i(19 downto 0) := dm1h_i(cur_i - add_dm1h);
826 when add_dm2l to add_dm2l+sz_dmem-1 => -- DM2L
827 data_i(19 downto 0) := dm2l_i(cur_i - add_dm2l);
828 when add_dm2h to add_dm2h+sz_dmem-1 => -- DM2H
829 data_i(19 downto 0) := dm2h_i(cur_i - add_dm2h);
830 when add_head to add_head+sz_head-1 => -- HEAD
831 data_i(31 downto 0) := head_i(cur_i - add_head);
832 when others => null;
833 end case;
834 str_i := slv2hstr(data_i);
835 -- report "Reading from " & slv2hstr(int2slv(cur_i, 20)) &
836 -- ": " & str_i severity note;
837 write(line_i, str_i);
838 writeline(output_i, line_i);
839 cur_i := cur_i + 1;
840 end if;
841
842 when endit =>
843 -- report "Writing an e" severity note;
844 write(line_i, 'e');
845 writeline(output_i, line_i);
846 data_i := (others => '0');
847 cur_i := 0;
848 addr_i := 0;
849 cnt_i := 0;
850 finish_rd_i <= '1';
851 rd_st_i <= idle;
852
853 when others =>
854 rd_st_i <= idle;
855 end case;
856 end if;
857 end process reader;
858
859 -- purpose: Execute instruction memory
860 -- type : sequential
861 -- inputs : clk_i, grst_i, exec_cmd_i, cmd_abort_i, exec_addr_i
862 -- outputs: bd, cstb, write
863 imem_exec : process (clk_i, grst_i)
864 variable cur_i : integer := 0; -- Current instruction offset
865 variable jump_i : integer := 0; -- Current instruction offset
866 variable loop_i : integer := 0; -- Number of loops
867 variable iter_i : integer := 0; -- Current iteration
868 variable nwait_i : integer := 0; -- Clock cycles to wait
869 variable bcast_i : std_logic;
870 variable ack_cnt_i : integer;
871 variable cstb_cnt_i : integer;
872 variable writ_i : boolean := false;
873 constant dont_care_i : std_logic_vector(19 downto 0) := (others => 'Z');
874 begin -- process imem_exec
875
876 if grst_i = '0' then -- asynchronous reset (active low)
877 cstb <= 'H';
878 writ <= 'H';
879 bd <= (others => 'L');
880 exec_st_i <= idle;
881 iradd_i <= (others => '0');
882 irdat_i <= (others => '0');
883 cur_i := 0;
884 elsif clk_i'event and clk_i = '1' then -- rising clock edge
885 if cmd_glb_reset_i = '1' or cmd_rcu_reset_i = '1' then
886 exec_st_i <= idle;
887 else
888
889 case exec_st_i is
890 when idle =>
891 loop_i := 0;
892 jump_i := 0;
893 iter_i := 0;
894 bd <= (others => 'L');
895 cstb <= 'H';
896 writ <= 'H';
897
898 exec_busy_i <= '0';
899 if cmd_exec_i = '1' then
900 exec_st_i <= start;
901 exec_busy_i <= '1';
902 end if;
903
904 when start =>
905 if exec_addr_i < 0 or exec_addr_i >= sz_imem then
906 report "Address point out of scope" severity warning;
907 exec_st_i <= idle;
908 else
909 cur_i := exec_addr_i;
910 exec_st_i <= next_instr;
911 end if;
912
913 when next_instr =>
914 -- report "Looking at instruction @ " & integer'image(cur_i) &
915 -- ": " & slv2hstr(imem_i(cur_i)) severity note;
916 if cmd_abort_i = '1' then
917 exec_st_i <= idle;
918 elsif imem_i(cur_i)(22) = '0' then
919 exec_st_i <= rcu_instr;
920 else
921 exec_st_i <= altro_instr;
922 end if;
923
924 when rcu_instr =>
925 exec_st_i <= next_instr;
926 if cmd_abort_i = '1' then
927 exec_st_i <= idle;
928 else
929 case slv2int(imem_i(cur_i)(19 downto 16)) is
930 when 0 => -- Loop or jump
931 jump_i := slv2int(imem_i(cur_i)(7 downto 0)) - 1;
932 if imem_i(cur_i)(15) = '0' then -- Jump
933 cur_i := jump_i; -- Jump to address
934 elsif loop_i = 0 then
935 loop_i := slv2int(imem_i(cur_i)(14 downto 8));
936 iter_i := 1;
937 cur_i := jump_i;
938 elsif iter_i < loop_i then
939 iter_i := iter_i + 1;
940 cur_i := jump_i;
941 else
942 loop_i := 0;
943 iter_i := 0;
944 end if;
945 when 1 => -- Reset errst
946 icmd_rs_status_i <= '1';
947 when 2 => -- Reset trcfg
948 icmd_rs_trcfg_i <= '1';
949 when 3 => -- Reset trcnt
950 icmd_rs_trcnt_i <= '1';
951 when 6 => -- ChRdo (not handled)
952 null;
953 when 7 => -- PMREAD (not handled)
954 null;
955 when 8 => -- PMWRITE (not handled)
956 null;
957 when 9 => -- End of block;
958 exec_st_i <= idle;
959 when 10 => -- Wait for X clock cycles
960 nwait_i := slv2int(imem_i(cur_i)(15 downto 0));
961 exec_st_i <= wait_clk;
962 when 11 =>
963 icmd_trigger_i <= '1';
964 when others => null;
965 end case;
966 cur_i := cur_i + 1;
967 end if;
968
969 when wait_clk =>
970 if cmd_abort_i = '1' then
971 exec_st_i <= idle;
972 elsif nwait_i = 0 then
973 exec_st_i <= next_instr;
974 else
975 nwait_i := nwait_i - 1;
976 end if;
977
978
979 when altro_instr =>
980 if cmd_abort_i = '1' then
981 exec_st_i <= idle;
982 else
983 -- Set address on bus
984 iradd_i <= (parity(imem_i(cur_i)(18 downto 0)) &
985 imem_i(cur_i)(18 downto 0));
986 bcast_i := imem_i(cur_i)(18);
987 writ_i := imem_i(cur_i)(21) = '1';
988 if writ_i then
989 writ <= '0';
990 else
991 writ <= 'H';
992 end if;
993 cur_i := cur_i + 1;
994 exec_st_i <= altro_instr2;
995 end if;
996
997 when altro_instr2 =>
998 if cmd_abort_i = '1' then
999 exec_st_i <= idle;
1000 else
1001 -- Set data on bus
1002 irdat_i <= imem_i(cur_i)(19 downto 0);
1003 cur_i := cur_i + 1;
1004 exec_st_i <= set_bus;
1005 end if;
1006
1007 when set_bus =>
1008 if cmd_abort_i = '1' then
1009 exec_st_i <= idle;
1010 else
1011 if writ_i then
1012 bd <= iradd_i & irdat_i;
1013 else
1014 bd <= iradd_i & dont_care_i;
1015 end if;
1016 exec_st_i <= strobe;
1017 end if;
1018
1019 when strobe =>
1020 if cmd_abort_i = '1' then
1021 exec_st_i <= idle;
1022 else
1023 -- Assert the control strobe
1024 cstb <= '0';
1025 timeout_i <= '0';
1026 if bcast_i = '1' then
1027 cstb_cnt_i := 4;
1028 exec_st_i <= wait_strobe;
1029 else
1030 ack_cnt_i := 32;
1031 exec_st_i <= wait_ack;
1032 end if;
1033 end if;
1034
1035 when wait_strobe =>
1036 if cmd_abort_i = '1' then
1037 exec_st_i <= idle;
1038 elsif cstb_cnt_i = 0 then
1039 cstb <= 'H';
1040 writ <= 'H';
1041 exec_st_i <= next_instr;
1042 else
1043 cstb_cnt_i := cstb_cnt_i - 1;
1044 end if;
1045
1046 when wait_ack =>
1047 if cmd_abort_i = '1' then
1048 exec_st_i <= idle;
1049 elsif eror = '0' then
1050 exec_st_i <= idle;
1051 elsif ackn = '0' then
1052 cstb <= 'H';
1053 writ <= 'H';
1054 bd(39 downto 20) <= (others => 'L');
1055 exec_st_i <= take_data;
1056 -- elsif ack_cnt_i = 16 then -- Temporary
1057 -- cstb <= 'H';
1058 -- writ <= 'H';
1059 -- bd <= (others => 'L');
1060 -- exec_st_i <= take_data;
1061 elsif ack_cnt_i = 0 then
1062 report "Acknowledge timeout " severity WARNING;
1063 cstb <= 'H';
1064 writ <= 'H';
1065 timeout_i <= '1';
1066 exec_st_i <= next_instr;
1067 else
1068 ack_cnt_i := ack_cnt_i - 1;
1069 end if;
1070
1071 when take_data =>
1072 -- report "data on bus: " & slv2hstr(bd(19 downto 0)) &
1073 -- " rmem_0=" & slv2hstr(rmem_i(0)) severity note;
1074 rmem_i(0) <= bd(19 downto 0);
1075 if ackn /= '0' then
1076 exec_st_i <= next_instr;
1077 end if;
1078
1079 when others => null;
1080 end case;
1081 end if;
1082 end if;
1083 end process imem_exec;
1084
1085
1086 -- purpose: Handle register trcfg_i
1087 -- type : sequential
1088 -- inputs : clk_i, grst_i
1089 -- outputs:
1090 registers : process (clk_i, grst_i)
1091 variable l1_cnt_i : integer range 0 to 2**16 - 1;
1092 variable l2_cnt_i : integer range 0 to 2**16 - 1;
1093 variable rst_cnt_i : integer := 0;
1094 begin -- process trcfg_proc
1095 if grst_i = '0' then -- asynchronous reset (active low)
1096 trcfg_i <= (others => '0');
1097 pmcfg_i <= (others => '0');
1098 l1_cnt_i := 0;
1099 l2_cnt_i := 0;
1100 grst <= '0';
1101 elsif clk_i'event and clk_i = '1' then -- rising clock edge
1102
1103 if (icmd_rs_trcfg_i = '1' or
1104 cmd_rs_trcfg_i = '1' or
1105 cmd_rcu_reset_i = '1' or
1106 cmd_glb_reset_i = '1') then
1107 trcfg_i <= (others => '0');
1108 elsif load_trcfg_i = '1' then
1109 trcfg_i <= idata_i;
1110 end if;
1111
1112 if (cmd_rcu_reset_i = '1' or
1113 cmd_glb_reset_i = '1') then
1114 pmcfg_i <= (others => '0');
1115 elsif load_pmcfg_i = '1' then
1116 pmcfg_i <= idata_i(19 downto 0);
1117 end if;
1118
1119 if (cmd_rcu_reset_i = '1' or
1120 cmd_glb_reset_i = '1') then
1121 afl_i <= (others => '0');
1122 elsif load_afl_i = '1' then
1123 afl_i <= idata_i(31 downto 0);
1124 end if;
1125
1126 if (cmd_rs_status_i = '1' or
1127 icmd_rs_status_i = '1' or
1128 cmd_rcu_reset_i = '1' or
1129 cmd_glb_reset_i = '1') then
1130 errst_i <= (others => '0');
1131 else
1132 errst_i(31) <= exec_busy_i;
1133 errst_i(30 downto 4) <= (others => '0');
1134 if eror = '0' then
1135 errst_i(3) <= '1';
1136 else
1137 errst_i(3) <= '0';
1138 end if;
1139 if cmd_abort_i = '1' then
1140 errst_i(1) <= '1';
1141 else
1142 errst_i(1) <= '0';
1143 end if;
1144 if timeout_i = '1' then
1145 errst_i(2) <= '1';
1146 else
1147 errst_i(2) <= '0';
1148 end if;
1149 errst_i(0) <= '0';
1150 end if;
1151
1152 l1_ii <= l1_i;
1153 l2_ii <= l2_i;
1154 if (cmd_rs_trcnt_i = '1' or
1155 icmd_rs_trcnt_i = '1' or
1156 cmd_rcu_reset_i = '1' or
1157 cmd_glb_reset_i = '1') then
1158 l1_cnt_i := 0;
1159 l2_cnt_i := 0;
1160 elsif l1_i = '0' and l1_ii = '1' then
1161 l1_cnt_i := l1_cnt_i + 1;
1162 elsif l2_i = '0' and l2_ii = '1' then
1163 l2_cnt_i := l2_cnt_i + 1;
1164 end if;
1165 trcnt_i <= int2slv(l2_cnt_i, 16) & int2slv(l1_cnt_i, 16);
1166
1167 -- Keep the fec reset down for at least 200 ns;
1168 if (cmd_glb_reset_i = '1' or cmd_fec_reset_i = '1') then
1169 rst_cnt_i := 8;
1170 grst <= '0';
1171 elsif rst_cnt_i > 0 then
1172 rst_cnt_i := rst_cnt_i - 1;
1173 grst <= '0';
1174 else
1175 grst <= '1';
1176 end if;
1177
1178 end if;
1179 end process registers;
1180
1181 -- purpose: Make triggers
1182 -- type : sequential
1183 -- inputs : clk_i, grst_i
1184 -- outputs:
1185 triggers : process (clk_i, grst_i)
1186 variable l0_dur_i : integer := 0;
1187 variable l1_dur_i : integer := 0;
1188 variable l2_dur_i : integer := 0;
1189 variable l1_wait_i : integer := 0;
1190 variable l2_wait_i : integer := 0;
1191 begin -- process triggers
1192 if grst_i = '0' then -- asynchronous reset (active low)
1193 trg_st_i <= idle;
1194 l0_i <= '0';
1195 l1_i <= '1';
1196 l2_i <= '1';
1197 elsif clk_i'event and clk_i = '1' then -- rising clock edge
1198 trg_st_i <= trg_st_i;
1199
1200 case trg_st_i is
1201 when idle =>
1202 l0_i <= '0';
1203 l1_i <= '1';
1204 l2_i <= '1';
1205 if ((cmd_l1_i = '1' or icmd_trigger_i = '1') and
1206 cmd_l1_cmd_i = '1' and trcfg_i(16 downto 15) = "10") then
1207 trg_st_i <= gen_l0;
1208 l0_dur_i := 8;
1209 l0_i <= '1';
1210 end if;
1211
1212 when gen_l0 =>
1213 if l0_dur_i = 0 then
1214 l1_wait_i := 5.5 us / 25 ns - 8;
1215 l0_i <= '0';
1216 trg_st_i <= wait_to_l2;
1217 else
1218 l0_i <= '1';
1219 l0_dur_i := l0_dur_i - 1;
1220 end if;
1221
1222 when wait_to_l1 =>
1223 if l2_wait_i = 0 then
1224 trg_st_i <= gen_l1;
1225 else
1226 l1_wait_i := l1_wait_i - 1;
1227 end if;
1228
1229 when gen_l1 =>
1230 if l1_dur_i = 0 then
1231 l2_wait_i := slv2int(trcfg_i(13 downto 0));
1232 l1_i <= '1';
1233 trg_st_i <= wait_to_l2;
1234 else
1235 l1_i <= '0';
1236 l1_dur_i := l1_dur_i - 1;
1237 end if;
1238
1239 when wait_to_l2 =>
1240 if l2_wait_i = 0 then
1241 trg_st_i <= gen_l2;
1242 else
1243 l2_wait_i := l2_wait_i - 1;
1244 end if;
1245
1246 when gen_l2 =>
1247 if l2_dur_i = 0 then
1248 l2_i <= '1';
1249 trg_st_i <= idle;
1250 else
1251 l2_i <= '0';
1252 l2_dur_i := l2_dur_i - 1;
1253 end if;
1254
1255 when others => null;
1256 end case;
1257 end if;
1258 end process triggers ;
1259
1260 -- Reset
1261 reset_it : entity rcu_model.reseter port map (rstb => grst_i);
1262
1263 -- 40 Mhz
1264 rclk_clocker : entity rcu_model.clocker
1265 generic map (PERIOD => 1 sec / 40000000)
1266 port map (clk => clk_i);
1267
1268 -- 10 MHz
1269 sclk_clocker : entity rcu_model.clocker
1270 generic map (PERIOD => 1 sec / 10000000)
1271 port map (clk => sclk_i);
1272
1273 -- 5 MHz
1274 scl_clocker : entity rcu_model.clocker
1275 generic map (PERIOD => 1 sec / 5000000)
1276 port map (clk => scl);
1277
1278 end architecture pipe_stim;
1279
1280 ------------------------------------------------------------------------------
1281 --
1282 -- EOF
1283 --
1284
This page was generated using GHDL 0.26 (20070408) [Sokcho edition], a program written by Tristan Gingold