Skip to content

Commit d823486

Browse files
Added iq modulator testbench
Added testbench for the gc_iq_modulator.vhd core. This uses the gc_iq_demodulator.vhd core to demodulate a cossine and checks if it is properly modulated again on the output.
1 parent e6afdd3 commit d823486

File tree

5 files changed

+200
-5
lines changed

5 files changed

+200
-5
lines changed
Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,2 @@
11
files = ["gc_iq_demod_tb.vhd",
2-
"../../../modules/dsp/gc_iq_demodulator.vhd"]
3-
# modules = {"local" : [
4-
# "../../../modules/dsp/gc_iq_demodulator.vhd"
5-
# ]
6-
# }
2+
"../../../modules/dsp/gc_iq_demodulator.vhd"]
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
files = ["gc_iq_mod_tb.vhd",
2+
"../../../modules/dsp/gc_iq_modulator.vhd",
3+
"../../../modules/dsp/gc_iq_demodulator.vhd"
4+
]
Lines changed: 180 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,180 @@
1+
-------------------------------------------------------------------------------
2+
-- Title : gc_iq_modulator.vhd testbench
3+
-- Project :
4+
-------------------------------------------------------------------------------
5+
-- File : gc_iq_mod_tb.vhd
6+
-- Author : David Daminelli <david.daminelli@lnls.br>
7+
-- Company : Brazilian Synchrotron Light Laboratory, LNLS/CNPEM
8+
-- Created : 2025-06-18
9+
-- Last update: 2025-06-18
10+
-- Platform :
11+
-- Standard : VHDL'08
12+
-------------------------------------------------------------------------------
13+
-- Description:
14+
-------------------------------------------------------------------------------
15+
-- Copyright (c) 2025 Brazilian Synchrotron Light Laboratory, LNLS/CNPEM
16+
--
17+
-------------------------------------------------------------------------------
18+
-- Revisions :
19+
-- Date Version Author Description
20+
-- 2025-06-18 1.0 david.daminelli Created
21+
-------------------------------------------------------------------------------
22+
23+
library ieee;
24+
use ieee.std_logic_1164.all;
25+
use ieee.numeric_std.all;
26+
use ieee.math_real.all;
27+
28+
library std;
29+
30+
library work;
31+
32+
entity gc_iq_mod_tb is
33+
end entity gc_iq_mod_tb;
34+
35+
architecture tb of gc_iq_mod_tb is
36+
-----------------------Procedure Declaration----------------------------------
37+
-- Clock Generation
38+
procedure f_gen_clk(constant freq : in natural;
39+
signal clk : inout std_logic) is
40+
begin
41+
loop
42+
wait for (0.5 / real(freq)) * 1 sec;
43+
clk <= not clk;
44+
end loop;
45+
end procedure f_gen_clk;
46+
47+
-- Wait procedure
48+
procedure f_wait_cycles(signal clk : in std_logic;
49+
constant cycles : natural) is
50+
begin
51+
for i in 1 to cycles loop
52+
wait until rising_edge(clk);
53+
end loop;
54+
end procedure f_wait_cycles;
55+
--------------------------- Constants Declaration ---------------------------
56+
constant c_clk_freq : natural := 100e3; -- Clk Freq
57+
constant c_in_freq : real := real(c_clk_freq)/4.1;
58+
constant c_N : positive := 16; -- data size
59+
----------------------------- Signal Declaration -----------------------------
60+
signal clk : std_logic := '0';
61+
signal rst : std_logic := '0';
62+
signal s_data_in : std_logic_vector(c_N-1 downto 0) := (others => '0');
63+
signal s_data_in_d0 : std_logic_vector(c_N-1 downto 0) := (others => '0');
64+
signal s_data_in_d1 : std_logic_vector(c_N-1 downto 0) := (others => '0');
65+
signal s_data_in_d2 : std_logic_vector(c_N-1 downto 0) := (others => '0');
66+
signal s_i_o, s_q_o : std_logic_vector(c_N-1 downto 0) := (others => '0');
67+
signal s_i_i, s_q_i : std_logic_vector(c_N downto 0) := (others => '0');
68+
signal s_sync, s_sync_d0 : std_logic := '0';
69+
signal s_timestamp : integer := 0;
70+
signal s_sine_amp : real := 0.0;
71+
signal s_sine_phs : real := math_pi/4.0;
72+
signal s_sine : real := 0.0;
73+
begin
74+
-------- Clock generation --------
75+
f_gen_clk(c_clk_freq, clk);
76+
77+
-------- Test Processes --------
78+
s_data_in <= std_logic_vector(to_signed(integer(s_sine), s_data_in'length));
79+
80+
-- Time stamp
81+
p_timestamp: process(clk)
82+
begin
83+
if rising_edge(clk) then
84+
if rst = '1' then
85+
s_timestamp <= 0;
86+
else
87+
s_timestamp <= s_timestamp + 1;
88+
end if;
89+
end if;
90+
end process;
91+
92+
-- delay the input in 3 cycles for comparting it with the outputs
93+
p_dly: process(clk)
94+
begin
95+
if rising_edge(clk) then
96+
s_data_in_d0 <= s_data_in;
97+
s_data_in_d1 <= s_data_in_d0;
98+
s_data_in_d2 <= s_data_in_d1;
99+
s_sync_d0 <= s_sync;
100+
end if;
101+
end process;
102+
103+
-- Sine generation
104+
p_sine: process(clk)
105+
begin
106+
if rising_edge(clk) then
107+
if rst = '1' then
108+
s_sine <= 0.0;
109+
else
110+
s_sine <= s_sine_amp *
111+
cos(2.0 * math_pi * c_in_freq *
112+
real(s_timestamp)/real(c_clk_freq)
113+
+ s_sine_phs);
114+
end if;
115+
end if;
116+
end process;
117+
118+
p_loop: process
119+
begin
120+
rst <= '1';
121+
f_wait_cycles(clk, 5);
122+
rst <= '0';
123+
f_wait_cycles(clk, 1);
124+
for i in 0 to c_N-1 loop -- Loop through c_N amplitudes
125+
s_sync <= '1';
126+
f_wait_cycles(clk, 1);
127+
s_sync <= '0';
128+
f_wait_cycles(clk, 1);
129+
s_sine_amp <= 2.0**real(i) - 1.0;
130+
for j in 0 to 19 loop -- Loop through 20 phases
131+
s_sine_phs <= real(j) * 2.0*math_pi/20.0;
132+
f_wait_cycles(clk, 50); -- wait 50 cycles in each value
133+
end loop;
134+
end loop;
135+
report "Finished!";
136+
std.env.finish;
137+
end process;
138+
139+
p_assert: process(clk)
140+
variable v_error : signed(s_i_o'range) := (others => '0');
141+
begin
142+
if rising_edge(clk) then
143+
v_error := signed(s_i_o) - signed(s_data_in_d2);
144+
assert to_integer(v_error) = 0
145+
report "Error in output value"
146+
severity warning;
147+
end if;
148+
end process;
149+
150+
------ Entity declaration ------
151+
UUT: entity work.gc_iq_modulator
152+
generic map (
153+
g_N => c_N
154+
)
155+
port map (
156+
clk_i => clk,
157+
en_i => '1',
158+
rst_i => rst,
159+
sync_p1_i => s_sync_d0,
160+
i_i => s_i_i(c_N-1 downto 0),
161+
q_i => s_q_i(c_N-1 downto 0),
162+
i_o => s_i_o,
163+
q_o => s_q_o
164+
);
165+
166+
------ Entity declaration ------
167+
UUT2: entity work.gc_iq_demodulator
168+
generic map (
169+
g_N => c_N
170+
)
171+
port map (
172+
clk_i => clk,
173+
rst_i => rst,
174+
sync_p1_i => s_sync,
175+
adc_data_i => s_data_in,
176+
i_o => s_i_i,
177+
q_o => s_q_i
178+
);
179+
180+
end architecture tb;
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
gc_iq_mod_tb
2+
gc_iq_mod_tb.ghw
3+
*.cf
4+
*.o
5+
Makefile
6+
work/
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
action = "simulation"
2+
sim_tool = "ghdl"
3+
top_module = "gc_iq_mod_tb"
4+
5+
modules = {"local" : ["../"]}
6+
7+
ghdl_opt = "--std=08 -fsynopsys -g"
8+
9+
sim_post_cmd = "ghdl -r --std=93 %s --wave=%s.ghw --assert-level=error" % (top_module, top_module)

0 commit comments

Comments
 (0)