File: /__w/ctu-can-regression/ctu-can-regression/test/main_tb/agents/clock_agent/clk_gen_agent.vhd
0: --------------------------------------------------------------------------------
1: --
2: -- CTU CAN FD IP Core
3: -- Copyright (C) 2021-2023 Ondrej Ille
4: -- Copyright (C) 2023- Logic Design Services Ltd.s
5: --
6: -- Permission is hereby granted, free of charge, to any person obtaining a copy
7: -- of this VHDL component and associated documentation files (the "Component"),
8: -- to use, copy, modify, merge, publish, distribute the Component for
9: -- non-commercial purposes. Using the Component for commercial purposes is
10: -- forbidden unless previously agreed with Copyright holder.
11: --
12: -- The above copyright notice and this permission notice shall be included in
13: -- all copies or substantial portions of the Component.
14: --
15: -- THE COMPONENT IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16: -- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17: -- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18: -- AUTHORS OR COPYRIGHTHOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19: -- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20: -- FROM, OUT OF OR IN CONNECTION WITH THE COMPONENT OR THE USE OR OTHER DEALINGS
21: -- IN THE COMPONENT.
22: --
23: -- The CAN protocol is developed by Robert Bosch GmbH and protected by patents.
24: -- Anybody who wants to implement this IP core on silicon has to obtain a CAN
25: -- protocol license from Bosch.
26: --
27: -- -------------------------------------------------------------------------------
28: --
29: -- CTU CAN FD IP Core
30: -- Copyright (C) 2015-2020 MIT License
31: --
32: -- Authors:
33: -- Ondrej Ille <ondrej.ille@gmail.com>
34: -- Martin Jerabek <martin.jerabek01@gmail.com>
35: --
36: -- Project advisors:
37: -- Jiri Novak <jnovak@fel.cvut.cz>
38: -- Pavel Pisa <pisa@cmp.felk.cvut.cz>
39: --
40: -- Department of Measurement (http://meas.fel.cvut.cz/)
41: -- Faculty of Electrical Engineering (http://www.fel.cvut.cz)
42: -- Czech Technical University (http://www.cvut.cz/)
43: --
44: -- Permission is hereby granted, free of charge, to any person obtaining a copy
45: -- of this VHDL component and associated documentation files (the "Component"),
46: -- to deal in the Component without restriction, including without limitation
47: -- the rights to use, copy, modify, merge, publish, distribute, sublicense,
48: -- and/or sell copies of the Component, and to permit persons to whom the
49: -- Component is furnished to do so, subject to the following conditions:
50: --
51: -- The above copyright notice and this permission notice shall be included in
52: -- all copies or substantial portions of the Component.
53: --
54: -- THE COMPONENT IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
55: -- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
56: -- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
57: -- AUTHORS OR COPYRIGHTHOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
58: -- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
59: -- FROM, OUT OF OR IN CONNECTION WITH THE COMPONENT OR THE USE OR OTHER DEALINGS
60: -- IN THE COMPONENT.
61: --
62: -- The CAN protocol is developed by Robert Bosch GmbH and protected by patents.
63: -- Anybody who wants to implement this IP core on silicon has to obtain a CAN
64: -- protocol license from Bosch.
65: --
66: --------------------------------------------------------------------------------
67:
68: --------------------------------------------------------------------------------
69: -- @Purpose:
70: -- Clock generator agent.
71:
72: -- Clock generator agent generates clock (whoooa thats surprise right).
73: --
74: -- Clock generator agent only generates clock when it is enabled. When it is
75: -- disabled, its clock output remains in value which clock output had at
76: -- time when it was disabled.
77: --
78: -- Clock generator agent has following configurable parameters:
79: -- Clock period Obvious who does not know what clock period is should
80: -- not be reading this text.
81: -- Jitter Cycle to cycle jitter. Each clock cycle can last:
82: -- period +- "rand_val" where "rand_val" is less than
83: -- or equal to jitter.
84: -- Duty cycle Again, obvious, if you don't know what duty cycle
85: -- is, seriously, stop reading!
86: --
87: --------------------------------------------------------------------------------
88: -- Revision History:
89: -- 19.1.2020 Created file
90: -- 04.2.2021 Adjusted to work without Vunits COM library.
91: --------------------------------------------------------------------------------
92:
93: Library ctu_can_fd_tb;
94: context ctu_can_fd_tb.ieee_context;
95: context ctu_can_fd_tb.tb_common_context;
96:
97: use ctu_can_fd_tb.clk_gen_agent_pkg.all;
98: use ctu_can_fd_tb.tb_shared_vars_pkg.all;
99:
100: entity clk_gen_agent is
101: port (
102: -- Generated clock output
103: clock_out : out std_logic := '0';
104: clock_in : in std_logic
105: );
106: end entity;
107:
108: architecture tb of clk_gen_agent is
109:
110: ---------------------------------------------------------------------------
111: -- Parameters configured over communication library
112: ---------------------------------------------------------------------------
113:
114: -- Clock generator is enabled, clocks are being generated!
115: -- Note: This must be enabled by default when testbench is controlled from
116: -- SW, otherwise simulator will run out of events and timeout!
117: signal enabled : boolean := false;
118:
119: -- Generated clock period
120: signal period : time := 10 ns;
121:
122: -- Duty cycle of generated clock (in %)
123: signal duty : integer range 0 to 100 := 50;
124:
125: -- Jitter of generated clock (short time -> cycle to cycle)
126: signal jitter : time := 1 fs;
127:
128: -- High / Low times
129: signal t_low : time;
130: signal t_high : time;
131:
132: procedure recalc_parameters(
133: p_period : in time;
134: p_duty : in integer range 0 to 100;
135: signal p_t_low : out time;
136: signal p_t_high : out time
137: )is
138: begin
139: p_t_low <= p_period * (real(p_duty) / 100.0);
140: p_t_high <= p_period * (1.0 - (real(p_duty) / 100.0));
141: end;
142:
143: begin
144:
145: ---------------------------------------------------------------------------
146: -- Comunication receiver process
147: ---------------------------------------------------------------------------
148: receiver_proc : process
149: variable cmd : integer;
150: variable reply_code : integer;
151: begin
152: receive_start(default_channel, C_CLOCK_AGENT_ID);
153:
154: -- Command is sent as message type
155: reply_code := C_REPLY_CODE_OK;
156: cmd := com_channel_data.get_msg_code;
157:
158: case cmd is
159: when CLK_AGNT_CMD_START =>
160: enabled <= true;
161:
162: when CLK_AGNT_CMD_STOP =>
163: enabled <= false;
164:
165: when CLK_AGNT_CMD_PERIOD_SET =>
166: period <= com_channel_data.get_param;
167: recalc_parameters(period, duty, t_low, t_high);
168:
169: when CLK_AGNT_CMD_PERIOD_GET =>
170: com_channel_data.set_param(period);
171:
172: when CLK_AGNT_CMD_JITTER_SET =>
173: jitter <= com_channel_data.get_param;
174:
175: when CLK_AGNT_CMD_JITTER_GET =>
176: com_channel_data.set_param(jitter);
177:
178: when CLK_AGNT_CMD_DUTY_SET =>
179: duty <= com_channel_data.get_param;
180: recalc_parameters(period, duty, t_low, t_high);
181:
182: when CLK_AGNT_CMD_DUTY_GET =>
183: com_channel_data.set_param(duty);
184:
185: when CLK_AGNT_CMD_WAIT_CYCLE =>
186: wait until rising_edge(clock_in) for 1 us;
187:
188: when others =>
189: reply_code := C_REPLY_CODE_ERR;
190: end case;
191:
192: receive_finish(default_channel, reply_code);
193: end process;
194:
195:
196: ---------------------------------------------------------------------------
197: -- Clock generation process
198: ---------------------------------------------------------------------------
199: clk_gen_proc : process
200: variable t_high_with_jitter : time;
201: variable t_low_with_jitter : time;
202: variable rand_real : real;
203: variable rand_jitter : time;
204: variable seed1 : positive := 1;
205: variable seed2 : positive := 1;
206: variable jitter_div_2 : time;
207: begin
208: if (enabled) then
209:
210: if (jitter > 0 fs) then
211: uniform(seed1, seed2, rand_real);
212: rand_jitter := jitter * rand_real;
213: jitter_div_2 := jitter / 2;
214: t_high_with_jitter := (period + rand_jitter - jitter_div_2) * (real(duty) / 100.0);
215: t_low_with_jitter := (period + rand_jitter - jitter_div_2) * (1.0 - (real(duty) / 100.0));
216:
217: clock_out <= '1';
218: wait for t_high_with_jitter;
219: clock_out <= '0';
220: wait for t_low_with_jitter;
221: else
222: clock_out <= '1';
223: wait for t_high;
224: clock_out <= '0';
225: wait for t_low;
226: end if;
227: else
228: wait until enabled;
229: end if;
230: end process;
231:
232: end architecture;