chapter13 - PacoReinaCampo/SoC-MSP430 GitHub Wiki
HARDWARE VERIFICATION
.. ....... ........ ........ ....... .. ........... ...... .... .. ...... ..... .. ..... .... ........ ... ...... . ... .... .. ......... ........... .... .... ........ .. .... . ..... ....... .... ... ........ .... ............ .. ... ... ....... .. ...... .... ... .... ....... .. ..... ... .... ....... ... ....... ......... ..... .......... ....... ..... ....... ... ....... ... ....... ..... ..... .... . ........ .. ... ..... ......... .. ........ ..... ....... .......... .......... ... ........ .. ... ..... .. ........ ..... .......... .... ... ...... .. .....
$$Verification(UVM): Design(HDL)=Model(HDL)?$$
.. ....... ........ ........ ....... .. ........... ...... .... .. ...... ..... .. ..... .... ........ ... ...... . ... .... .. ......... ........... .... .... ........ .. .... . ..... ....... .... ... ........ .... ............ .. ... ... ....... .. ...... .... ... .... ....... .. ..... ... .... ....... ... ....... ......... ..... .......... ....... ..... ....... ... ....... ... ....... ..... ..... .... . ........ .. ... ..... ......... .. ........ ..... ....... .......... .......... ... ........ .. ... ..... .. ........ ..... .......... .... ... ...... .. .....
$$FormalVerification(UVM): Design(HDL)=Requirements(PSL)?$$
.. ....... ........ ........ ....... .. ........... ...... .... .. ...... ..... .. ..... .... ........ ... ...... . ... .... .. ......... ........... .... .... ........ .. .... . ..... ....... .... ... ........ .... ............ .. ... ... ....... .. ...... .... ... .... ....... .. ..... ... .... ....... ... ....... ......... ..... .......... ....... ..... ....... ... ....... ... ....... ..... ..... .... . ........ .. ... ..... ......... .. ........ ..... ....... .......... .......... ... ........ .. ... ..... .. ........ ..... .......... .... ... ...... .. .....
.. ....... ........ ........ ....... .. ........... ...... .... .. ...... ..... .. ..... .... ........ ... ...... . ... .... .. ......... ........... .... .... ........ .. .... . ..... ....... .... ... ........ .... ............ .. ... ... ....... .. ...... .... ... .... ....... .. ..... ... .... ....... ... ....... ......... ..... .......... ....... ..... ....... ... ....... ... ....... ..... ..... .... . ........ .. ... ..... ......... .. ........ ..... ....... .......... .......... ... ........ .. ... ..... .. ........ ..... .......... .... ... ...... .. .....
TESTS METHODOLOGY
.. ....... ........ ........ ....... .. ........... ...... .... .. ...... ..... .. ..... .... ........ ... ...... . ... .... .. ......... ........... .... .... ........ .. .... . ..... ....... .... ... ........ .... ............ .. ... ... ....... .. ...... .... ... .... ....... .. ..... ... .... ....... ... ....... ......... ..... .......... ....... ..... ....... ... ....... ... ....... ..... ..... .... . ........ .. ... ..... ......... .. ........ ..... ....... .......... .......... ... ........ .. ... ..... .. ........ ..... .......... .... ... ...... .. .....
Testbench Architecture
.. ....... ........ ........ ....... .. ........... ...... .... .. ...... ..... .. ..... .... ........ ... ...... . ... .... .. ......... ........... .... .... ........ .. .... . ..... ....... .... ... ........ .... ............ .. ... ... ....... .. ...... .... ... .... ....... .. ..... ... .... ....... ... ....... ......... ..... .......... ....... ..... ....... ... ....... ... ....... ..... ..... .... . ........ .. ... ..... ......... .. ........ ..... ....... .......... .......... ... ........ .. ... ..... .. ........ ..... .......... .... ... ...... .. .....
Stimulus
.. ....... ........ ........ ....... .. ........... ...... .... .. ...... ..... .. ..... .... ........ ... ...... . ... .... .. ......... ........... .... .... ........ .. .... . ..... ....... .... ... ........ .... ............ .. ... ... ....... .. ...... .... ... .... ....... .. ..... ... .... ....... ... ....... ......... ..... .......... ....... ..... ....... ... ....... ... ....... ..... ..... .... . ........ .. ... ..... ......... .. ........ ..... ....... .......... .......... ... ........ .. ... ..... .. ........ ..... .......... .... ... ...... .. .....
Asserts
.. ....... ........ ........ ....... .. ........... ...... .... .. ...... ..... .. ..... .... ........ ... ...... . ... .... .. ......... ........... .... .... ........ .. .... . ..... ....... .... ... ........ .... ............ .. ... ... ....... .. ...... .... ... .... ....... .. ..... ... .... ....... ... ....... ......... ..... .......... ....... ..... ....... ... ....... ... ....... ..... ..... .... . ........ .. ... ..... ......... .. ........ ..... ....... .......... .......... ... ........ .. ... ..... .. ........ ..... .......... .... ... ...... .. .....
Bus Verification
.. ....... ........ ........ ....... .. ........... ...... .... .. ...... ..... .. ..... .... ........ ... ...... . ... .... .. ......... ........... .... .... ........ .. .... . ..... ....... .... ... ........ .... ............ .. ... ... ....... .. ...... .... ... .... ....... .. ..... ... .... ....... ... ....... ......... ..... .......... ....... ..... ....... ... ....... ... ....... ..... ..... .... . ........ .. ... ..... ......... .. ........ ..... ....... .......... .......... ... ........ .. ... ..... .. ........ ..... .......... .... ... ...... .. .....
AMBA4 AXI-Lite Bus
.. ....... ........ ........ ....... .. ........... ...... .... .. ...... ..... .. ..... .... ........ ... ...... . ... .... .. ......... ........... .... .... ........ .. .... . ..... ....... .... ... ........ .... ............ .. ... ... ....... .. ...... .... ... .... ....... .. ..... ... .... ....... ... ....... ......... ..... .......... ....... ..... ....... ... ....... ... ....... ..... ..... .... . ........ .. ... ..... ......... .. ........ ..... ....... .......... .......... ... ........ .. ... ..... .. ........ ..... .......... .... ... ...... .. .....
AMBA3 AHB-Lite Bus
.. ....... ........ ........ ....... .. ........... ...... .... .. ...... ..... .. ..... .... ........ ... ...... . ... .... .. ......... ........... .... .... ........ .. .... . ..... ....... .... ... ........ .... ............ .. ... ... ....... .. ...... .... ... .... ....... .. ..... ... .... ....... ... ....... ......... ..... .......... ....... ..... ....... ... ....... ... ....... ..... ..... .... . ........ .. ... ..... ......... .. ........ ..... ....... .......... .......... ... ........ .. ... ..... .. ........ ..... .......... .... ... ...... .. .....
WishBone Bus
.. ....... ........ ........ ....... .. ........... ...... .... .. ...... ..... .. ..... .... ........ ... ...... . ... .... .. ......... ........... .... .... ........ .. .... . ..... ....... .... ... ........ .... ............ .. ... ... ....... .. ...... .... ... .... ....... .. ..... ... .... ....... ... ....... ......... ..... .......... ....... ..... ....... ... ....... ... ....... ..... ..... .... . ........ .. ... ..... ......... .. ........ ..... ....... .......... .......... ... ........ .. ... ..... .. ........ ..... .......... .... ... ...... .. .....
Design Under Verification
.. ....... ........ ........ ....... .. ........... ...... .... .. ...... ..... .. ..... .... ........ ... ...... . ... .... .. ......... ........... .... .... ........ .. .... . ..... ....... .... ... ........ .... ............ .. ... ... ....... .. ...... .... ... .... ....... .. ..... ... .... ....... ... ....... ......... ..... .......... ....... ..... ....... ... ....... ... ....... ..... ..... .... . ........ .. ... ..... ......... .. ........ ..... ....... .......... .......... ... ........ .. ... ..... .. ........ ..... .......... .... ... ...... .. .....
PROCEDURES METHODOLOGY
.. ....... ........ ........ ....... .. ........... ...... .... .. ...... ..... .. ..... .... ........ ... ...... . ... .... .. ......... ........... .... .... ........ .. .... . ..... ....... .... ... ........ .... ............ .. ... ... ....... .. ...... .... ... .... ....... .. ..... ... .... ....... ... ....... ......... ..... .......... ....... ..... ....... ... ....... ... ....... ..... ..... .... . ........ .. ... ..... ......... .. ........ ..... ....... .......... .......... ... ........ .. ... ..... .. ........ ..... .......... .... ... ...... .. .....
Procedures Testbench Architecture
.. ....... ........ ........ ....... .. ........... ...... .... .. ...... ..... .. ..... .... ........ ... ...... . ... .... .. ......... ........... .... .... ........ .. .... . ..... ....... .... ... ........ .... ............ .. ... ... ....... .. ...... .... ... .... ....... .. ..... ... .... ....... ... ....... ......... ..... .......... ....... ..... ....... ... ....... ... ....... ..... ..... .... . ........ .. ... ..... ......... .. ........ ..... ....... .......... .......... ... ........ .. ... ..... .. ........ ..... .......... .... ... ...... .. .....
Procedures Stimulus
.. ....... ........ ........ ....... .. ........... ...... .... .. ...... ..... .. ..... .... ........ ... ...... . ... .... .. ......... ........... .... .... ........ .. .... . ..... ....... .... ... ........ .... ............ .. ... ... ....... .. ...... .... ... .... ....... .. ..... ... .... ....... ... ....... ......... ..... .......... ....... ..... ....... ... ....... ... ....... ..... ..... .... . ........ .. ... ..... ......... .. ........ ..... ....... .......... .......... ... ........ .. ... ..... .. ........ ..... .......... .... ... ...... .. .....
Procedures Asserts
.. ....... ........ ........ ....... .. ........... ...... .... .. ...... ..... .. ..... .... ........ ... ...... . ... .... .. ......... ........... .... .... ........ .. .... . ..... ....... .... ... ........ .... ............ .. ... ... ....... .. ...... .... ... .... ....... .. ..... ... .... ....... ... ....... ......... ..... .......... ....... ..... ....... ... ....... ... ....... ..... ..... .... . ........ .. ... ..... ......... .. ........ ..... ....... .......... .......... ... ........ .. ... ..... .. ........ ..... .......... .... ... ...... .. .....
Bus Verification
.. ....... ........ ........ ....... .. ........... ...... .... .. ...... ..... .. ..... .... ........ ... ...... . ... .... .. ......... ........... .... .... ........ .. .... . ..... ....... .... ... ........ .... ............ .. ... ... ....... .. ...... .... ... .... ....... .. ..... ... .... ....... ... ....... ......... ..... .......... ....... ..... ....... ... ....... ... ....... ..... ..... .... . ........ .. ... ..... ......... .. ........ ..... ....... .......... .......... ... ........ .. ... ..... .. ........ ..... .......... .... ... ...... .. .....
AMBA4 AXI-Lite Bus
.. ....... ........ ........ ....... .. ........... ...... .... .. ...... ..... .. ..... .... ........ ... ...... . ... .... .. ......... ........... .... .... ........ .. .... . ..... ....... .... ... ........ .... ............ .. ... ... ....... .. ...... .... ... .... ....... .. ..... ... .... ....... ... ....... ......... ..... .......... ....... ..... ....... ... ....... ... ....... ..... ..... .... . ........ .. ... ..... ......... .. ........ ..... ....... .......... .......... ... ........ .. ... ..... .. ........ ..... .......... .... ... ...... .. .....
AMBA3 AHB-Lite Bus
.. ....... ........ ........ ....... .. ........... ...... .... .. ...... ..... .. ..... .... ........ ... ...... . ... .... .. ......... ........... .... .... ........ .. .... . ..... ....... .... ... ........ .... ............ .. ... ... ....... .. ...... .... ... .... ....... .. ..... ... .... ....... ... ....... ......... ..... .......... ....... ..... ....... ... ....... ... ....... ..... ..... .... . ........ .. ... ..... ......... .. ........ ..... ....... .......... .......... ... ........ .. ... ..... .. ........ ..... .......... .... ... ...... .. .....
WishBone Bus
.. ....... ........ ........ ....... .. ........... ...... .... .. ...... ..... .. ..... .... ........ ... ...... . ... .... .. ......... ........... .... .... ........ .. .... . ..... ....... .... ... ........ .... ............ .. ... ... ....... .. ...... .... ... .... ....... .. ..... ... .... ....... ... ....... ......... ..... .......... ....... ..... ....... ... ....... ... ....... ..... ..... .... . ........ .. ... ..... ......... .. ........ ..... ....... .......... .......... ... ........ .. ... ..... .. ........ ..... .......... .... ... ...... .. .....
Design Under Verification
.. ....... ........ ........ ....... .. ........... ...... .... .. ...... ..... .. ..... .... ........ ... ...... . ... .... .. ......... ........... .... .... ........ .. .... . ..... ....... .... ... ........ .... ............ .. ... ... ....... .. ...... .... ... .... ....... .. ..... ... .... ....... ... ....... ......... ..... .......... ....... ..... ....... ... ....... ... ....... ..... ..... .... . ........ .. ... ..... ......... .. ........ ..... ....... .......... .......... ... ........ .. ... ..... .. ........ ..... .......... .... ... ...... .. .....
CLASSES METHODOLOGY
.. ....... ........ ........ ....... .. ........... ...... .... .. ...... ..... .. ..... .... ........ ... ...... . ... .... .. ......... ........... .... .... ........ .. .... . ..... ....... .... ... ........ .... ............ .. ... ... ....... .. ...... .... ... .... ....... .. ..... ... .... ....... ... ....... ......... ..... .......... ....... ..... ....... ... ....... ... ....... ..... ..... .... . ........ .. ... ..... ......... .. ........ ..... ....... .......... .......... ... ........ .. ... ..... .. ........ ..... .......... .... ... ...... .. .....
Classes Testbench Architecture
.. ....... ........ ........ ....... .. ........... ...... .... .. ...... ..... .. ..... .... ........ ... ...... . ... .... .. ......... ........... .... .... ........ .. .... . ..... ....... .... ... ........ .... ............ .. ... ... ....... .. ...... .... ... .... ....... .. ..... ... .... ....... ... ....... ......... ..... .......... ....... ..... ....... ... ....... ... ....... ..... ..... .... . ........ .. ... ..... ......... .. ........ ..... ....... .......... .......... ... ........ .. ... ..... .. ........ ..... .......... .... ... ...... .. .....
Classes Stimulus
.. ....... ........ ........ ....... .. ........... ...... .... .. ...... ..... .. ..... .... ........ ... ...... . ... .... .. ......... ........... .... .... ........ .. .... . ..... ....... .... ... ........ .... ............ .. ... ... ....... .. ...... .... ... .... ....... .. ..... ... .... ....... ... ....... ......... ..... .......... ....... ..... ....... ... ....... ... ....... ..... ..... .... . ........ .. ... ..... ......... .. ........ ..... ....... .......... .......... ... ........ .. ... ..... .. ........ ..... .......... .... ... ...... .. .....
Classes Asserts
.. ....... ........ ........ ....... .. ........... ...... .... .. ...... ..... .. ..... .... ........ ... ...... . ... .... .. ......... ........... .... .... ........ .. .... . ..... ....... .... ... ........ .... ............ .. ... ... ....... .. ...... .... ... .... ....... .. ..... ... .... ....... ... ....... ......... ..... .......... ....... ..... ....... ... ....... ... ....... ..... ..... .... . ........ .. ... ..... ......... .. ........ ..... ....... .......... .......... ... ........ .. ... ..... .. ........ ..... .......... .... ... ...... .. .....
Bus Verification
.. ....... ........ ........ ....... .. ........... ...... .... .. ...... ..... .. ..... .... ........ ... ...... . ... .... .. ......... ........... .... .... ........ .. .... . ..... ....... .... ... ........ .... ............ .. ... ... ....... .. ...... .... ... .... ....... .. ..... ... .... ....... ... ....... ......... ..... .......... ....... ..... ....... ... ....... ... ....... ..... ..... .... . ........ .. ... ..... ......... .. ........ ..... ....... .......... .......... ... ........ .. ... ..... .. ........ ..... .......... .... ... ...... .. .....
AMBA4 AXI-Lite Bus
.. ....... ........ ........ ....... .. ........... ...... .... .. ...... ..... .. ..... .... ........ ... ...... . ... .... .. ......... ........... .... .... ........ .. .... . ..... ....... .... ... ........ .... ............ .. ... ... ....... .. ...... .... ... .... ....... .. ..... ... .... ....... ... ....... ......... ..... .......... ....... ..... ....... ... ....... ... ....... ..... ..... .... . ........ .. ... ..... ......... .. ........ ..... ....... .......... .......... ... ........ .. ... ..... .. ........ ..... .......... .... ... ...... .. .....
AMBA3 AHB-Lite Bus
.. ....... ........ ........ ....... .. ........... ...... .... .. ...... ..... .. ..... .... ........ ... ...... . ... .... .. ......... ........... .... .... ........ .. .... . ..... ....... .... ... ........ .... ............ .. ... ... ....... .. ...... .... ... .... ....... .. ..... ... .... ....... ... ....... ......... ..... .......... ....... ..... ....... ... ....... ... ....... ..... ..... .... . ........ .. ... ..... ......... .. ........ ..... ....... .......... .......... ... ........ .. ... ..... .. ........ ..... .......... .... ... ...... .. .....
WishBone Bus
.. ....... ........ ........ ....... .. ........... ...... .... .. ...... ..... .. ..... .... ........ ... ...... . ... .... .. ......... ........... .... .... ........ .. .... . ..... ....... .... ... ........ .... ............ .. ... ... ....... .. ...... .... ... .... ....... .. ..... ... .... ....... ... ....... ......... ..... .......... ....... ..... ....... ... ....... ... ....... ..... ..... .... . ........ .. ... ..... ......... .. ........ ..... ....... .......... .......... ... ........ .. ... ..... .. ........ ..... .......... .... ... ...... .. .....
Design Under Verification
.. ....... ........ ........ ....... .. ........... ...... .... .. ...... ..... .. ..... .... ........ ... ...... . ... .... .. ......... ........... .... .... ........ .. .... . ..... ....... .... ... ........ .... ............ .. ... ... ....... .. ...... .... ... .... ....... .. ..... ... .... ....... ... ....... ......... ..... .......... ....... ..... ....... ... ....... ... ....... ..... ..... .... . ........ .. ... ..... ......... .. ........ ..... ....... .......... .......... ... ........ .. ... ..... .. ........ ..... .......... .... ... ...... .. .....
OSVVM METHODOLOGY
.. ....... ........ ........ ....... .. ........... ...... .... .. ...... ..... .. ..... .... ........ ... ...... . ... .... .. ......... ........... .... .... ........ .. .... . ..... ....... .... ... ........ .... ............ .. ... ... ....... .. ...... .... ... .... ....... .. ..... ... .... ....... ... ....... ......... ..... .......... ....... ..... ....... ... ....... ... ....... ..... ..... .... . ........ .. ... ..... ......... .. ........ ..... ....... .......... .......... ... ........ .. ... ..... .. ........ ..... .......... .... ... ...... .. .....
OSVVM Testbench Architecture
.. ....... ........ ........ ....... .. ........... ...... .... .. ...... ..... .. ..... .... ........ ... ...... . ... .... .. ......... ........... .... .... ........ .. .... . ..... ....... .... ... ........ .... ............ .. ... ... ....... .. ...... .... ... .... ....... .. ..... ... .... ....... ... ....... ......... ..... .......... ....... ..... ....... ... ....... ... ....... ..... ..... .... . ........ .. ... ..... ......... .. ........ ..... ....... .......... .......... ... ........ .. ... ..... .. ........ ..... .......... .... ... ...... .. .....
{width=8cm}
.. ....... ........ ........ ....... .. ........... ...... .... .. ...... ..... .. ..... .... ........ ... ...... . ... .... .. ......... ........... .... .... ........ .. .... . ..... ....... .... ... ........ .... ............ .. ... ... ....... .. ...... .... ... .... ....... .. ..... ... .... ....... ... ....... ......... ..... .......... ....... ..... ....... ... ....... ... ....... ..... ..... .... . ........ .. ... ..... ......... .. ........ ..... ....... .......... .......... ... ........ .. ... ..... .. ........ ..... .......... .... ... ...... .. .....
package ring_buffer_pkg is
type LinkedList is protected
procedure Push(constant Data : in integer);
impure function Pop return integer;
impure function IsEmpty return boolean;
end protected;
end package ring_buffer_pkg;
package body ring_buffer_pkg is
type LinkedList is protected body
type Item;
type Ptr is access Item;
type Item is record
Data : integer;
NextItem : Ptr;
end record;
variable Root : Ptr;
procedure Push(Data : in integer) is
variable NewItem : Ptr;
variable Node : Ptr;
begin
NewItem := new Item;
NewItem.Data := Data;
if Root = null then
Root := NewItem;
else
Node := Root;
while Node.NextItem /= null loop
Node := Node.NextItem;
end loop;
Node.NextItem := NewItem;
end if;
end;
impure function Pop return integer is
variable Node : Ptr;
variable RetVal : integer;
begin
Node := Root;
Root := Root.NextItem;
RetVal := Node.Data;
deallocate(Node);
return RetVal;
end;
impure function IsEmpty return boolean is
begin
return Root = null;
end;
end protected body;
end package body ring_buffer_pkg;
.. ....... ........ ........ ....... .. ........... ...... .... .. ...... ..... .. ..... .... ........ ... ...... . ... .... .. ......... ........... .... .... ........ .. .... . ..... ....... .... ... ........ .... ............ .. ... ... ....... .. ...... .... ... .... ....... .. ..... ... .... ....... ... ....... ......... ..... .......... ....... ..... ....... ... ....... ... ....... ..... ..... .... . ........ .. ... ..... ......... .. ........ ..... ....... .......... .......... ... ........ .. ... ..... .. ........ ..... .......... .... ... ...... .. .....
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use std.env.finish;
library osvvm;
use osvvm.RandomPkg.all;
use osvvm.CoveragePkg.all;
use work.ring_buffer_pkg.all;
entity ring_buffer_testbench is
end ring_buffer_testbench;
architecture simulation of ring_buffer_testbench is
constant clock_period : time := 10 ns;
constant RAM_WIDTH : natural := 16;
constant RAM_DEPTH : natural := 256;
-- DUT signals
signal clk : std_logic := '1';
signal rst : std_logic := '1';
signal wr_en : std_logic := '0';
signal wr_data : std_logic_vector(RAM_WIDTH - 1 downto 0) := (others => '0');
signal rd_en : std_logic := '0';
signal rd_valid : std_logic;
signal rd_data : std_logic_vector(RAM_WIDTH - 1 downto 0);
signal empty : std_logic;
signal empty_next : std_logic;
signal full : std_logic;
signal full_next : std_logic;
signal fill_count : integer range RAM_DEPTH downto 0;
-- OSVVM variables
shared variable rv : RandomPType;
shared variable bin1 : CovPType;
shared variable bin2 : CovPType;
shared variable bin3 : CovPType;
shared variable bin4 : CovPType;
shared variable bin5 : CovPType;
shared variable bin6 : CovPType;
-- Testbench FIFO that emulates the DUT
shared variable fifo : LinkedList;
-- Testbench FIFO signals
signal fifo_out : integer;
signal fifo_out_valid : std_logic := '0';
begin
dut : entity work.ring_buffer(rtl)
generic map (
RAM_WIDTH => RAM_WIDTH,
RAM_DEPTH => RAM_DEPTH
)
port map (
clk => clk,
rst => rst,
wr_en => wr_en,
wr_data => wr_data,
rd_en => rd_en,
rd_valid => rd_valid,
rd_data => rd_data,
empty => empty,
empty_next => empty_next,
full => full,
full_next => full_next,
fill_count => fill_count
);
clk <= not clk after clock_period/2;
process_sequencer : process
begin
-- Set up coverage bins
bin1.AddBins("Write while empty", ONE_BIN);
bin2.AddBins("Read while full", ONE_BIN);
bin3.AddBins("Read and write while almost empty", ONE_BIN);
bin4.AddBins("Read and write while almost full", ONE_BIN);
bin5.AddBins("Read without write when almost empty", ONE_BIN);
bin6.AddBins("Write without read when almost full", ONE_BIN);
wait until rising_edge(clk);
wait until rising_edge(clk);
rst <= '0';
wait until rising_edge(clk);
loop
wait until rising_edge(clk);
-- Collect coverage data
bin1.ICover(to_integer(wr_en = '1' and empty = '1'));
bin2.ICover(to_integer(rd_en = '1' and full = '1'));
bin3.ICover(to_integer(rd_en = '1' and wr_en = '1' and empty = '0' and empty_next = '1'));
bin4.ICover(to_integer(rd_en = '1' and wr_en = '1' and full = '0' and full_next = '1'));
bin5.ICover(to_integer(rd_en = '1' and wr_en = '0' and empty = '0' and empty_next = '1'));
bin6.ICover(to_integer(rd_en = '0' and wr_en = '1' and full = '0' and full_next = '1'));
-- Stop the test when all coverage goals have been met
exit when
bin1.IsCovered and
bin2.IsCovered and
bin3.IsCovered and
bin4.IsCovered and
bin5.IsCovered and
bin6.IsCovered;
end loop;
report("Coverage goals met");
-- Make sure that the DUT is empty before terminating the test
wr_en <= force '0';
rd_en <= force '1';
loop
wait until rising_edge(clk);
exit when empty = '1';
end loop;
-- Print coverage data
bin1.WriteBin;
bin2.WriteBin;
bin3.WriteBin;
bin4.WriteBin;
bin5.WriteBin;
bin6.WriteBin;
finish;
end process;
-- Generate random input
process_write : process
begin
wr_en <= rv.RandSlv(1)(1) and not rst;
for i in 0 to rv.RandInt(0, 2*RAM_DEPTH) loop
wr_data <= rv.RandSlv(RAM_WIDTH);
wait until rising_edge(clk);
end loop;
end process;
-- Perform random reads
process_read : process
begin
rd_en <= rv.RandSlv(1)(1) and not rst;
for i in 0 to rv.RandInt(0, 2*RAM_DEPTH) loop
wait until rising_edge(clk);
end loop;
end process;
-- Emulate the DUT
process_behavioral_model : process
begin
wait until rising_edge(clk) and rst = '0';
-- Emulate a write
if wr_en = '1' and full = '0' then
fifo.Push(to_integer(unsigned(wr_data)));
report "Push " & integer'image(to_integer(unsigned(wr_data)));
end if;
-- Emulate a read
if rd_en = '1' and empty = '0' then
fifo_out <= fifo.Pop;
fifo_out_valid <= '1';
else
fifo_out_valid <= '0';
end if;
end process;
-- Check that the output from the DUT matches the behavioral model
process_verify : process
begin
wait until rising_edge(clk) and rst = '0';
-- Check that DUT and TB FIFO are reporting empty simultaneously
assert (empty = '1' and fifo.IsEmpty) or (empty = '0' and not fifo.IsEmpty)
report "empty=" & std_logic'image(empty) & " while fifo.IsEmpty=" & boolean'image(fifo.IsEmpty)
severity failure;
-- Check that the valid signals are matching
assert rd_valid = fifo_out_valid
report "rd_valid=" & std_logic'image(rd_valid) & " while fifo_out_valid=" & std_logic'image(fifo_out_valid)
severity failure;
-- Check that the output from the DUT matches the TB FIFO
if rd_valid then
assert fifo_out = to_integer(unsigned(rd_data))
report "rd_data=" & integer'image(to_integer(unsigned(rd_data))) & " while fifo_out=" & integer'image(fifo_out)
severity failure;
report "Pop " & integer'image(fifo_out);
end if;
end process;
end architecture;
.. ....... ........ ........ ....... .. ........... ...... .... .. ...... ..... .. ..... .... ........ ... ...... . ... .... .. ......... ........... .... .... ........ .. .... . ..... ....... .... ... ........ .... ............ .. ... ... ....... .. ...... .... ... .... ....... .. ..... ... .... ....... ... ....... ......... ..... .......... ....... ..... ....... ... ....... ... ....... ..... ..... .... . ........ .. ... ..... ......... .. ........ ..... ....... .......... .......... ... ........ .. ... ..... .. ........ ..... .......... .... ... ...... .. .....
OSVVM Stimulus
.. ....... ........ ........ ....... .. ........... ...... .... .. ...... ..... .. ..... .... ........ ... ...... . ... .... .. ......... ........... .... .... ........ .. .... . ..... ....... .... ... ........ .... ............ .. ... ... ....... .. ...... .... ... .... ....... .. ..... ... .... ....... ... ....... ......... ..... .......... ....... ..... ....... ... ....... ... ....... ..... ..... .... . ........ .. ... ..... ......... .. ........ ..... ....... .......... .......... ... ........ .. ... ..... .. ........ ..... .......... .... ... ...... .. .....
OSVVM Asserts
.. ....... ........ ........ ....... .. ........... ...... .... .. ...... ..... .. ..... .... ........ ... ...... . ... .... .. ......... ........... .... .... ........ .. .... . ..... ....... .... ... ........ .... ............ .. ... ... ....... .. ...... .... ... .... ....... .. ..... ... .... ....... ... ....... ......... ..... .......... ....... ..... ....... ... ....... ... ....... ..... ..... .... . ........ .. ... ..... ......... .. ........ ..... ....... .......... .......... ... ........ .. ... ..... .. ........ ..... .......... .... ... ...... .. .....
Bus Verification
.. ....... ........ ........ ....... .. ........... ...... .... .. ...... ..... .. ..... .... ........ ... ...... . ... .... .. ......... ........... .... .... ........ .. .... . ..... ....... .... ... ........ .... ............ .. ... ... ....... .. ...... .... ... .... ....... .. ..... ... .... ....... ... ....... ......... ..... .......... ....... ..... ....... ... ....... ... ....... ..... ..... .... . ........ .. ... ..... ......... .. ........ ..... ....... .......... .......... ... ........ .. ... ..... .. ........ ..... .......... .... ... ...... .. .....
AMBA4 AXI-Lite Bus
.. ....... ........ ........ ....... .. ........... ...... .... .. ...... ..... .. ..... .... ........ ... ...... . ... .... .. ......... ........... .... .... ........ .. .... . ..... ....... .... ... ........ .... ............ .. ... ... ....... .. ...... .... ... .... ....... .. ..... ... .... ....... ... ....... ......... ..... .......... ....... ..... ....... ... ....... ... ....... ..... ..... .... . ........ .. ... ..... ......... .. ........ ..... ....... .......... .......... ... ........ .. ... ..... .. ........ ..... .......... .... ... ...... .. .....
AMBA3 AHB-Lite Bus
.. ....... ........ ........ ....... .. ........... ...... .... .. ...... ..... .. ..... .... ........ ... ...... . ... .... .. ......... ........... .... .... ........ .. .... . ..... ....... .... ... ........ .... ............ .. ... ... ....... .. ...... .... ... .... ....... .. ..... ... .... ....... ... ....... ......... ..... .......... ....... ..... ....... ... ....... ... ....... ..... ..... .... . ........ .. ... ..... ......... .. ........ ..... ....... .......... .......... ... ........ .. ... ..... .. ........ ..... .......... .... ... ...... .. .....
WishBone Bus
.. ....... ........ ........ ....... .. ........... ...... .... .. ...... ..... .. ..... .... ........ ... ...... . ... .... .. ......... ........... .... .... ........ .. .... . ..... ....... .... ... ........ .... ............ .. ... ... ....... .. ...... .... ... .... ....... .. ..... ... .... ....... ... ....... ......... ..... .......... ....... ..... ....... ... ....... ... ....... ..... ..... .... . ........ .. ... ..... ......... .. ........ ..... ....... .......... .......... ... ........ .. ... ..... .. ........ ..... .......... .... ... ...... .. .....
Design Under Verification
.. ....... ........ ........ ....... .. ........... ...... .... .. ...... ..... .. ..... .... ........ ... ...... . ... .... .. ......... ........... .... .... ........ .. .... . ..... ....... .... ... ........ .... ............ .. ... ... ....... .. ...... .... ... .... ....... .. ..... ... .... ....... ... ....... ......... ..... .......... ....... ..... ....... ... ....... ... ....... ..... ..... .... . ........ .. ... ..... ......... .. ........ ..... ....... .......... .......... ... ........ .. ... ..... .. ........ ..... .......... .... ... ...... .. .....
library ieee;
use ieee.std_logic_1164.all;
entity ring_buffer is
generic (
RAM_WIDTH : natural;
RAM_DEPTH : natural
);
port (
clk : in std_logic;
rst : in std_logic;
-- Write port
wr_en : in std_logic;
wr_data : in std_logic_vector(RAM_WIDTH - 1 downto 0);
-- Read port
rd_en : in std_logic;
rd_valid : out std_logic;
rd_data : out std_logic_vector(RAM_WIDTH - 1 downto 0);
-- Flags
empty : out std_logic;
empty_next : out std_logic;
full : out std_logic;
full_next : out std_logic;
-- The number of elements in the FIFO
fill_count : out integer range RAM_DEPTH - 1 downto 0
);
end ring_buffer;
architecture rtl of ring_buffer is
type ram_type is array (0 to RAM_DEPTH - 1) of std_logic_vector(wr_data'range);
signal ram : ram_type;
subtype index_type is integer range ram_type'range;
signal head : index_type;
signal tail : index_type;
signal empty_i : std_logic;
signal full_i : std_logic;
signal fill_count_i : integer range RAM_DEPTH - 1 downto 0;
begin
-- Copy internal signals to output
empty <= empty_i;
full <= full_i;
fill_count <= fill_count_i;
-- Set the flags
empty_i <= '1' when fill_count_i = 0 else '0';
empty_next <= '1' when fill_count_i <= 1 else '0';
full_i <= '1' when fill_count_i >= RAM_DEPTH - 1 else '0';
full_next <= '1' when fill_count_i >= RAM_DEPTH - 2 else '0';
-- Update the head pointer in write
process_head : process(clk)
begin
if rising_edge(clk) then
if rst = '1' then
head <= 0;
else
if wr_en = '1' and full_i = '0' then
if head = index_type'high then
head <= index_type'low;
else
head <= head + 1;
end if;
end if;
end if;
end if;
end process;
-- Update the tail pointer on read and pulse valid
process_tail : process(clk)
begin
if rising_edge(clk) then
if rst = '1' then
tail <= 0;
rd_valid <= '0';
else
if rd_en = '1' and empty_i = '0' then
if tail = index_type'high then
tail <= index_type'low;
else
tail <= tail + 1;
end if;
rd_valid <= '1';
else
rd_valid <= '0';
end if;
end if;
end if;
end process;
-- Write to and read from the RAM
process_ram : process(clk)
begin
if rising_edge(clk) then
ram(head) <= wr_data;
rd_data <= ram(tail);
end if;
end process;
-- Update the fill count
process_count : process(head, tail)
begin
if head < tail then
fill_count_i <= head - tail + RAM_DEPTH;
else
fill_count_i <= head - tail;
end if;
end process;
end architecture;
.. ....... ........ ........ ....... .. ........... ...... .... .. ...... ..... .. ..... .... ........ ... ...... . ... .... .. ......... ........... .... .... ........ .. .... . ..... ....... .... ... ........ .... ............ .. ... ... ....... .. ...... .... ... .... ....... .. ..... ... .... ....... ... ....... ......... ..... .......... ....... ..... ....... ... ....... ... ....... ..... ..... .... . ........ .. ... ..... ......... .. ........ ..... ....... .......... .......... ... ........ .. ... ..... .. ........ ..... .......... .... ... ...... .. .....
UVM METHODOLOGY
The Universal Verification Methodology (UVM) is a standardized methodology for verifying integrated circuits, particularly in the field of System-on-Chip (SoC) design. UVM is built on SystemVerilog and provides a robust framework for creating reusable and modular verification environments. Below is a detailed explanation of UVM and its components.
Overview
UVM aims to provide a structured and reusable approach to verification, facilitating the development of testbenches that can be easily maintained and adapted to various verification scenarios. Its key features include the ability to create complex verification environments, stimulate designs under test (DUT) with various scenarios, and check the DUT's behavior against expected results.
Typical UVM Testbench Architecture
The typical UVM testbench architecture is composed of several key components, each with a specific role in the verification process. The hierarchy of a UVM testbench is designed to be modular, allowing each component to be developed, tested, and reused independently.
UVM Testbench
...
The UVM testbench is the top-level module in a UVM environment. It instantiates all other components and coordinates the overall verification process. The testbench is responsible for setting up the DUT, initializing the UVM environment, and running the tests.
UVM Test
...
The UVM test is a specific scenario or set of scenarios used to verify the DUT. Each UVM test inherits from the uvm_test
base class and typically configures the environment and sequences to be used. It may override configuration settings, instantiate specific sequences, and control the execution flow.
UVM Environment
...
The UVM environment is a container for the various agents, scoreboards, and other components needed for verification. It typically includes one or more agents, a scoreboard for result checking, and any necessary interfaces. The environment class inherits from uvm_env
.
UVM Scoreboard
...
The UVM scoreboard is responsible for checking the DUT's output against expected results. It collects data from various monitors and compares it to expected values, flagging any discrepancies. The scoreboard is crucial for functional verification, ensuring that the DUT behaves as intended.
UVM Agent
...
A UVM agent is a modular component that encapsulates the functionality required to stimulate and monitor a specific interface of the DUT. It typically includes a sequencer, driver, and monitor. An agent can be active, generating stimuli and driving them onto the interface, or passive, simply monitoring the interface.
UVM Sequencer
...
The UVM sequencer controls the flow of sequences to the driver. It manages the order and timing of transaction generation, ensuring that the correct sequences are sent to the DUT. The sequencer class inherits from uvm_sequencer
.
UVM Sequence
...
A UVM sequence is a series of transactions or operations to be performed on the DUT. Sequences are defined by inheriting from the uvm_sequence
base class and can be composed to create complex stimulus scenarios. Sequences are executed by the sequencer and can be randomized to improve test coverage.
UVM Driver
...
The UVM driver receives sequences from the sequencer and drives them onto the DUT's interface. It converts high-level transactions into pin-level activity, ensuring that the DUT receives the correct stimuli. The driver class inherits from uvm_driver
.
UVM Monitor
...
The UVM monitor observes the DUT's interface, capturing data for analysis by the scoreboard and other components. It is typically passive, meaning it does not influence the DUT's behavior. The monitor class inherits from uvm_monitor
.
UVM Class Library
The UVM class library provides a comprehensive set of base classes and utilities for building verification environments. It includes classes for components (such as the test, environment, agent, sequencer, sequence, driver, and monitor), as well as utilities for configuration, reporting, messaging, and more.
Key classes and utilities in the UVM class library include:
- uvm_component: Base class for all UVM components.
- uvm_test: Base class for tests.
- uvm_env: Base class for environments.
- uvm_agent: Base class for agents.
- uvm_sequencer: Base class for sequencers.
- uvm_sequence: Base class for sequences.
- uvm_driver: Base class for drivers.
- uvm_monitor: Base class for monitors.
- uvm_config_db: Utility for configuration and parameterization.
- uvm_report_server: Utility for reporting and messaging.
- uvm_factory: Utility for component creation and management.
These classes and utilities provide a standardized way to construct verification environments, ensuring consistency and reusability across different projects and teams.
Transaction-Level Modeling (TLM)
Transaction-Level Modeling (TLM) is a high-level approach to modeling the communication between components in a system, focusing on the transactions rather than the lower-level signal details. TLM abstracts the details of the communication, making it easier to develop, understand, and simulate complex systems.
Overview
TLM is widely used in system-level design and verification, providing a higher abstraction level than traditional register-transfer level (RTL) modeling. It allows for faster simulations and easier debugging, as well as better reuse of models. TLM is particularly beneficial in early stages of design for architectural exploration and software development.
TLM, TLM-1, and TLM-2.0
TLM has evolved over time, leading to different versions with varying levels of abstraction and capabilities:
- TLM: The initial concept of transaction-level modeling, focusing on abstracting communication into transactions.
- TLM-1: The first standard version, providing basic mechanisms for transaction-level communication, focusing on the communication itself rather than timing accuracy.
- TLM-2.0: An advanced version that introduces standardized interfaces and protocols, supporting more detailed timing and communication mechanisms. TLM-2.0 is more comprehensive and includes features for interoperability and more accurate modeling of timing and synchronization.
TLM-1 Implementation
Basics
...
TLM-1 provides the foundation for transaction-level modeling. It abstracts communication into transactions, which are data structures representing read or write operations. Components communicate by passing these transactions rather than manipulating signals directly.
Encapsulation and Hierarchy
...
In TLM-1, components are typically encapsulated in a hierarchical manner. This encapsulation helps manage complexity and promotes modularity. Each component can be a master, slave, or intermediary, initiating or responding to transactions.
Analysis Communication
...
Analysis communication in TLM-1 involves observing and analyzing transactions as they pass through the system. Monitors or analysis components can be attached to observe transactions, enabling the collection of statistics, performance analysis, and functional verification without affecting the communication itself.
TLM-2.0 Implementation
TLM-2.0 builds on the concepts introduced in TLM-1, adding more detailed and standardized features for improved modeling accuracy and interoperability.
Generic Payload
...
The generic payload in TLM-2.0 is a standardized transaction data structure that includes fields for address, data, command (read/write), response status, and other attributes. This standardization simplifies communication and promotes reuse across different models and platforms.
Core Interfaces and Ports
...
TLM-2.0 defines core interfaces and ports for communication:
- tlm_fw_transport_if: Forward transport interface for initiating transactions.
- tlm_bw_transport_if: Backward transport interface for receiving responses.
- tlm_initiator_socket: Socket used by initiators to send transactions.
- tlm_target_socket: Socket used by targets to receive transactions.
Blocking Transport
...
Blocking transport in TLM-2.0 involves transactions that complete before control is returned to the caller. This is useful for simple and immediate communication scenarios. The b_transport
method is used for blocking transport, ensuring that a transaction is fully processed before moving on.
Nonblocking Transport
...
Nonblocking transport allows transactions to be initiated without waiting for their completion, enabling more complex and asynchronous communication. The nb_transport_fw
and nb_transport_bw
methods are used for forward and backward nonblocking transport, respectively.
Sockets
...
Sockets in TLM-2.0 facilitate the connection between initiators and targets. They encapsulate the interfaces and provide a standardized way to connect components. Sockets support both blocking and nonblocking transport methods, promoting flexibility and ease of use.
Time
...
TLM-2.0 includes mechanisms for modeling timing and delays, allowing for more accurate simulation of system behavior. Time annotations can be added to transactions to represent communication delays, processing times, and synchronization points.
Use Models
...
TLM-2.0 supports various use models, including:
- Loosely-timed (LT) models: Focus on functionality with approximate timing. Suitable for early software development and high-level architectural exploration.
- Approximately-timed (AT) models: Provide more detailed timing information, suitable for performance analysis and detailed design exploration.
- Timed models: Capture precise timing details for accurate hardware simulation and verification.
In summary, TLM-2.0 provides a rich set of features and standardized mechanisms for high-level system modeling, supporting a range of use cases from early design exploration to detailed performance analysis and verification.
Developing Reusable Verification Components
Creating reusable verification components is crucial for an efficient and effective verification process. This involves building modular, flexible, and highly configurable components that can be reused across different projects and verification environments.
Modeling Data Items for Generation
Inheritance and Constraint Layering
...
Modeling data items involves defining the structure and properties of the transactions that will be used in verification. In UVM, data items are typically modeled as classes that extend from uvm_sequence_item
. Inheritance allows for creating base transaction classes with common fields and methods, which can then be extended to create specific transaction types.
Constraint layering is used to apply constraints to randomize the fields of the data items. Constraints can be layered to apply different sets of constraints based on the context or scenario.
class base_transaction extends uvm_sequence_item;
rand bit [7:0] address;
rand bit [31:0] data;
`uvm_object_utils(base_transaction)
function new(string name = "base_transaction");
super.new(name);
endfunction
// Define constraints here
constraint valid_address { address < 128; }
endclass
class specific_transaction extends base_transaction;
rand bit [3:0] control_flags;
`uvm_object_utils(specific_transaction)
function new(string name = "specific_transaction");
super.new(name);
endfunction
// Additional constraints for specific transaction
constraint control_constraint { control_flags != 4'b0000; }
endclass
Defining Control Fields ("Knobs")
...
Control fields, or "knobs", are used to adjust the behavior of the verification components dynamically. These fields can be configured through the UVM configuration database, enabling flexibility in controlling the verification environment without modifying the code.
class transaction_knobs extends uvm_object;
bit enable_error_injection;
bit [15:0] max_transactions;
`uvm_object_utils(transaction_knobs)
function new(string name = "transaction_knobs");
super.new(name);
endfunction
endclass
Transaction-Level Components
Transaction-level components are responsible for generating, processing, and monitoring transactions. These components include drivers, sequencers, and monitors.
Creating the Driver
The driver is responsible for driving the transactions onto the DUT's interface. It extends from uvm_driver
and implements the run_phase
method to fetch transactions from the sequencer and drive them onto the interface.
class my_driver extends uvm_driver<base_transaction>;
virtual dut_if dut_interface;
`uvm_component_utils(my_driver)
function new(string name, uvm_component parent);
super.new(name, parent);
endfunction
virtual function void build_phase(uvm_phase phase);
super.build_phase(phase);
if (!uvm_config_db#(virtual dut_if)::get(this, "", "dut_interface", dut_interface))
`uvm_fatal("NOVIF", "Virtual interface not found")
endfunction
task run_phase(uvm_phase phase);
base_transaction trans;
forever begin
seq_item_port.get_next_item(trans);
// Drive transaction onto DUT
dut_interface.addr = trans.address;
dut_interface.data = trans.data;
seq_item_port.item_done();
end
endtask
endclass
Creating the Sequencer
The sequencer manages the flow of transactions. It generates or selects transactions to be sent to the driver.
class my_sequencer extends uvm_sequencer<base_transaction>;
`uvm_component_utils(my_sequencer)
function new(string name, uvm_component parent);
super.new(name, parent);
endfunction
endclass
Connecting the Driver and Sequencer
Basic Sequencer and Driver Interaction
...
The driver and sequencer interact through TLM ports and exports. The sequencer generates transactions, which the driver then processes.
Querying for the Randomized Item
...
The sequencer generates randomized items, which the driver fetches and processes.
Fetching Consecutive Randomized Items
...
The driver fetches consecutive transactions from the sequencer, ensuring continuous operation.
Sending Processed Data back to the Sequencer
...
Processed data can be sent back to the sequencer if needed, typically using TLM analysis ports.
Using TLM-Based Drivers
...
TLM-based drivers use TLM interfaces for more abstract communication.
Creating the Monitor
The monitor observes the DUT's interface and collects data for analysis. It extends from uvm_monitor
and typically implements the run_phase
method to capture transactions from the DUT.
class my_monitor extends uvm_monitor;
virtual dut_if dut_interface;
uvm_analysis_port#(base_transaction) ap;
`uvm_component_utils(my_monitor)
function new(string name, uvm_component parent);
super.new(name, parent);
ap = new("ap", this);
endfunction
virtual function void build_phase(uvm_phase phase);
super.build_phase(phase);
if (!uvm_config_db#(virtual dut_if)::get(this, "", "dut_interface", dut_interface))
`uvm_fatal("NOVIF", "Virtual interface not found")
endfunction
task run_phase(uvm_phase phase);
base_transaction trans;
forever begin
// Capture transaction from DUT
trans = base_transaction::type_id::create("trans");
trans.address = dut_interface.addr;
trans.data = dut_interface.data;
ap.write(trans);
end
endtask
endclass
Instantiating Components
Components are instantiated in the testbench, and their connections are configured using the UVM configuration database.
Creating the Agent
Operating Modes
...
An agent can operate in active or passive mode. In active mode, it generates and drives transactions. In passive mode, it only monitors transactions.
Connecting Components
...
The agent instantiates and connects the driver, sequencer, and monitor.
class my_agent extends uvm_agent;
my_driver drv;
my_sequencer seqr;
my_monitor mon;
`uvm_component_utils(my_agent)
function new(string name, uvm_component parent);
super.new(name, parent);
endfunction
virtual function void build_phase(uvm_phase phase);
super.build_phase(phase);
drv = my_driver::type_id::create("drv", this);
seqr = my_sequencer::type_id::create("seqr", this);
mon = my_monitor::type_id::create("mon", this);
endfunction
virtual function void connect_phase(uvm_phase phase);
super.connect_phase(phase);
drv.seq_item_port.connect(seqr.seq_item_export);
endfunction
endclass
Creating the Environment
Environment Class
...
The environment class encapsulates agents and other components, creating a complete verification environment.
class my_env extends uvm_env;
my_agent agent;
`uvm_component_utils(my_env)
function new(string name, uvm_component parent);
super.new(name, parent);
endfunction
virtual function void build_phase(uvm_phase phase);
super.build_phase(phase);
agent = my_agent::type_id::create("agent", this);
endfunction
endclass
Invoking build_phase
...
The build_phase
method is used to instantiate and configure components.
Enabling Scenario Creation
Declaring User-Defined Sequences
...
User-defined sequences extend from uvm_sequence
and define specific transaction scenarios.
Sending Subsequences and Sequence Items
...
Subsequences and sequence items can be sent to the sequencer to create complex scenarios.
Starting a Sequence on a Sequencer
...
Sequences are started on the sequencer using the start
method.
Overriding Sequence Items and Sequences
...
Sequence items and sequences can be overridden to customize the scenarios.
Managing End of Test
Managing the end of the test involves detecting when all transactions are complete and stopping the simulation.
Implementing Checks and Coverage
Implementing Checks and Coverage in Classes
...
Checks and coverage can be implemented in verification components to ensure the DUT behaves as expected and to measure verification progress.
Implementing Checks and Coverage in Interfaces
...
Interfaces can also include checks and coverage points to capture detailed information about the DUT's behavior.
Controlling Checks and Coverage
...
Checks and coverage can be controlled through configuration settings, allowing for flexible and targeted verification efforts.
By following these guidelines, you can develop reusable and robust verification components that can be easily integrated and adapted to different verification environments, improving efficiency and effectiveness in the verification process.
Using Verification Components
Creating a Top-Level Environment
A top-level environment encapsulates all the components needed for verification. This environment includes agents, scoreboards, monitors, and other verification components. It provides a cohesive structure to manage the interactions between these components.
class top_env extends uvm_env;
my_agent agent;
my_scoreboard scoreboard;
`uvm_component_utils(top_env)
function new(string name, uvm_component parent);
super.new(name, parent);
endfunction
virtual function void build_phase(uvm_phase phase);
super.build_phase(phase);
agent = my_agent::type_id::create("agent", this);
scoreboard = my_scoreboard::type_id::create("scoreboard", this);
endfunction
virtual function void connect_phase(uvm_phase phase);
super.connect_phase(phase);
agent.mon.ap.connect(scoreboard.analysis_export);
endfunction
endclass
Instantiating Verification Components
Verification components such as drivers, sequencers, monitors, and agents are instantiated within the top-level environment. These components are configured and connected during the build and connect phases.
Creating Test Classes
Test classes define specific verification scenarios. Each test class inherits from uvm_test
and configures the environment, sequences, and other parameters needed for the test.
class base_test extends uvm_test;
top_env env;
`uvm_component_utils(base_test)
function new(string name, uvm_component parent);
super.new(name, parent);
endfunction
virtual function void build_phase(uvm_phase phase);
super.build_phase(phase);
env = top_env::type_id::create("env", this);
endfunction
virtual function void run_phase(uvm_phase phase);
phase.raise_objection(this);
// Run the test sequences here
phase.drop_objection(this);
endfunction
endclass
Verification Component Configuration
Verification Component Configurable Parameters
...
Configurable parameters allow for dynamic control of verification components. These parameters can be set through the UVM configuration database.
Verification Component Configuration Mechanism
...
Configuration is typically done using uvm_config_db
. Parameters can be set and retrieved using this database, allowing for flexible and reusable configurations.
uvm_resource_db
and uvm_config_db
Choosing between ...
- uvm_resource_db: Suitable for global settings that are rarely changed.
- uvm_config_db: Preferred for flexible, dynamic configurations that may vary between tests.
Using a Configuration Class
...
A configuration class encapsulates all the parameters needed for a component. This class is then used to configure the component during the build phase.
class my_config extends uvm_object;
bit enable_error_injection;
int max_transactions;
`uvm_object_utils(my_config)
function new(string name = "my_config");
super.new(name);
endfunction
endclass
class my_agent extends uvm_agent;
my_config cfg;
function void build_phase(uvm_phase phase);
super.build_phase(phase);
if (!uvm_config_db#(my_config)::get(this, "", "my_config", cfg))
`uvm_fatal("NOCFG", "No configuration found")
endfunction
endclass
Creating and Selecting a User-Defined Test
Creating the Base Test
...
The base test class sets up the environment and provides common functionality for derived test classes.
Creating Tests from a Test-Family Base Class
...
Derived test classes extend the base test and implement specific scenarios.
class my_test extends base_test;
`uvm_component_utils(my_test)
function void run_phase(uvm_phase phase);
super.run_phase(phase);
phase.raise_objection(this);
// Specific test sequence
phase.drop_objection(this);
endfunction
endclass
Test Selection
...
Tests are selected at runtime, typically through command-line arguments or a test management framework.
Creating Meaningful Tests
Constraining Data Items
...
Constraining data items ensures that generated transactions meet the required conditions.
Data Item Definitions
...
Data items are defined using uvm_sequence_item
and constrained using SystemVerilog constraints.
Creating a Test-Specific Frame
...
Test-specific frames define the context and conditions for the test, ensuring meaningful verification scenarios.
Virtual Sequences
Creating a Virtual Sequencer
...
A virtual sequencer coordinates multiple sequencers, allowing for complex, multi-interface tests.
class my_virtual_sequencer extends uvm_sequencer;
my_sequencer seq1;
my_sequencer seq2;
`uvm_component_utils(my_virtual_sequencer)
function new(string name, uvm_component parent);
super.new(name, parent);
endfunction
endclass
Creating a Virtual Sequence
...
A virtual sequence orchestrates other sequences, providing a higher level of control over the verification process.
class my_virtual_sequence extends uvm_sequence;
`uvm_object_utils(my_virtual_sequence)
function new(string name = "my_virtual_sequence");
super.new(name);
endfunction
task body();
my_sequence seq1;
my_sequence seq2;
// Start sequences on different sequencers
fork
seq1.start(p_sequencer.seq1);
seq2.start(p_sequencer.seq2);
join
endtask
endclass
Controlling Other Sequencers
...
The virtual sequencer controls other sequencers by starting and managing their sequences.
Connecting a Virtual Sequencer to Subsequencers
...
Virtual sequencers are connected to subsequencers during the build phase.
Checking for DUT Correctness
Correctness checks ensure the DUT behaves as expected. These checks are implemented in scoreboards and monitors.
Scoreboards
Creating the Scoreboard
...
The scoreboard collects and compares results, ensuring the DUT's output matches expected values.
class my_scoreboard extends uvm_scoreboard;
uvm_analysis_export#(base_transaction) analysis_export;
`uvm_component_utils(my_scoreboard)
function new(string name, uvm_component parent);
super.new(name, parent);
analysis_export = new("analysis_export", this);
endfunction
virtual function void write(base_transaction t);
// Compare the transaction with expected values
endfunction
endclass
uvm_scoreboard
Adding Exports to ...
Exports are added to connect the scoreboard to other components.
Requirements of the TLM Implementation
...
The TLM implementation ensures smooth communication between components, allowing for data exchange and synchronization.
Defining the Action Taken
...
The action taken by the scoreboard involves comparing actual results with expected values and reporting discrepancies.
Adding the Scoreboard to the Environment
...
The scoreboard is instantiated and connected in the environment.
IMPLEMENTING A COVERAGE MODEL
Selecting a Coverage Method
...
Coverage methods can be functional or code-based. Functional coverage captures specific conditions and scenarios, while code coverage measures exercised code paths.
Implementing a Functional Coverage Model
...
Functional coverage models are implemented using SystemVerilog covergroups and coverpoints.
class my_coverage extends uvm_subscriber#(base_transaction);
covergroup cg;
coverpoint trans.address;
coverpoint trans.data;
endgroup
`uvm_component_utils(my_coverage)
function new(string name, uvm_component parent);
super.new(name, parent);
cg = new();
endfunction
virtual function void write(base_transaction t);
cg.sample();
endfunction
endclass
Enabling and Disabling Coverage
...
Coverage can be enabled or disabled using configuration settings, allowing for targeted analysis.
By following these steps, you can effectively use verification components to create robust and reusable verification environments. These practices ensure comprehensive verification of the DUT, leveraging the modularity and flexibility provided by UVM.
Using the Register Layer Classes
The Register Layer in UVM provides a robust framework for modeling and verifying the configuration and state registers of a design. It offers a structured way to define, access, and verify the registers and memories in a device under test (DUT).
Overview
The UVM register layer simplifies the modeling of registers and memories, offering mechanisms for defining the structure, accessing the values, and verifying the correctness of the data. It supports both front-door (via bus transactions) and back-door (direct access) mechanisms for register operations.
Usage Model
Mirroring
...
Mirroring refers to keeping a software model (the register model) synchronized with the actual hardware state of the DUT. This synchronization can be done using front-door accesses (through the DUT's bus interface) or back-door accesses (directly accessing the DUT's internal state).
Memories are not Mirrored
...
Unlike registers, memories are typically not mirrored. This is because memory contents can be large and constantly changing, making it impractical to maintain an exact software copy. Instead, specific memory locations can be accessed and verified as needed.
Access API
The UVM register layer provides a rich API for accessing and manipulating register and memory contents.
read / write
...
These methods are used to perform front-door access to the registers through the bus interface.
reg_model.REG1.write(status, value);
reg_model.REG1.read(status, value);
peek / poke
...
These methods are used for back-door access, directly accessing the register value without going through the bus interface.
reg_model.REG1.peek(value);
reg_model.REG1.poke(value);
get / set
...
These methods are used to get or set the register field values in the register model without actually accessing the hardware.
reg_model.REG1.FIELD1.set(value);
value = reg_model.REG1.FIELD1.get();
randomize
...
This method randomizes the field values of a register according to their constraints.
reg_model.REG1.randomize();
update
...
This method writes the current values from the register model to the hardware using front-door access.
reg_model.REG1.update(status);
mirror
...
This method reads the current values from the hardware into the register model, ensuring synchronization.
reg_model.REG1.mirror(status);
Concurrent Accesses
...
The UVM register layer handles concurrent accesses by serializing them, ensuring data integrity.
Coverage Models
Predefined Coverage Identifiers
...
The register layer provides predefined coverage identifiers for register and field accesses, allowing users to collect coverage data for verification purposes.
Controlling Coverage Model Construction and Sampling
...
Coverage model construction and sampling can be controlled through UVM configuration settings, enabling users to focus on specific areas of interest.
Constructing a Register Model
Field Types
...
Fields are the smallest unit in a register model, representing individual bits or groups of bits with specific attributes like access type (read/write).
Register Types
...
Registers are collections of fields, representing a single register in the hardware. They can have attributes such as address, access type, and reset value.
Register File Types
...
Register files are collections of registers grouped together for organizational purposes.
Memory Types
...
Memories are large storage elements, modeled separately from registers due to their size and access patterns.
Block Types
...
Blocks are top-level containers for register files, registers, and memories, representing an entire addressable block of the DUT.
Packaging a Register Model
...
A register model is packaged by defining all its components (fields, registers, register files, memories, and blocks) and linking them together.
Maximum Data Size
...
The maximum data size for register fields and memories is determined by the specific implementation and limitations of the hardware and software tools used.
Back-door Access
Back-door read/write vs. peek/poke
...
Back-door read/write methods use hierarchical HDL paths to directly access the hardware, while peek/poke methods access the register model.
Hierarchical HDL Paths
...
Back-door access relies on hierarchical HDL paths to directly reference and manipulate hardware states.
VPI-based Back-door Access
...
VPI (Verilog Procedural Interface) provides a standard way to implement back-door access in Verilog-based designs.
User-defined Back-door Access
...
Users can define custom back-door access methods to suit specific needs or hardware configurations.
Back-door Access for Protected Memories
...
Protected memories require special handling to ensure security and data integrity during back-door accesses.
Active Monitoring
...
Active monitoring involves continuously checking the DUT's state to detect and report any discrepancies between the register model and the actual hardware.
Special Registers
Pre-defined Special Registers
...
Certain registers have predefined roles and behaviors, such as status registers or control registers.
Unmapped Registers and Memories
...
Unmapped registers and memories are those that do not have a direct correspondence in the hardware but are included in the model for completeness or simulation purposes.
Aliased Registers
...
Aliased registers share the same address space but serve different purposes based on context or mode of operation.
Unimplemented Registers
...
Unimplemented registers are placeholders for future expansion or optional features not currently present in the hardware.
RO and WO Registers Sharing the Same Address
...
Read-only (RO) and write-only (WO) registers can share the same address if they represent different aspects of the same hardware location.
Integrating a Register Model in a Verification Environment
Integrating a Register Model
Transaction Adapter
...
The transaction adapter translates high-level register operations into low-level bus transactions compatible with the DUT's bus protocol.
Integrating Bus Sequencers
...
Bus sequencers control the sequence of bus transactions, coordinating with the register model to perform reads and writes.
Integrating the Register Model with a Bus Monitor
...
A bus monitor observes bus transactions and updates the register model to reflect changes in the DUT's state, ensuring consistency and correctness.
Randomizing Field Values
Randomizing field values allows for extensive testing of different register states and transitions, uncovering edge cases and potential issues.
reg_model.REG1.randomize();
Pre-defined Sequences
Pre-defined sequences provide common register access patterns and scenarios, facilitating efficient and thorough verification.
class my_reg_sequence extends uvm_sequence;
`uvm_object_utils(my_reg_sequence)
function new(string name = "my_reg_sequence");
super.new(name);
endfunction
task body();
// Define sequence of register operations
endtask
endclass
By leveraging the capabilities of the UVM register layer, verification engineers can create comprehensive, flexible, and reusable register models that enhance the effectiveness and efficiency of the verification process.
Advanced Topics
uvm_component
Base Class
The uvm_component
base class is a fundamental building block in UVM, providing a framework for building modular, reusable verification components. It serves as the base class for all hierarchical components in a UVM testbench.
Key features of uvm_component
include:
- Phases: UVM components participate in predefined simulation phases such as
build_phase
,connect_phase
,run_phase
, etc. - Factory Registration: Allows components to be created dynamically using the UVM factory.
- Configuration Database: Enables flexible configuration of component properties.
Example:
class my_component extends uvm_component;
`uvm_component_utils(my_component)
function new(string name, uvm_component parent);
super.new(name, parent);
endfunction
virtual function void build_phase(uvm_phase phase);
super.build_phase(phase);
// Component build logic
endfunction
virtual function void run_phase(uvm_phase phase);
phase.raise_objection(this);
// Component run logic
phase.drop_objection(this);
endfunction
endclass
Built-In Factory and Overrides
About the Factory
...
The UVM factory is a mechanism for creating objects and components dynamically at runtime. It supports object-oriented principles such as polymorphism and abstraction, enabling flexibility and reusability.
Factory Registration
...
To use the factory, components and objects must be registered using macros such as uvm_component_utils
and uvm_object_utils
.
class my_component extends uvm_component;
`uvm_component_utils(my_component)
// ...
endclass
Component Overrides
...
Overrides allow one component or object type to be replaced with another at runtime, facilitating easier configuration changes and extending testbenches without modifying the original code.
uvm_factory::set_type_override_by_type(original_type::get_type(), override_type::get_type());
Callbacks
Use Model
...
Callbacks are a mechanism to add custom behavior to UVM components without modifying their source code. They enable a flexible way to extend and customize components.
Example
...
class my_callback extends uvm_callback;
`uvm_object_utils(my_callback)
function new(string name = "my_callback");
super.new(name);
endfunction
virtual function void post_write(uvm_reg reg, uvm_reg_data_t data);
// Custom behavior after a register write
endfunction
endclass
class my_component extends uvm_component;
`uvm_component_utils(my_component)
my_callback cb;
function new(string name, uvm_component parent);
super.new(name, parent);
endfunction
virtual function void build_phase(uvm_phase phase);
super.build_phase(phase);
cb = my_callback::type_id::create("cb");
uvm_reg::get().add_callback(cb);
endfunction
endclass
Sequence Library
The UVM sequence library provides a framework for creating, managing, and executing sequences. It allows for defining complex transaction flows and reuse across different tests and environments.
Advanced Sequence Control
Implementing Complex Scenarios
...
Complex scenarios can be implemented by composing sequences from simpler sequences, controlling the order, timing, and conditions of execution.
Protocol Layering
...
Protocol layering involves creating sequences that operate at different levels of abstraction, enabling a layered approach to verification.
Generating the Item or Sequence in Advance
...
Sequences can pre-generate items before sending them to the sequencer, allowing for more complex pre-processing or timing control.
Executing Sequences and Items on Other Sequencers
...
Sequences can target different sequencers, enabling coordination between multiple protocol layers or functional units.
task body();
my_seq1.start(p_sequencer);
my_seq2.start(other_sequencer);
endtask
Command Line Interface (CLI)
Introduction
...
The UVM CLI allows users to pass arguments to the simulation, controlling various aspects of the verification environment.
Getting Started
...
To use the CLI, UVM provides built-in macros and functions to parse and handle command-line arguments.
UVM-aware Command Line Processing
...
UVM-aware command-line processing involves using the UVM configuration database and factory to set up the environment based on CLI arguments.
if ($test$plusargs("enable_feature")) begin
uvm_config_db#(bit)::set(null, "uvm_test_top", "enable_feature", 1);
end
Macros in UVM
UVM provides a variety of macros to simplify the creation and management of verification components. Some commonly used macros include:
uvm_component_utils
: Registers a component with the UVM factory.uvm_object_utils
: Registers an object with the UVM factory.uvm_info
,uvm_warning
,uvm_error
,uvm_fatal
: Logging and messaging macros.
Example:
`uvm_info("MY_TAG", "This is an informational message", UVM_LOW)
`uvm_warning("MY_TAG", "This is a warning message")
`uvm_error("MY_TAG", "This is an error message")
`uvm_fatal("MY_TAG", "This is a fatal message")
By mastering these advanced topics, verification engineers can create highly flexible, reusable, and robust verification environments, leveraging the full power of UVM.
UBUS Verification Component Example
UBus Example
The UBus example demonstrates a complete UVM testbench for verifying a simple bus protocol called UBus. This example showcases the architecture, components, and interactions necessary for verifying a bus protocol.
UBus Example ARCHITECTURE
The UBus example architecture consists of several components that work together to verify the UBus protocol. These components include:
- UBus Top Module
- Test
- Testbench Environment
- UBus Environment
- UBus Master Agent
- UBus Master Sequencer
- UBus Driver
- UBus Agent Monitor
- UBus Bus Monitor
- UBus Interface
UBus Top Module
The top module instantiates the DUT and connects it to the UVM testbench components. It provides the necessary signals and interfaces for the UBus protocol.
module ubus_top;
// Clock and reset signals
reg clk;
reg reset;
// UBus signals
wire [31:0] addr;
wire [31:0] data;
wire [3:0] control;
wire ready;
wire valid;
// Instantiate DUT
ubus dut (
.clk(clk),
.reset(reset),
.addr(addr),
.data(data),
.control(control),
.ready(ready),
.valid(valid)
);
// Instantiate UVM testbench
initial begin
run_test();
end
endmodule
Test
A UVM test sets up the environment and specifies the sequences to be executed. It configures the UBus environment and starts the verification process.
class ubus_test extends uvm_test;
`uvm_component_utils(ubus_test)
ubus_env env;
function new(string name, uvm_component parent);
super.new(name, parent);
endfunction
virtual function void build_phase(uvm_phase phase);
super.build_phase(phase);
env = ubus_env::type_id::create("env", this);
endfunction
virtual task run_phase(uvm_phase phase);
phase.raise_objection(this);
// Start the sequence
ubus_master_seq seq;
seq = ubus_master_seq::type_id::create("seq");
seq.start(env.masters[0].sequencer);
phase.drop_objection(this);
endtask
endclass
TestBENCH ENVIRONMENT
The testbench environment instantiates and connects all the necessary components for verifying the UBus protocol. It includes agents, monitors, and scoreboards.
class ubus_env extends uvm_env;
`uvm_component_utils(ubus_env)
ubus_master_agent masters[NUM_MASTERS];
ubus_monitor monitor;
function new(string name, uvm_component parent);
super.new(name, parent);
endfunction
virtual function void build_phase(uvm_phase phase);
super.build_phase(phase);
for (int i = 0; i < NUM_MASTERS; i++) begin
masters[i] = ubus_master_agent::type_id::create($sformatf("master%d", i), this);
end
monitor = ubus_monitor::type_id::create("monitor", this);
endfunction
endclass
UBus Environment
The UBus environment is a specialized environment for the UBus protocol, integrating specific agents and monitors required for UBus verification.
class ubus_env extends uvm_env;
`uvm_component_utils(ubus_env)
ubus_master_agent master_agent;
ubus_monitor bus_monitor;
function new(string name, uvm_component parent);
super.new(name, parent);
endfunction
virtual function void build_phase(uvm_phase phase);
super.build_phase(phase);
master_agent = ubus_master_agent::type_id::create("master_agent", this);
bus_monitor = ubus_monitor::type_id::create("bus_monitor", this);
endfunction
virtual function void connect_phase(uvm_phase phase);
super.connect_phase(phase);
master_agent.monitor.ap.connect(bus_monitor.analysis_export);
endfunction
endclass
UBus Master Agent
The UBus master agent contains the sequencer, driver, and monitor components necessary for generating and monitoring bus transactions from the master perspective.
class ubus_master_agent extends uvm_agent;
`uvm_component_utils(ubus_master_agent)
ubus_master_sequencer sequencer;
ubus_driver driver;
ubus_monitor monitor;
function new(string name, uvm_component parent);
super.new(name, parent);
endfunction
virtual function void build_phase(uvm_phase phase);
super.build_phase(phase);
sequencer = ubus_master_sequencer::type_id::create("sequencer", this);
driver = ubus_driver::type_id::create("driver", this);
monitor = ubus_monitor::type_id::create("monitor", this);
endfunction
virtual function void connect_phase(uvm_phase phase);
super.connect_phase(phase);
driver.seq_item_port.connect(sequencer.seq_item_export);
endfunction
endclass
UBus Master Sequencer
The UBus master sequencer is responsible for managing sequences and providing transactions to the driver.
class ubus_master_sequencer extends uvm_sequencer #(ubus_transaction);
`uvm_component_utils(ubus_master_sequencer)
function new(string name, uvm_component parent);
super.new(name, parent);
endfunction
endclass
UBus Driver
The UBus driver converts sequence items into pin-level activity on the bus interface.
class ubus_driver extends uvm_driver #(ubus_transaction);
`uvm_component_utils(ubus_driver)
virtual function void build_phase(uvm_phase phase);
super.build_phase(phase);
// Driver-specific build logic
endfunction
virtual task run_phase(uvm_phase phase);
forever begin
ubus_transaction tr;
seq_item_port.get_next_item(tr);
// Drive the transaction on the bus
seq_item_port.item_done();
end
endtask
endclass
UBus Agent Monitor
The UBus agent monitor observes bus transactions and converts them into analysis transactions for further processing.
class ubus_monitor extends uvm_monitor;
`uvm_component_utils(ubus_monitor)
uvm_analysis_port #(ubus_transaction) ap;
function new(string name, uvm_component parent);
super.new(name, parent);
ap = new("ap", this);
endfunction
virtual task run_phase(uvm_phase phase);
// Monitor logic
endtask
endclass
UBus Bus Monitor
Collecting Transfers from the Bus
...
The bus monitor collects transactions from the bus and converts them into analysis transactions.
Number of Transfers
...
The monitor tracks the number of transfers and other relevant statistics.
Notifiers Emitted by the UBus Bus Monitor
...
The monitor can emit notifications for specific events, such as errors or protocol violations.
Checks and Coverage
...
The monitor performs protocol checks and collects coverage information, ensuring comprehensive verification of the bus protocol.
UBus Interface
The UBus interface defines the signals and structure of the UBus protocol.
interface ubus_if(input bit clk);
logic [31:0] addr;
logic [31:0] data;
logic [3:0] control;
logic ready;
logic valid;
// Clocking block for synchronous signals
clocking cb @(posedge clk);
output addr;
output data;
output control;
input ready;
output valid;
endclocking
endinterface
This example provides a comprehensive overview of how to set up and utilize a UVM testbench for the UBus protocol, highlighting the key components and their interactions.
UBUS Specification
Introduction
Motivation
...
The UBus (Universal Bus) protocol is designed to provide a flexible and efficient means of communication between different components in a system. It supports various types of data transfers and can be extended to include optional pipelining for improved performance.
Bus Overview
...
UBus is a synchronous bus protocol that includes arbitration, address, and data phases. It supports multiple masters and slaves, ensuring fair access to shared resources through an arbitration mechanism.
Bus Description
Bus Signals
...
UBus consists of several signals that manage data transfer, address selection, and control functions:
clk
: The clock signal driving the synchronous operation of the bus.reset
: Resets the bus and all connected devices.addr[31:0]
: The 32-bit address bus.data[31:0]
: The 32-bit data bus.control[3:0]
: Control signals for various bus operations.ready
: Indicates the slave's readiness to accept or provide data.valid
: Indicates the master's validity of the address or data on the bus.
Clocking
...
UBus is a synchronous protocol driven by a single clock signal. All bus transactions occur on the rising edge of the clock.
Reset
...
The reset
signal is used to initialize the bus and all connected devices to a known state. It is an active-high signal.
Arbitration Phase
The arbitration phase determines which master gains control of the bus. Each master competes for bus access, and a centralized arbiter grants access based on a predefined policy, such as round-robin or priority-based.
Address Phase
During the address phase, the master places the address of the target slave on the address bus.
NOP Cycle
...
A No Operation (NOP) cycle occurs when no master is driving the bus, and all signals remain in their idle state.
Normal Address Phase
...
In a normal address phase, the master asserts the address on the bus and sets the control signals to indicate the type of operation (read/write).
Data Phase
The data phase follows the address phase and involves the actual data transfer between the master and the slave.
Write Transfer
...
In a write transfer, the master places the data on the data bus, and the slave latches the data when the ready
signal is asserted.
Error during Write Transfer
...
If an error occurs during a write transfer, the slave can assert an error signal to indicate the failure.
Read Transfer
...
In a read transfer, the master places the address on the address bus, and the slave returns the data on the data bus when the ready
signal is asserted.
Error during Read Transfer
...
If an error occurs during a read transfer, the slave can assert an error signal to indicate the failure.
How Data is Driven
Data is driven on the bus by the master during write operations and by the slave during read operations. The valid
signal indicates that the data on the bus is valid and can be latched by the receiving device.
Optional Pipelining Scheme
Pipelining improves bus performance by overlapping the arbitration, address, and data phases of multiple transactions.
Pipelined Arbitration Phase
...
In the pipelined arbitration phase, the next master to gain control of the bus is determined while the current data transfer is still in progress.
Pipelined Address Phase
...
The pipelined address phase allows the next address to be placed on the bus before the current data transfer is completed.
Pipelined Data Phase
...
In the pipelined data phase, data transfers for different transactions overlap, with each phase (arbitration, address, data) occurring simultaneously for different transactions.
Example Timing Diagrams
Below are example timing diagrams illustrating different phases and operations in the UBus protocol.
This document outlines the UBus protocol, its phases, signal descriptions, and example timing diagrams, providing a comprehensive guide for implementing and verifying UBus in a hardware design.