Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions examples/vhdl/uart/run.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,4 +27,14 @@
VU.add_library("uart_lib").add_source_files(SRC_PATH / "*.vhd")
VU.add_library("tb_uart_lib").add_source_files(SRC_PATH / "test" / "*.vhd")

for tb in VU.library("tb_uart_lib").get_test_benches():
for parity in [0, 1, 2]:
generics = dict(
parity=parity
)
tb.add_config(
name=",".join("{}={}".format(k, v) for (k, v) in generics.items()),
generics=generics,
)

VU.main()
9 changes: 6 additions & 3 deletions examples/vhdl/uart/src/test/tb_uart_rx.vhd
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@ library uart_lib;

entity tb_uart_rx is
generic (
runner_cfg : string);
runner_cfg : string;
parity : natural);
end entity;

architecture tb of tb_uart_rx is
Expand All @@ -33,7 +34,8 @@ architecture tb of tb_uart_rx is

signal num_overflows : integer := 0;

constant uart_bfm : uart_master_t := new_uart_master(initial_baud_rate => baud_rate);
constant uart_bfm : uart_master_t := new_uart_master(initial_baud_rate => baud_rate,
initial_parity => parity);
constant uart_stream : stream_master_t := as_stream(uart_bfm);

constant axi_stream_bfm : axi_stream_slave_t := new_axi_stream_slave(data_length => tdata'length);
Expand Down Expand Up @@ -87,7 +89,8 @@ begin

dut : entity uart_lib.uart_rx
generic map (
cycles_per_bit => cycles_per_bit)
cycles_per_bit => cycles_per_bit,
parity => parity)
port map (
clk => clk,
rx => rx,
Expand Down
7 changes: 5 additions & 2 deletions examples/vhdl/uart/src/test/tb_uart_tx.vhd
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@ library uart_lib;

entity tb_uart_tx is
generic (
runner_cfg : string);
runner_cfg : string;
parity : natural);
end entity;

architecture tb of tb_uart_tx is
Expand All @@ -35,6 +36,7 @@ architecture tb of tb_uart_tx is

shared variable rnd_stimuli, rnd_expected : RandomPType;
constant uart_bfm : uart_slave_t := new_uart_slave(initial_baud_rate => baud_rate,
initial_parity => parity,
data_length => tdata'length);
constant uart_stream : stream_slave_t := as_stream(uart_bfm);

Expand Down Expand Up @@ -79,7 +81,8 @@ begin

dut : entity uart_lib.uart_tx
generic map (
cycles_per_bit => cycles_per_bit)
cycles_per_bit => cycles_per_bit,
parity => parity)
port map (
clk => clk,
tx => tx,
Expand Down
26 changes: 23 additions & 3 deletions examples/vhdl/uart/src/uart_rx.vhd
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ use vunit_lib.logger_pkg.all;

entity uart_rx is
generic (
cycles_per_bit : natural := 434);
cycles_per_bit : natural := 434;
parity : natural := 0);
port (
clk : in std_logic;

Expand All @@ -29,6 +30,7 @@ entity uart_rx is
tvalid : out std_Logic := '0';
tdata : out std_logic_vector(7 downto 0));
begin

-- pragma translate_off
check_stable(clk, check_enabled, tvalid, tready, tdata, "tdata must be stable until tready is active");
check_stable(clk, check_enabled, tvalid, tready, tvalid, "tvalid must be active until tready is active");
Expand All @@ -46,12 +48,30 @@ end entity;

architecture a of uart_rx is
signal tvalid_int : std_logic := '0';

function data_size(
constant parity: natural
) return natural is
begin
if parity = 0 then
-- uart data (8 bits)
return 8;
elsif parity = 1 or parity = 2 then
-- uart data (8 bits)+ parity
return 9;
else
-- invalid mode
return 0;
end if;
end function data_size;

begin
main : process (clk)
type state_t is (idle, receiving, done);
variable state : state_t := idle;
variable datawidth : natural := data_size(parity);
variable cycles : natural range 0 to cycles_per_bit-1 := 0;
variable data : std_logic_vector(7 downto 0);
variable data : std_logic_vector(datawidth-1 downto 0);
variable index : natural range 0 to data'length-1 := 0;
begin
if rising_edge(clk) then
Expand Down Expand Up @@ -89,7 +109,7 @@ begin
-- New output overwrites old output
overflow <= tvalid_int and not tready;
tvalid_int <= '1';
tdata <= data;
tdata <= data(7 downto 0);
state := idle;
end case;

Expand Down
44 changes: 41 additions & 3 deletions examples/vhdl/uart/src/uart_tx.vhd
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ use vunit_lib.logger_pkg.all;

entity uart_tx is
generic (
cycles_per_bit : natural := 434);
cycles_per_bit : natural := 434;
parity : natural := 0);
port (
clk : in std_logic;

Expand Down Expand Up @@ -44,12 +45,42 @@ end entity;

architecture a of uart_tx is
signal tready_int : std_logic := '0';

function data_size(
constant parity: natural
) return natural is
begin
if parity = 0 then
-- uart data (8 bits)
return 8;
elsif parity = 1 or parity = 2 then
-- uart data (8 bits)+ parity
return 9;
else
-- invalid mode
return 0;
end if;
end function data_size;

function even_parity (data : std_logic_vector) return std_logic is
begin
return xor data;

end function even_parity;

function odd_parity (data : std_logic_vector) return std_logic is
begin

return xnor data;
end function odd_parity;

begin
main : process (clk)
type state_t is (idle, sending);
variable state : state_t := idle;
variable datawidth : natural := data_size(parity) + 2;
variable cycles : natural range 0 to cycles_per_bit-1 := 0;
variable data : std_logic_vector(9 downto 0);
variable data : std_logic_vector(datawidth-1 downto 0);
variable index : natural range 0 to data'length-1 := 0;
begin
if rising_edge(clk) then
Expand All @@ -60,7 +91,14 @@ begin
state := sending;
cycles := 0;
index := 0;
data := '1' & tdata & '0';

if parity = 0 then
data := '1' & tdata & '0';
elsif parity = 1 then
data := '1' & odd_parity(tdata) & tdata & '0';
elsif parity = 2 then
data := '1' & even_parity(tdata) & tdata & '0';
end if;
end if;
when sending =>
tx <= data(0);
Expand Down
24 changes: 19 additions & 5 deletions vunit/vhdl/verification_components/src/uart_master.vhd
Original file line number Diff line number Diff line change
Expand Up @@ -17,18 +17,22 @@ use work.uart_pkg.all;

entity uart_master is
generic (
uart : uart_master_t);
uart : uart_master_t
);
port (
tx : out std_logic := uart.p_idle_state);
end entity;
tx : out std_logic := uart.p_idle_state
);
end entity uart_master;

architecture a of uart_master is
begin

main : process
procedure uart_send(data : std_logic_vector;
signal tx : out std_logic;
baud_rate : integer) is
baud_rate : integer;
parity : natural
) is
constant time_per_bit : time := (10**9 / baud_rate) * 1 ns;

procedure send_bit(value : std_logic) is
Expand All @@ -43,11 +47,19 @@ begin
for i in 0 to data'length-1 loop
send_bit(data(i));
end loop;

if parity = 1 then
send_bit(odd_parity(data));
elsif parity = 2 then
send_bit(even_parity(data));
end if;

send_bit(uart.p_idle_state);
end procedure;

variable msg : msg_t;
variable baud_rate : natural := uart.p_baud_rate;
variable parity : natural := uart.p_parity;
variable msg_type : msg_type_t;
begin
receive(net, uart.p_actor, msg);
Expand All @@ -56,9 +68,11 @@ begin
handle_sync_message(net, msg_type, msg);

if msg_type = stream_push_msg then
uart_send(pop_std_ulogic_vector(msg), tx, baud_rate);
uart_send(pop_std_ulogic_vector(msg), tx, baud_rate, parity);
elsif msg_type = uart_set_baud_rate_msg then
baud_rate := pop(msg);
elsif msg_type = uart_set_parity_msg then
parity := pop(msg);
else
unexpected_msg_type(msg_type);
end if;
Expand Down
74 changes: 71 additions & 3 deletions vunit/vhdl/verification_components/src/uart_pkg.vhd
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,14 @@ package uart_pkg is
type uart_master_t is record
p_actor : actor_t;
p_baud_rate : natural;
p_parity : natural;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Create an enumerated type parity_t for this.

p_idle_state : std_logic;
end record;
end record uart_master_t;

type uart_slave_t is record
p_actor : actor_t;
p_baud_rate : natural;
p_parity : natural;
p_idle_state : std_logic;
p_data_length : positive;
end record;
Expand All @@ -37,12 +39,25 @@ package uart_pkg is
uart_slave : uart_slave_t;
baud_rate : natural);

-- 0 = no parity, 1 = odd parity, 2 = even parity
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These are suitable names for the values of parity_t.

procedure set_parity(signal net : inout network_t;
uart_master : uart_master_t;
parity : natural);

procedure set_parity(signal net : inout network_t;
uart_slave : uart_slave_t;
parity : natural);

constant default_baud_rate : natural := 115200;
constant default_idle_state : std_logic := '1';
constant default_data_length : positive := 8;
constant default_parity : natural := 0;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Better to use the no_parity enum directly.


impure function new_uart_master(initial_baud_rate : natural := default_baud_rate;
initial_parity : natural := default_parity;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add new parameters to the end to avoid breaking existing implementations.

idle_state : std_logic := default_idle_state) return uart_master_t;
impure function new_uart_slave(initial_baud_rate : natural := default_baud_rate;
initial_parity : natural := default_parity;
idle_state : std_logic := default_idle_state;
data_length : positive := default_data_length) return uart_slave_t;

Expand All @@ -52,24 +67,37 @@ package uart_pkg is
impure function as_sync(uart_slave : uart_slave_t) return sync_handle_t;

constant uart_set_baud_rate_msg : msg_type_t := new_msg_type("uart set baud rate");

constant uart_set_parity_msg : msg_type_t := new_msg_type("uart set parity rate");
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No "rate" in the message name.


function even_parity(data : std_logic_vector) return std_logic;
function odd_parity (data : std_logic_vector) return std_logic;

end package;

package body uart_pkg is

impure function new_uart_master(initial_baud_rate : natural := default_baud_rate;
initial_parity : natural := default_parity;
idle_state : std_logic := default_idle_state) return uart_master_t is
begin
return (p_actor => new_actor,
p_baud_rate => initial_baud_rate,
p_parity => initial_parity,
p_idle_state => idle_state);
end;

impure function new_uart_slave(initial_baud_rate : natural := default_baud_rate;
impure function new_uart_slave(
initial_baud_rate : natural := default_baud_rate;
initial_parity : natural := default_parity;
idle_state : std_logic := default_idle_state;
data_length : positive := default_data_length) return uart_slave_t is
data_length : positive := default_data_length
) return uart_slave_t is

begin
return (p_actor => new_actor,
p_baud_rate => initial_baud_rate,
p_parity => initial_parity,
p_idle_state => idle_state,
p_data_length => data_length);
end;
Expand Down Expand Up @@ -116,4 +144,44 @@ package body uart_pkg is
begin
set_baud_rate(net, uart_slave.p_actor, baud_rate);
end;

procedure set_parity(signal net : inout network_t;
actor : actor_t;
parity : natural) is
variable msg : msg_t := new_msg(uart_set_parity_msg);
begin
if parity > 2 then
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No need for this check with an enumerated type

report "Invalid parity value: " & to_string(parity)
severity error;
end if;

push(msg, parity);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Push parity_t'pos(parity)

send(net, actor, msg);
end;

procedure set_parity(signal net : inout network_t;
uart_master : uart_master_t;
parity : natural) is
begin
set_parity(net, uart_master.p_actor, parity);
end;

procedure set_parity(signal net : inout network_t;
uart_slave : uart_slave_t;
parity : natural) is
begin
set_parity(net, uart_slave.p_actor, parity);
end;

function even_parity (data : std_logic_vector) return std_logic is
begin
return xor data;

end function even_parity;

function odd_parity (data : std_logic_vector) return std_logic is
begin

return xnor data;
end function odd_parity;
end package body;
Loading
Loading