Skip to content

Commit da47364

Browse files
Vendor proposed VUnit vc, not currently available in VUnit releases or pre-releases
1 parent ef8fa30 commit da47364

File tree

8 files changed

+397
-7
lines changed

8 files changed

+397
-7
lines changed

hdl/ip/vhd/vunit_components/BUCK

+9-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
load("//tools:hdl.bzl", "vhdl_unit", "vunit_sim")
1+
load("//tools:hdl.bzl", "vhdl_unit", "vunit_sim", "third_party")
22
load("//tools:rdl.bzl", "rdl_file")
33

44
vhdl_unit(
@@ -26,9 +26,17 @@ vhdl_unit(
2626
visibility = ['PUBLIC'],
2727
)
2828

29+
third_party(
30+
name = "spi_vcs",
31+
srcs = glob(["spi_controller/*.vhd"]),
32+
library = "vunit_lib",
33+
visibility = ['PUBLIC'],
34+
)
35+
2936
vhdl_unit(
3037
name = "basic_stream",
3138
srcs = glob(["basic_stream/*.vhd"]),
39+
3240
visibility = ['PUBLIC']
3341
)
3442

hdl/ip/vhd/vunit_components/qspi_controller/qspi_vc_pkg.vhd

+15-5
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,11 @@ use ieee.numeric_std.all;
1111
library vunit_lib;
1212
context vunit_lib.vunit_context;
1313
context vunit_lib.com_context;
14+
context vunit_lib.vc_context;
15+
1416
use vunit_lib.sync_pkg.all;
1517

18+
1619
package qspi_vc_pkg is
1720

1821
-- Message defs
@@ -48,13 +51,15 @@ package qspi_vc_pkg is
4851
p_actor : actor_t;
4952
p_ack_actor : actor_t;
5053
p_logger : logger_t;
54+
p_checker : checker_t;
5155
end record;
5256

53-
constant qspi_vc_logger : logger_t := get_logger("work:qspi_vc");
54-
5557
impure function new_qspi_vc (
5658
name : string := "";
57-
logger : logger_t := qspi_vc_logger
59+
logger : logger_t := null_logger;
60+
checker: checker_t := null_checker;
61+
actor : actor_t := null_actor;
62+
unexpected_msg_type_policy : unexpected_msg_type_policy_t := fail
5863
)
5964
return qspi_vc_t;
6065

@@ -130,15 +135,20 @@ package body qspi_vc_pkg is
130135
return qspi_mode_t'val(to_integer(unsigned(mode_vec)));
131136
end;
132137

138+
-- VUnit VC rule #2: constructor starts with "new_"
133139
impure function new_qspi_vc (
134140
name : string := "";
135-
logger : logger_t := qspi_vc_logger
141+
logger : logger_t := null_logger;
142+
checker: checker_t := null_checker;
143+
actor : actor_t := null_actor;
144+
unexpected_msg_type_policy : unexpected_msg_type_policy_t := fail
136145
)
137146
return qspi_vc_t is
138147
begin
139148
return (p_actor => new_actor(name),
140149
p_ack_actor => new_actor(name & " read-ack"),
141-
p_logger => logger
150+
p_logger => logger,
151+
p_checker => checker
142152
);
143153
end;
144154

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
These represent a "vendoring" of the files from
2+
https://github.com/VUnit/vunit/pull/1041/files
3+
a PR that hasn't merged into VUnit proper. Rather
4+
than write our own, or continue waiting, we've pulled
5+
them in here and will adjust/deprecate/remove when/if
6+
the PR finally lands in VUnit or VUnit figures out what
7+
to do with the impending "verification component restructure"
8+
9+
From here: https://github.com/n8tlarsen/vunit/tree/vc-spi
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
library ieee;
2+
use ieee.std_logic_1164.all;
3+
4+
use work.com_pkg.net;
5+
use work.com_pkg.receive;
6+
use work.com_pkg.reply;
7+
use work.com_types_pkg.all;
8+
use work.stream_master_pkg.all;
9+
use work.stream_slave_pkg.all;
10+
use work.sync_pkg.all;
11+
use work.spi_pkg.all;
12+
use work.queue_pkg.all;
13+
use work.sync_pkg.all;
14+
use work.print_pkg.all;
15+
use work.log_levels_pkg.all;
16+
use work.logger_pkg.all;
17+
use work.log_handler_pkg.all;
18+
19+
entity spi_master is
20+
generic (
21+
spi : spi_master_t
22+
);
23+
port (
24+
sclk : out std_logic := spi.p_cpol_mode;
25+
mosi : out std_logic := spi.p_idle_state;
26+
miso : in std_logic
27+
);
28+
end entity;
29+
30+
architecture a of spi_master is
31+
32+
constant din_queue : queue_t := new_queue;
33+
34+
begin
35+
36+
main : process
37+
38+
procedure spi_transaction(
39+
dout : std_logic_vector;
40+
frequency : integer;
41+
signal sclk : out std_logic;
42+
signal mosi : out std_logic;
43+
signal miso : in std_logic
44+
) is
45+
constant half_bit_time : time := (10**9 / (frequency*2)) * 1 ns;
46+
variable din : std_logic_vector(dout'length-1 downto 0);
47+
variable clk : std_logic := spi.p_cpol_mode;
48+
begin
49+
debug("Transmitting " & to_string(dout));
50+
sclk <= clk;
51+
mosi <= dout(dout'length-1);
52+
if (spi.p_cpha_mode = '0') then
53+
wait for half_bit_time;
54+
end if;
55+
clk := not clk;
56+
sclk <= clk;
57+
if (spi.p_cpha_mode = '0') then
58+
din(dout'length-1) := miso;
59+
end if;
60+
for b in dout'length-2 downto 0 loop
61+
wait for half_bit_time;
62+
clk := not clk;
63+
sclk <= clk;
64+
if (spi.p_cpha_mode = '0') then
65+
mosi <= dout(b);
66+
else
67+
din(b) := miso;
68+
end if;
69+
wait for half_bit_time;
70+
clk := not clk;
71+
sclk <= clk;
72+
if (spi.p_cpha_mode = '1') then
73+
mosi <= dout(b);
74+
else
75+
din(b) := miso;
76+
end if;
77+
end loop;
78+
wait for half_bit_time;
79+
sclk <= spi.p_cpol_mode;
80+
push_std_ulogic_vector(din_queue, din);
81+
end procedure;
82+
83+
variable query_msg : msg_t;
84+
variable reply_msg : msg_t;
85+
variable frequency : natural := spi.p_frequency;
86+
variable msg_type : msg_type_t;
87+
variable din : std_logic_vector(7 downto 0);
88+
89+
begin
90+
91+
receive(net, spi.p_actor, query_msg);
92+
msg_type := message_type(query_msg);
93+
94+
handle_sync_message(net, msg_type, query_msg);
95+
96+
if msg_type = stream_push_msg then
97+
spi_transaction(pop_std_ulogic_vector(query_msg), frequency, sclk, mosi, miso);
98+
elsif msg_type = stream_pop_msg then
99+
if (length(din_queue) > 0) then
100+
reply_msg := new_msg;
101+
push_std_ulogic_vector(reply_msg, pop_std_ulogic_vector(din_queue));
102+
push_boolean(reply_msg, false);
103+
reply(net, query_msg, reply_msg);
104+
else
105+
unexpected_msg_type(msg_type);
106+
end if;
107+
elsif msg_type = spi_set_frequency_msg then
108+
frequency := pop(query_msg);
109+
else
110+
unexpected_msg_type(msg_type);
111+
end if;
112+
113+
end process;
114+
115+
end architecture;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
library ieee;
2+
use ieee.std_logic_1164.all;
3+
4+
context work.com_context;
5+
use work.stream_master_pkg.all;
6+
use work.stream_slave_pkg.all;
7+
use work.sync_pkg.all;
8+
use work.integer_vector_ptr_pkg.all;
9+
use work.queue_pkg.all;
10+
11+
package spi_pkg is
12+
13+
type spi_master_t is record
14+
p_actor : actor_t;
15+
p_cpol_mode : std_logic;
16+
p_cpha_mode : std_logic;
17+
p_idle_state : std_logic;
18+
p_frequency : natural;
19+
end record;
20+
21+
type spi_slave_t is record
22+
p_actor : actor_t;
23+
p_cpol_mode : std_logic;
24+
p_cpha_mode : std_logic;
25+
end record;
26+
27+
procedure set_frequency(
28+
signal net : inout network_t;
29+
spi_master : spi_master_t;
30+
frequency : natural
31+
);
32+
33+
constant default_cpol_mode : std_logic := '0';
34+
constant default_cpha_mode : std_logic := '0';
35+
constant default_idle_state : std_logic := '0';
36+
constant default_frequency : natural := 1000000;
37+
38+
impure function new_spi_master(
39+
cpol_mode : std_logic := default_cpol_mode;
40+
cpha_mode : std_logic := default_cpha_mode;
41+
idle_state : std_logic := default_idle_state;
42+
initial_frequency : natural := default_frequency
43+
) return spi_master_t;
44+
45+
impure function new_spi_slave(
46+
cpol_mode : std_logic := default_cpol_mode;
47+
cpha_mode : std_logic := default_cpha_mode
48+
) return spi_slave_t;
49+
50+
impure function as_stream(spi_master : spi_master_t) return stream_master_t;
51+
impure function as_stream(spi_master : spi_master_t) return stream_slave_t;
52+
impure function as_stream(spi_slave : spi_slave_t) return stream_master_t;
53+
impure function as_stream(spi_slave : spi_slave_t) return stream_slave_t;
54+
impure function as_sync (spi_master : spi_master_t) return sync_handle_t;
55+
impure function as_sync (spi_slave : spi_slave_t) return sync_handle_t;
56+
57+
constant spi_set_frequency_msg : msg_type_t := new_msg_type("spi set frequency");
58+
59+
end package spi_pkg;
60+
61+
package body spi_pkg is
62+
63+
impure function new_spi_master(
64+
cpol_mode : std_logic := default_cpol_mode;
65+
cpha_mode : std_logic := default_cpha_mode;
66+
idle_state : std_logic := default_idle_state;
67+
initial_frequency : natural := default_frequency
68+
) return spi_master_t is
69+
begin
70+
return (
71+
p_actor => new_actor,
72+
p_cpol_mode => cpol_mode,
73+
p_cpha_mode => cpha_mode,
74+
p_idle_state => default_idle_state,
75+
p_frequency => initial_frequency
76+
);
77+
end function new_spi_master;
78+
79+
impure function new_spi_slave(
80+
cpol_mode : std_logic := default_cpol_mode;
81+
cpha_mode : std_logic := default_cpha_mode
82+
) return spi_slave_t is
83+
begin
84+
return (
85+
p_actor => new_actor,
86+
p_cpol_mode => cpol_mode,
87+
p_cpha_mode => cpha_mode
88+
);
89+
end function new_spi_slave;
90+
91+
impure function as_stream(spi_master : spi_master_t) return stream_master_t is
92+
begin
93+
return stream_master_t'(p_actor => spi_master.p_actor);
94+
end function as_stream;
95+
96+
impure function as_stream(spi_master : spi_master_t) return stream_slave_t is
97+
begin
98+
return stream_slave_t'(p_actor => spi_master.p_actor);
99+
end function as_stream;
100+
101+
impure function as_stream(spi_slave : spi_slave_t) return stream_master_t is
102+
begin
103+
return stream_master_t'(p_actor => spi_slave.p_actor);
104+
end function as_stream;
105+
106+
impure function as_stream(spi_slave : spi_slave_t) return stream_slave_t is
107+
begin
108+
return stream_slave_t'(p_actor => spi_slave.p_actor);
109+
end function as_stream;
110+
111+
impure function as_sync(spi_master : spi_master_t) return sync_handle_t is
112+
begin
113+
return spi_master.p_actor;
114+
end function as_sync;
115+
116+
impure function as_sync(spi_slave : spi_slave_t) return sync_handle_t is
117+
begin
118+
return spi_slave.p_actor;
119+
end function as_sync;
120+
121+
procedure set_frequency(
122+
signal net : inout network_t;
123+
spi_master : spi_master_t;
124+
frequency : natural
125+
) is
126+
variable msg : msg_t := new_msg(spi_set_frequency_msg);
127+
begin
128+
push(msg, frequency);
129+
send(net,spi_master.p_actor,msg);
130+
end procedure set_frequency;
131+
132+
end package body spi_pkg;

0 commit comments

Comments
 (0)