Files
lt16lab/soc/lib/wb_tp.vhd
2017-06-28 07:42:58 -05:00

1251 lines
42 KiB
VHDL

-- See the file "LICENSE" for the full license governing this code. --
library ieee;
use ieee.STD_LOGIC_1164.ALL;
use ieee.numeric_std.all;
use ieee.math_real.all;
use ieee.std_logic_textio.all;
library std;
use std.standard.all;
use std.textio.all;
library work;
use work.wishbone.all;
use work.config.all;
use work.txt_util.all;
use work.lt16x32_internal.all;
use work.lt16x32_global.all;
-- Whishbone Testing Package
package wb_tp is
constant READY: std_logic := '1'; --ready signal from mem which will be converted to msti.ack
constant NREADY: std_logic := '0';
type access_type is (NO_ACC, RD_ACC, WR_ACC, SIM_ACC);
---------------------------------------------------------------
--
-- Prototype: Function
--
---------------------------------------------------------------
function slvi_chk_quiet(
signal slvi_vector : wb_slv_in_vector;
constant ScrnOut : boolean := false;
constant InstancePath: string := "slvi_chk_quiet "
) return boolean;
function msti_chk_quiet(
signal msti_vector : wb_mst_in_vector;
constant ScrnOut : boolean := false;
constant InstancePath: string := "msti_chk_quiet "
) return boolean;
function msto_chk_quiet(
signal msto_vector : wb_mst_out_vector;
constant ScrnOut : boolean := false;
constant InstancePath: string := "msto_chk_quiet "
) return boolean ;
function core2wbmo_chk(
signal wbadr : std_logic_vector(31 downto 0);
signal wbsz : std_logic_vector(1 downto 0);
signal wbwrdat : std_logic_vector(31 downto 0);
signal msto : wb_mst_out_type;
constant we : access_type := NO_ACC;
constant ScrnOut : boolean := false;
constant InstancePath: string := "core2wbmo_chk "
) return boolean ;
function slvi_chk_all(
signal slvo : wb_slv_out_vector; -- for address map check
signal msto : wb_mst_out_vector;
signal slvi : wb_slv_in_vector;
constant mst_mask_vector : std_logic_vector(0 to NWBMST-1) := b"0000";
constant ScrnOut : boolean := false;
constant InstancePath : string := "slvi_chk_all "
) return boolean;
function msti_chk_all (
signal msti : wb_mst_in_vector;
signal msto : wb_mst_out_vector;
signal slvo : wb_slv_out_vector; -- response from selected slave (if no addr map, no slave never been selected !!)
constant mst_mask_vector : std_logic_vector(0 to NWBMST-1) := b"0000";
constant ScrnOut : boolean := false;
constant InstancePath : string := "msti_chk_all "
) return boolean;
function wbmi2core_chk(
signal wb2core : dmem_core;
constant we : access_type := NO_ACC;
signal mo_sel : std_logic_vector(WB_SEL_WIDTH-1 downto 0);
signal mi_ack : std_logic;
signal resp_rddat : std_logic_vector(memory_width - 1 downto 0);
constant ScrnOut : boolean := false;
constant InstancePath: string := "wbmi2core_chk "
) return boolean;
function wb2mem_chk(
signal wb2mem : core_dmem;
signal slvi : wb_slv_in_type;
constant we : access_type := NO_ACC;
constant ScrnOut : boolean := false;
constant InstancePath: string := "wb2mem_chk "
) return boolean;
function gmst_idx_fn (
signal msto : wb_mst_out_vector;
constant mst_mask_vector : std_logic_vector(0 to NWBMST-1) := b"0000";
constant ScrnOut : boolean := false;
constant InstancePath : string := "gmst_idx_fn "
) return integer ;
function wbszconv_chk(
signal size : in std_logic_vector(1 downto 0);
constant ScrnOut : boolean := false;
constant InstancePath: string := "wbszconv_chk"
) return boolean;
---------------------------------------------------------------
--
-- Prototype: Procedure
--
---------------------------------------------------------------
procedure gencore2mem_req (
signal core2dmem :out core_dmem;
--
constant req_acc :in access_type := NO_ACC;
constant rd_adr :in std_logic_vector(memory_width - 1 downto 0) := (others=>'0');
constant rd_sz :in std_logic_vector(1 downto 0) := "00";
--
constant wr_adr :in std_logic_vector(memory_width - 1 downto 0):= (others=>'0');
constant wr_sz :in std_logic_vector(1 downto 0):= "00";
constant wr_dat :in std_logic_vector(memory_width - 1 downto 0):= (others=>'-');
--
constant ScrnOut :in boolean := false;
constant InstancePath :in string := "gencore2mem_req "
);
--
procedure genwb2core (
signal msti :out wb_mst_in_type;
--
constant req_acc :in access_type := NO_ACC;
constant rd_sz :in std_logic_vector(1 downto 0) := "00";
constant wb_sel :in std_logic_vector(WB_SEL_WIDTH-1 downto 0);
--
constant read_data :in std_logic_vector(memory_width - 1 downto 0);
constant ready :in std_logic := '0';
constant ScrnOut :in boolean := false;
constant InstancePath :in string := "genwb2core"
);
--
procedure genmst_req (
signal mst_out :out wb_mst_out_type;
constant req_idx :in integer := 0;
constant we :in std_logic;
constant adr :in std_logic_vector(WB_ADR_WIDTH-1 downto 0);
constant dat :in std_logic_vector(WB_PORT_SIZE-1 downto 0);
constant sel :in std_logic_vector(WB_SEL_WIDTH-1 downto 0);
constant ScrnOut :in boolean := false;
constant InstancePath :in string := "genmst_req "
);
--
procedure list_all_mst_req (
signal msto : in wb_mst_out_vector;
constant mst_mask_vector : std_logic_vector(0 to NWBMST-1) := b"0000";
constant ScrnOut : boolean := false;
constant InstancePath : string := "list_all_mst_req "
);
procedure generate_sync_wb_single_write(
signal msto : out wb_mst_out_type;
signal slvo : in wb_slv_out_type;
signal clk : in std_logic;
signal writedata : std_logic_vector(WB_PORT_SIZE-1 downto 0);
constant SIZE : std_logic_vector(WB_ADR_BOUND-1 downto 0) := "10";
constant ADR_OFFSET : integer := 0 -- Offset added to the access address
);
procedure generate_sync_wb_burst_write(
signal msto : out wb_mst_out_type;
signal slvo : in wb_slv_out_type;
signal clk : in std_logic;
signal writedata : std_logic_vector(WB_PORT_SIZE-1 downto 0);
constant NUMBURSTS : positive := 4;
constant SIZE : std_logic_vector(WB_ADR_BOUND-1 downto 0) := "10";
constant ADR_OFFSET : integer := 0 -- Offset added to the access address
);
procedure generate_sync_wb_single_read(
signal msto : out wb_mst_out_type; -- Slave input
signal slvo : in wb_slv_out_type; -- Slave output
signal clk : in std_logic;
signal readdata : out std_logic_vector(WB_PORT_SIZE -1 downto 0);
constant ADR_OFFSET : integer := 0; -- Offset added to the access address
constant SIZE : std_logic_vector(WB_ADR_BOUND-1 downto 0) := "10"
);
procedure generate_sync_wb_burst_read(
signal msto : out wb_mst_out_type; -- Slave input
signal slvo : in wb_slv_out_type; -- Slave output
signal clk : in std_logic;
signal readdata : out std_logic_vector(WB_PORT_SIZE -1 downto 0);
constant NUMBURSTS : positive := 4;
constant ADR_OFFSET : integer := 0; -- Offset added to the access address
constant SIZE : std_logic_vector(WB_ADR_BOUND-1 downto 0) := "10"
);
end wb_tp;
package body wb_tp is
---------------------------------------------------------------
-- Function: slvi_chk_quiet(slvi_vector)
--
-- Check if there is any request (cyc) to any slave
---------------------------------------------------------------
function slvi_chk_quiet(
signal slvi_vector : wb_slv_in_vector;
constant ScrnOut : boolean := false;
constant InstancePath: string := "slvi_chk_quiet "
) return boolean is
variable L: Line;
begin
for i in 0 to NWBSLV-1 loop
if slvi_vector(i).cyc /= '0' then
if ScrnOut then
write(L, Now, Right, 15);
write(L, " : " & InstancePath);
write(L, String'("E00: slv(" & integer'image(i) & ") should not get any request !!!"));
writeline(output, L);
end if;
return false;
end if;
end loop;
return true;
end function;
---------------------------------------------------------------
-- Function: msti_chk_quiet(msti_vector)
--
-- Check if there is any request (ack) to any master
---------------------------------------------------------------
function msti_chk_quiet(
signal msti_vector : wb_mst_in_vector;
constant ScrnOut : boolean := false;
constant InstancePath: string := "msti_chk_quiet "
) return boolean is
variable L: Line;
begin
for i in 0 to NWBMST-1 loop
if msti_vector(i).ack /= '0' then
if ScrnOut then
write(L, Now, Right, 15);
write(L, " : " & InstancePath);
write(L, String'("E00: mst(" & integer'image(i) & ") should not get any ack !!!"));
writeline(output, L);
end if;
return false;
end if;
end loop;
return true;
end function;
---------------------------------------------------------------
-- Function: msto_chk_quiet(mst_mask_vector)
--
-- check if there is any master request (no need to assert error as it will be handle in fn caller)
-- Any master that is disable, wb_intercon will not assert the request (cyc) for that master
-- true = wb_intercon will consider that master as quiet as it either is inactive or sends no request (cyc= 0)
---------------------------------------------------------------
function msto_chk_quiet(
signal msto_vector : wb_mst_out_vector;
constant ScrnOut : boolean := false;
constant InstancePath: string := "msto_chk_quiet "
) return boolean is
variable L: Line;
begin
for i in 0 to NWBMST-1 loop
if msto_vector(i).cyc = '1' then
if ScrnOut then
write(L, Now, Right, 15);
write(L, " : " & InstancePath);
write(L, String'("E00: mst(" & integer'image(i) & ") should not send any request!!!"));
writeline(output, L);
end if;
return false;
end if;
end loop;
return true;
end function;
---------------------------------------------------------------
-- Function: core2wbmo_chk(wbadr, wbsz, wb_wrdat, msto, ACC)
-- This function checks control signals (stb, cyc, we) of core-to-wb conversion for single master(core)
-- Esp made for module "core2wb.vhd"
--
-- SIM_ACC handles same as WR_ACC
---------------------------------------------------------------
function core2wbmo_chk(
signal wbadr : std_logic_vector(31 downto 0);
signal wbsz : std_logic_vector(1 downto 0);
signal wbwrdat : std_logic_vector(31 downto 0);
signal msto : wb_mst_out_type;
constant we : access_type := NO_ACC;
constant ScrnOut : boolean := false;
constant InstancePath: string := "core2wbmo_chk "
) return boolean is
variable L: Line;
begin
if we = RD_ACC then -- read
if msto.stb = '1' and msto.cyc = '1' and msto.we = '0' and
msto.adr = wbadr(memory_width - 1 downto WB_ADR_BOUND) and
msto.sel = gen_select(wbadr(1 downto 0), wbsz)
then
return true;
else
if ScrnOut then
write(L, Now, Right, 15);
write(L, " : " & InstancePath);
write(L, String'("E00: Read req - "));
if not(msto.stb = '1' and msto.cyc = '1' and msto.we = '0') then
write(L, String'("(msto.stb, msto.cyc, msto.we) should be (1, 1, 0) "));
end if;
if (msto.adr /= wbadr(memory_width - 1 downto WB_ADR_BOUND)) then
write(L, String'("Mismatch addr: (msto.adr, wbadr) = (" &
hstr(msto.adr) & ", " &
hstr(wbadr(memory_width - 1 downto WB_ADR_BOUND)) & ") "));
end if;
if (msto.sel /= gen_select(wbadr(1 downto 0), wbsz)) then
write(L, String'("Mismatch sel: (msto.sel, wbadr(1:0)) = (" &
str(msto.sel) & ", " &
str(gen_select(wbadr(1 downto 0), wbsz)) & ")"));
end if;
writeline(output, L);
end if;
end if;
elsif we = WR_ACC or we = SIM_ACC then -- write/sim
if msto.stb = '1' and msto.cyc = '1' and msto.we = '1' and
msto.adr = wbadr(memory_width - 1 downto WB_ADR_BOUND) and
msto.sel = gen_select(wbadr(1 downto 0), wbsz) and
msto.dat = enc_wb_dat(wbadr(1 downto 0), wbsz, wbwrdat) -- optional since mainly check from sel signal
then
return true;
else
if ScrnOut then
write(L, Now, Right, 15);
write(L, " : " & InstancePath);
if we = WR_ACC then
write(L, String'("E01: Write req - "));
else
write(L, String'("E02: Simultaneous req - "));
end if;
if not(msto.stb = '1' and msto.cyc = '1' and msto.we = '1') then
write(L, String'("(msto.stb, msto.cyc, msto.we) should be (1, 1, 1) "));
end if;
if (msto.adr /= wbadr(memory_width - 1 downto WB_ADR_BOUND)) then
write(L, String'("Mismatch addr: (msto.adr, wbadr) = (" &
hstr(msto.adr) & ", " &
hstr(wbadr(memory_width - 1 downto WB_ADR_BOUND)) & ") "));
end if;
if (msto.sel /= gen_select(wbadr(1 downto 0), wbsz)) then
write(L, String'("Mismatch sel: (msto.sel, wbadr(1:0)) = (" &
str(msto.sel) & ", " &
str(gen_select(wbadr(1 downto 0), wbsz)) & ") "));
end if;
if (msto.dat /= enc_wb_dat(wbadr(1 downto 0), wbsz, wbwrdat)) then
write(L, String'("Mismatch data: (msto.dat, wb_wrdat) = (" &
hstr(msto.dat) & ", " &
hstr(enc_wb_dat(wbadr(1 downto 0), wbsz, wbwrdat)) & ")"));
end if;
writeline(output, L);
end if;
end if;
else
if msto.stb = '0' and msto.cyc = '0' and msto.we = '0' then
return true;
else
if ScrnOut then
write(L, Now, Right, 15);
write(L, " : " & InstancePath);
write(L, String'("E03: No request - (msto.stb, msto.cyc, msto.we) should be (0, 0, 0)"));
writeline(output, L);
end if;
end if;
end if;
return false;
end function;
---------------------------------------------------------------
-- Function: slvi_chk_all(slvo_vector, msto_vector, slvi_vector, mst_mask_vector, opt:instancepath, opt:scrnout)
--
-- slv_in check (out from wb_intercon)
-- This function checks if there is only selected slave from granted master gets the request signal (adr map) (cyc = 1)
-- Other slaves whose address is not mapped then should receive nothing (cyc = 0)
-- slv exist check by slvo(i).wbcfg(31 downto 24) must be x"FF" which will be called by wb_membar in order to reformat the mask addr of the slave
---------------------------------------------------------------
function slvi_chk_all(
signal slvo : wb_slv_out_vector; -- for address map check
signal msto : wb_mst_out_vector;
signal slvi : wb_slv_in_vector;
constant mst_mask_vector : std_logic_vector(0 to NWBMST-1) := b"0000";
constant ScrnOut : boolean := false;
constant InstancePath : string := "slvi_chk_all "
) return boolean is
variable madr, sadr : std_logic_vector(31 downto 0) := (others=>'0'); -- for display purpose only
variable gmst_idx : integer range 0 to NWBMST-1;
variable ssel_idx : integer range 0 to NWBSLV-1;
variable slv_found : boolean := false;
variable L : Line;
begin
if msto_chk_quiet(msto) = true then -- No request from all master, No need to continue check slvi
if slvi_chk_quiet(slvi) = false then
if ScrnOut then
write(L, Now, Right, 15);
write(L, " : " & InstancePath);
write(L, String'("E00: No request from any master"));
writeline(output, L);
end if;
return false;
end if;
else
gmst_idx := gmst_idx_fn(msto, mst_mask_vector);
madr := msto(gmst_idx).adr & "00";
-- compare, search for selected slave
for i in 0 to NWBSLV-1 loop
sadr := slvo(i).wbcfg(63 downto 34) & "00" ;
if ScrnOut then
write(L, Now, Right, 15);
write(L, " : " & InstancePath);
write(L, String'(
"[addr_cmp] slv(" & integer'image(i) &
") with its address: " & hstr(sadr) &
" mst(" & integer'image(gmst_idx) &
") with its address: " & hstr(madr)));
writeline(output, L);
end if;
if (slvadrmap(slvo(i).wbcfg, msto(gmst_idx).adr) = true) and slvo(i).wbcfg(31 downto 24) = x"FF" then
slv_found := true;
ssel_idx := i;
end if;
end loop;
-- end compare
if (slv_found = true) then
if (slvi(ssel_idx).cyc /= '1') then
if ScrnOut then
write(L, Now, Right, 15);
write(L, " : " & InstancePath);
write(L, String'("E01: No request from master(" & integer'image(gmst_idx) &
") for slv(" & integer'image(ssel_idx) & ")"));
writeline(output, L);
end if;
return false;
end if;
else
if (slvi(ssel_idx).cyc /= '0') then
if ScrnOut then
write(L, Now, Right, 15);
write(L, " : " & InstancePath);
write(L, String'("E02: request address " & hstr(madr) & " not map with any slave, there should be no request signal " &
"from the granted master (" & integer'image(gmst_idx) & ")"));
writeline(output, L);
end if;
return false;
end if;
end if;
end if;
return true;
end function;
---------------------------------------------------------------
-- Function: msti_chk_all(msti_vector, msto_vector, slvo_vector, mst_mask_vector)
--
-- Check msti
-- This function check if there is only granted master get the ack from selected slave (ack = 1)
-- Other master should not receive asserted ack signal from all slave (ack = 0)
-- slv exist check by slvo(i).wbcfg(31 downto 24) must be x"FF" which will be called by wb_membar in order to reformat the mask addr of the slave
---------------------------------------------------------------
function msti_chk_all (
signal msti : wb_mst_in_vector;
signal msto : wb_mst_out_vector;
signal slvo : wb_slv_out_vector; -- response from selected slave (if no addr map, no slave never been selected !!)
constant mst_mask_vector : std_logic_vector(0 to NWBMST-1) := b"0000";
constant ScrnOut : boolean := false;
constant InstancePath : string := "msti_chk_all "
) return boolean is
variable madr, sadr : std_logic_vector(31 downto 0) := (others=>'0'); -- for display purpose only
variable gmst_idx : integer range 0 to NWBMST-1;
variable ssel_idx : integer range 0 to NWBSLV-1;
variable slv_found : boolean := false;
variable L : Line;
begin
if (msto_chk_quiet(msto) = true) then -- No request from all master, No need to continue check slvi
if msti_chk_quiet(msti) = false then
if ScrnOut then
write(L, Now, Right, 15);
write(L, " : " & InstancePath);
write(L, String'("E00: No request from any master"));
writeline(output, L);
end if;
return false;
end if;
else
-- Get master index of granted master
gmst_idx := gmst_idx_fn(msto, mst_mask_vector);
madr := msto(gmst_idx).adr & "00";
-- compare, search for selected slave
for i in 0 to NWBSLV-1 loop
sadr := slvo(i).wbcfg(63 downto 34) & "00" ; -- for disp on report only
if ScrnOut then
write(L, Now, Right, 15);
write(L, " : " & InstancePath);
write(L, String'("[addr_cmp] slv(" & integer'image(i) &
") with its address: " & hstr(sadr) &
" mst(" & integer'image(gmst_idx) &
") with its address: " & hstr(madr)));
writeline(output, L);
end if;
if (slvadrmap(slvo(i).wbcfg, msto(gmst_idx).adr) = true) and slvo(i).wbcfg(31 downto 24) = x"FF" then
slv_found := true;
ssel_idx := i; -- ssel_idx wont update immediately need to be next iteration ??
end if;
end loop;
-- end compare
for i in 0 to NWBMST-1 loop
if (i = gmst_idx) then
-- handle for no grant like this case m3 = disable, cyc = 1 and m2 = enable, cyc = 0 -> no grant (correct) => no need to assert the error
-- for master that really request although it's inactive,
if msto(i).cyc = '1' then
if slv_found = true then
--if msti(i).ack /= '1' and slvo(ssel_idx).ack /= '1' and slv_found /= true then
if msti(i).ack /= '1' and slvo(ssel_idx).ack /= '1' then
if ScrnOut then
write(L, Now, Right, 15);
write(L, " : " & InstancePath);
write(L, String'("E01: no Ack to granted master(" & integer'image(i) & ") from slv (" & integer'image(ssel_idx) & ")"));
writeline(output, L);
end if;
return false;
end if;
else
if ScrnOut then
write(L, Now, Right, 15);
write(L, " : " & InstancePath);
write(L, String'("E02: request address " & hstr(madr) & " not map with any slave, there should be no request signal " &
"from the granted master (" & integer'image(gmst_idx) & ")"));
writeline(output, L);
end if;
return false;
end if;
end if;
else -- non grant master (ack must be 0)
if msti(i).ack /= '0' then
if ScrnOut then
write(L, Now, Right, 15);
write(L, " : " & InstancePath);
write(L, String'("E03: mst(" & integer'image(i) & ") should not have any response from any slv !!!"));
writeline(output, L);
end if;
return false;
end if;
end if;
end loop;
end if;
return true;
end function;
---------------------------------------------------------------
-- Function: wbmi2core_chk(wb2core, we, mo_sel, mo_dat, mi_ack, resp_rddat)
--
-- This function checks response signal conversion from memory(wb_msti) to core(in_dmem_core)
-- esp made for core2wb.vhd testing
-- *** For SIM_ACC, the function has not supported so far. It MUST be manually put either RD_ACC or WR_ACC
-- 1st ack of SIM_ACC, fn should verify as write (ack)
-- 2nd ack of SIM_ACC, fn should verify as read (ack, rd_dat)
---------------------------------------------------------------
function wbmi2core_chk(
signal wb2core : dmem_core;
constant we : access_type := NO_ACC;
signal mo_sel : std_logic_vector(WB_SEL_WIDTH-1 downto 0);
signal mi_ack : std_logic;
signal resp_rddat : std_logic_vector(memory_width - 1 downto 0);
constant ScrnOut : boolean := false;
constant InstancePath: string := "wbmi2core_chk "
) return boolean is
variable L: Line;
begin
if we = RD_ACC then -- read
if wb2core.ready = mi_ack and
wb2core.read_data = dec_wb_dat(mo_sel, resp_rddat) -- optional since mainly check from sel signal
then
return true;
else
if ScrnOut then
write(L, Now, Right, 15);
write(L, " : " & InstancePath);
if we = RD_ACC then
write(L, String'("E00: Read req - "));
else
write(L, String'("E00: Sim req (read) - "));
end if;
if wb2core.ready = mi_ack then
write(L, String'("Mismacth read data: msti.dat = " & hstr(wb2core.read_data) & ", resp_rddat = " & hstr(dec_wb_dat(mo_sel, resp_rddat))));
end if;
if wb2core.read_data /= dec_wb_dat(mo_sel, resp_rddat) then
write(L, String'(" Incorrect ack. ready = " & str(wb2core.ready) & ", msti.ack = "& str(mi_ack)));
end if;
writeline(output, L);
end if;
end if;
elsif we = WR_ACC then -- write
if wb2core.ready = mi_ack then
return true;
else
if ScrnOut then
write(L, Now, Right, 15);
write(L, " : " & InstancePath);
write(L, String'("E01: Write req - Incorrect ack. (ready = " & str(wb2core.ready) & ", msti.ack = "& str(mi_ack)));
writeline(output, L);
end if;
end if;
elsif we = SIM_ACC then -- check only SIMACC_WR and for SIMACC_RD, use same as RD_ACC
if wb2core.ready = '0' and mi_ack = '1' then
return true;
else
if ScrnOut then
write(L, Now, Right, 15);
write(L, " : " & InstancePath);
write(L, String'("E02: Write req - Incorrect ack. (in_dmem.ready, msti.ack) should be = (0, 1) since the request is not complete yet"));
writeline(output, L);
end if;
end if;
else -- we = NO_ACC
if wb2core.ready = '1' then
return true;
else
if ScrnOut then
write(L, Now, Right, 15);
write(L, " : " & InstancePath);
write(L, String'("E03: No request - wb2core.ready should always assert"));
writeline(output, L);
end if;
end if;
end if;
return false;
end function;
---------------------------------------------------------------
-- Function: wb2mem_chk(wb2mem, slvi, we)
--
-- This function checks control signals (stb, cyc, we) of wb-to-mem conversion for single slave(memory)
-- Esp made for mem2wb.vhd testing
---------------------------------------------------------------
function wb2mem_chk(
signal wb2mem : core_dmem;
signal slvi : wb_slv_in_type;
constant we : access_type := NO_ACC;
constant ScrnOut : boolean := false;
constant InstancePath: string := "wb2mem_chk "
) return boolean is
variable L: Line;
begin
if we = RD_ACC then -- read
if wb2mem.read_en = '1' and
wb2mem.read_addr(WB_ADR_WIDTH-1 downto WB_ADR_BOUND) = slvi.adr and
wbszconv_chk(wb2mem.read_size) and
wb2mem.write_en = '0' then
return true;
else
if ScrnOut then
write(L, Now, Right, 15);
write(L, " : " & InstancePath);
write(L, String'( "E00: Read req - wrong conversion from WB to MEMORY. wb_adr = " &
hstr(wb2mem.read_addr) &
" ,slvi.adr = " &
hstr(slvi.adr) &
" ,wb.read_en = "
));
writeline(output, L);
end if;
end if;
elsif we = WR_ACC then -- write
if wb2mem.write_en = '1' and
wb2mem.write_addr(WB_ADR_WIDTH-1 downto WB_ADR_BOUND) = slvi.adr and
wbszconv_chk(wb2mem.write_size) and
wb2mem.write_data = dec_wb_dat(slvi.sel, slvi.dat) and
wb2mem.read_en = '0' then
return true;
else
if ScrnOut then
write(L, Now, Right, 15);
write(L, " : " & InstancePath);
write(L, String'("E01: Write req - "));
if wb2mem.write_en /= '1' then
write(L, String'("Write_en should be active, "));
end if;
writeline(output, L);
end if;
end if;
elsif we = NO_ACC then
if wb2mem.read_en = '0' and
wb2mem.write_en = '0' then
return true;
else
if ScrnOut then
write(L, Now, Right, 15);
write(L, " : " & InstancePath);
write(L, String'("E02: No request"));
writeline(output, L);
end if;
end if;
else
if wb2mem.read_en = '1' and
wb2mem.write_en = '1' then
return true;
else
if ScrnOut then
write(L, Now, Right, 15);
write(L, " : " & InstancePath);
write(L, String'("E03: Sim request"));
writeline(output, L);
end if;
end if;
end if;
return false;
end function;
---------------------------------------------------------------
-- Function: gmst_idx = gmst_idx_fn(msto, mst_mask_vector, grant)
--
-- return: index of master that get the grant (highest priority/index number)
-- this index get the highest priority w/o checking active status (mst_mask_vector) ???
---------------------------------------------------------------
function gmst_idx_fn (
signal msto : wb_mst_out_vector;
constant mst_mask_vector : std_logic_vector(0 to NWBMST-1) := b"0000";
constant ScrnOut : boolean := false;
constant InstancePath : string := "gmst_idx_fn "
) return integer is
variable gnt_idx :integer range 0 to NWBMST-1;
variable L : Line;
begin
for i in 0 to NWBMST-1 loop
if(msto(i).cyc='1' and mst_mask_vector(i) = '1' )then
gnt_idx := i;
end if;
end loop;
if ScrnOut then
write(L, Now, Right, 15);
write(L, " : " & InstancePath);
write(L, String'("master grant idx: "& integer'image(gnt_idx)));
writeline(output, L);
end if;
return gnt_idx;
end function;
---------------------------------------------------------------
-- Function: wbszconv_chk = wbszconv_chk(size)
--
-- return:
--
-- remark: Internal use in wb_tp itself
---------------------------------------------------------------
function wbszconv_chk(
signal size : in std_logic_vector(1 downto 0);
constant ScrnOut : boolean := false;
constant InstancePath: string := "wbszconv_chk"
) return boolean is
variable L: Line;
begin
case WB_PORT_GRAN is
when 8 =>
if size = "00" then return true; end if;
when 16 =>
if size = "01" then return true; end if;
when 32 =>
if size = "10" then return true; end if;
when 64 =>
if size = "11" then return true; end if;
end case;
if ScrnOut then
write(L, Now, Right, 15);
write(L, " : " & InstancePath);
write(L, String'("E00: wb port gran doesn't match with port gran of core or memory"));
writeline(output, L);
end if;
return false;
end function;
---------------------------------------------------------------
-- Function: corewb_conv_chk(core2wb_in, msto)
--
---------------------------------------------------------------
-- function corewb_conv_chk(
-- core2wb_in : core_dmem;
-- msto : wb_mst_out_type;
-- constant InstancePath : string := "corewb_conv_chk";
-- constant ScrnOut : boolean := false
-- ) return boolean is
-- variable result : boolean := false;
-- variable L : Line;
-- begin
--
-- --check enable
--
--
-- write_data : std_logic_vector(memory_width - 1 downto 0);
-- write_addr : std_logic_vector(memory_width - 1 downto 0);
-- write_size : std_logic_vector(1 downto 0);
-- write_en : std_logic;
--
--
-- read_addr : std_logic_vector(memory_width - 1 downto 0);
-- read_size : std_logic_vector(1 downto 0);
-- read_en : std_logic;
--
-- if ScrnOut then
-- write(L, Now, Right, 15);
-- write(L, " : " & InstancePath);
-- write(L, String'(" xxxxx"));
-- writeline(output, L);
-- end if;
-- return false;
-- end if;
--
--
-- return result;
-- end function;
--
---------------------------------------------------------------
-- Procedure: gencore2mem_req(req_acc, rd_adr, rd_sz, wr_adr, wr_sz, wr_dat)
-- gencore2mem_req(XX_ACC, x"AAAAAAAA", "00", x"AAAAAAAA", "00", x"DDDDDDDD")
--
---------------------------------------------------------------
procedure gencore2mem_req (
signal core2dmem :out core_dmem;
--
constant req_acc :in access_type := NO_ACC;
constant rd_adr :in std_logic_vector(memory_width - 1 downto 0) := (others=>'0');
constant rd_sz :in std_logic_vector(1 downto 0) := "00";
--
constant wr_adr :in std_logic_vector(memory_width - 1 downto 0):= (others=>'0');
constant wr_sz :in std_logic_vector(1 downto 0):= "00";
constant wr_dat :in std_logic_vector(memory_width - 1 downto 0):= (others=>'-');
--
constant ScrnOut :in boolean := false;
constant InstancePath :in string := "gencore2mem_req "
) is
variable L: Line;
begin
if ScrnOut then
write(L, Now, Right, 15);
write(L, " : " & InstancePath);
case(req_acc) is
when RD_ACC =>
write(L, String'("RD request: adr: " & hstr(rd_adr)));
when WR_ACC =>
write(L, String'("WR request: adr: " & hstr(wr_adr) & " WR data: " & hstr(wr_dat)));
when SIM_ACC =>
write(L, String'("SIM, RD request: adr: " & hstr(rd_adr)));
write(L, String'("SIM, WR request: adr: " & hstr(wr_adr) & " WR data: " & hstr(wr_dat)));
when others =>
write(L, String'("NO request"));
end case;
writeline(output, L);
end if;
case(req_acc) is
when RD_ACC =>
core2dmem.read_en <= '1'; core2dmem.write_en <= '0';
when WR_ACC =>
core2dmem.read_en <= '0'; core2dmem.write_en <= '1';
when SIM_ACC =>
core2dmem.read_en <= '1'; core2dmem.write_en <= '1';
when others =>
core2dmem.read_en <= '0'; core2dmem.write_en <= '0';
end case;
-- leave data and adr as it is, although enable = 0
core2dmem.read_addr <= rd_adr;
core2dmem.read_size <= rd_sz;
--
core2dmem.write_addr <= wr_adr;
core2dmem.write_size <= wr_sz;
core2dmem.write_data <= wr_dat;
end gencore2mem_req;
---------------------------------------------------------------
-- Procedure: genwb2core(msti, req_acc, rd_sz, wb_sel, read_data, ready)
--
-- similar to function 'dec_wb_dat' in wishbone.vhd
---------------------------------------------------------------
procedure genwb2core (
signal msti :out wb_mst_in_type;
--
constant req_acc :in access_type := NO_ACC;
constant rd_sz :in std_logic_vector(1 downto 0) := "00";
constant wb_sel :in std_logic_vector(WB_SEL_WIDTH-1 downto 0);
--
constant read_data :in std_logic_vector(memory_width - 1 downto 0);
constant ready :in std_logic := '0';
constant ScrnOut :in boolean := false;
constant InstancePath :in string := "genwb2core"
) is
variable L :Line;
variable mi :wb_mst_in_type;
begin
mi.ack := ready;
--gen data based on sel and size
mi.dat := (others=>'0');
if req_acc = RD_ACC then
--read
case (rd_sz) is
when "00" =>
mi.dat( 7 downto 0) := read_data( 7 downto 0);
if wb_sel = "0001" then mi.dat( 7 downto 0) := read_data( 7 downto 0);
elsif wb_sel = "0010" then mi.dat(15 downto 8) := read_data(15 downto 8);
elsif wb_sel = "0100" then mi.dat(23 downto 16) := read_data(23 downto 16);
elsif wb_sel = "1000" then mi.dat(31 downto 24) := read_data(31 downto 24);
else mi.dat := (others=>'0');
end if;
when "01" =>
if wb_sel = "0001" then mi.dat(15 downto 0) := read_data(15 downto 0);
elsif wb_sel = "0010" then mi.dat(31 downto 16) := read_data(31 downto 16);
elsif wb_sel = "0011" then mi.dat(23 downto 8) := read_data(23 downto 8);
else mi.dat := (others=>'0');
end if;
when "10" =>
mi.dat := read_data;
when others =>
mi.dat := (others=>'0');
end case;
if ScrnOut then
write(L, Now, Right, 15);
write(L, " : " & InstancePath);
write(L, String'("RD resp: RD data: " &
hstr(mi.dat) & ", sel: " &
str(wb_sel) & ", rd_sz: " &
str(rd_sz) & ", ack = " &
str(mi.ack)));
writeline(output, L);
end if;
else
mi.dat := (others=>'0');
if ScrnOut then
write(L, Now, Right, 15);
write(L, " : " & InstancePath);
write(L, String'("WR resp: ack = " & str(mi.ack)));
writeline(output, L);
end if;
end if;
msti <= mi;
end genwb2core;
---------------------------------------------------------------
-- Procedure: genmst_req(msto(req_mst_idx),req_mst_idx, we, adr, dat, sel)
--
-- Master read/Write req function for wb_intercon_tb
-- CAUTION: input slave address as 32 bits instaed of 30 bits to be readable
---------------------------------------------------------------
procedure genmst_req (
signal mst_out :out wb_mst_out_type;
constant req_idx :in integer := 0;
constant we :in std_logic;
constant adr :in std_logic_vector(WB_ADR_WIDTH-1 downto 0);
constant dat :in std_logic_vector(WB_PORT_SIZE-1 downto 0);
constant sel :in std_logic_vector(WB_SEL_WIDTH-1 downto 0);
constant ScrnOut :in boolean := false;
constant InstancePath :in string := "genmst_req "
) is
variable L: Line;
begin
if ScrnOut then
write(L, Now, Right, 15);
write(L, " : " & InstancePath);
write(L, String'("Master(" & integer'image(req_idx) &") Request address: " & hstr(adr)));
writeline(output, L);
end if;
mst_out <= wbm_out_none; -- initial
mst_out.adr <= adr(31 downto 2);
mst_out.sel <= sel;
mst_out.stb <= '1';
mst_out.cyc <= '1';
-- mst_out.wbidx <= req_idx;
if we = '0' then -- read
mst_out.we <= '0';
mst_out.dat <= (others=>'-');
else -- write
mst_out.we <= '1';
mst_out.dat <= dat;
end if;
end genmst_req;
---------------------------------------------------------------
-- Procedure: list_all_mst_req(msto_vector, mst_mask_vector);
--
-- Utility procedure to list all master request(s)
---------------------------------------------------------------
procedure list_all_mst_req (
signal msto : in wb_mst_out_vector;
constant mst_mask_vector : std_logic_vector(0 to NWBMST-1) := b"0000";
constant ScrnOut : boolean := false;
constant InstancePath : string := "list_all_mst_req "
) is
variable mstat :integer range 0 to 1 := 0; -- for disp purpose
variable madr : std_logic_vector(31 downto 0) := (others=> '0');
variable noreq: boolean := true;
variable L : Line;
begin
for i in 0 to NWBMST-1 loop
if msto(i).cyc = '1' then
if mst_mask_vector(i) = '0' then
mstat := 0;
else
mstat := 1;
end if;
madr := msto(i).adr & "00";
if ScrnOut then
write(L, Now, Right, 15);
write(L, " : " & InstancePath);
write(L, String'("Request mst(" & integer'image(i) & "), addr: " & hstr(madr) & " with status: " & integer'image(mstat)));
writeline(output, L);
end if;
noreq := false;
end if;
end loop;
if noreq and ScrnOut then
write(L, Now, Right, 15);
write(L, " : " & InstancePath);
write(L, String'("No request"));
writeline(output, L);
end if;
end list_all_mst_req;
procedure generate_sync_wb_single_write(
signal msto : out wb_mst_out_type;
signal slvo : in wb_slv_out_type;
signal clk : in std_logic;
signal writedata : std_logic_vector(WB_PORT_SIZE-1 downto 0);
constant size : std_logic_vector(WB_ADR_BOUND-1 downto 0) := "10";
constant adr_offset : integer := 0 -- Offset added to the access address
) is
variable adr : std_logic_vector(31 downto 0);
variable sel : std_logic_vector(WB_SEL_WIDTH downto 0);
begin
adr := slvo.wbcfg(63 downto 32);
adr := std_logic_vector(unsigned(adr) + adr_offset);
--continue if rising edge active, else wait for it
--allows subsequent procedure calls without waiting for next edge
if not rising_edge(clk) then
wait until rising_edge(clk);
end if;
msto <= wbm_out_none;
msto.cyc <= '1';
msto.stb <= '1';
msto.we <= '1';
msto.sel <= gen_select(adr(1 downto 0),size);
msto.adr <= adr(31 downto 2);
msto.dat <= enc_wb_dat(adr(1 downto 0),size,writedata);
wait until rising_edge(clk);
wait until slvo.ack = '1' for 100 ns;
assert slvo.ack = '1' report "Slave did not ACK the write properly within 10 wait states";
wait until rising_edge(clk);
msto.cyc <= '0';
msto.stb <= '0';
msto.we <= '-';
msto.sel <= (others=>'-');
msto.dat <= (others=>'-');
msto.adr <= (others=>'-');
end procedure;
procedure generate_sync_wb_burst_write(
signal msto : out wb_mst_out_type;
signal slvo : in wb_slv_out_type;
signal clk : in std_logic;
signal writedata : std_logic_vector(WB_PORT_SIZE-1 downto 0);
constant NUMBURSTS : positive := 4;
constant SIZE : std_logic_vector(WB_ADR_BOUND-1 downto 0) := "10";
constant ADR_OFFSET : integer := 0 -- Offset added to the access address
) is
variable adr : std_logic_vector(31 downto 0);
variable sel : std_logic_vector(WB_SEL_WIDTH downto 0);
variable i : integer := 1;
begin
adr := slvo.wbcfg(63 downto 32);
adr := std_logic_vector(unsigned(adr) + ADR_OFFSET);
--continue if rising edge active, else wait for it
--allows subsequent procedure calls without waiting for next edge
if not rising_edge(clk) then
wait until rising_edge(clk);
end if;
msto <= wbm_out_none;
msto.cyc <= '1';
msto.stb <= '1';
msto.we <= '1';
msto.sel <= gen_select(adr(1 downto 0),SIZE);
msto.adr <= adr(31 downto 2);
msto.dat <= enc_wb_dat(adr(1 downto 0),SIZE,writedata);
msto.cti <= "010";
while i /= NUMBURSTS loop
wait until rising_edge(clk);
wait until slvo.ack = '1' for 1 ps;
adr := std_logic_vector(unsigned(adr) + 4);
msto.adr <= adr(31 downto 2);
msto.dat <= enc_wb_dat(adr(1 downto 0),SIZE,std_logic_vector(unsigned(writedata)+i));
i := i+1;
end loop;
msto.cti <= "111";
wait until rising_edge(clk);
msto.stb <= '0';
msto.cti <= (others => '-');
msto.dat <= (others => '-');
msto.sel <= (others => '-');
wait until rising_edge(clk);
if slvo.ack = '1' then
msto <= wbm_out_none;
end if;
end procedure;
procedure generate_sync_wb_single_read(
signal msto : out wb_mst_out_type; -- Slave input
signal slvo : in wb_slv_out_type; -- Slave output
signal clk : in std_logic;
signal readdata : out std_logic_vector(WB_PORT_SIZE -1 downto 0);
constant adr_offset : integer := 0; -- Offset added to the access address
constant size : std_logic_vector(WB_ADR_BOUND-1 downto 0) := "10"
) is
variable sel : std_logic_vector(WB_SEL_WIDTH-1 downto 0);
variable adr : std_logic_vector(31 downto 0);
begin
adr := slvo.wbcfg(63 downto 32);
adr := std_logic_vector(unsigned(adr) + adr_offset);
sel := gen_select(adr(1 downto 0),size);
--allow subsequent reads
if not rising_edge(clk) then
wait until rising_edge(clk);
end if;
msto <= wbm_out_none;
msto.cyc <= '1';
msto.stb <= '1';
msto.we <= '0';
msto.sel <= sel;
msto.adr <= adr;
wait until rising_edge(clk);
wait until slvo.ack='1' for 100 ns;
assert slvo.ack='1' report "Slave did not ACK the read properly within 10 wait states";
if slvo.ack='1' then
readdata <= dec_wb_dat(sel,slvo.dat);
else
readdata <= (others=>'X');
end if;
wait until rising_edge(clk);
msto.cyc <= '0';
msto.stb <= '0';
msto.we <= '-';
msto.sel <= (others=>'-');
msto.dat <= (others=>'-');
msto.adr <= (others=>'-');
end procedure;
procedure generate_sync_wb_burst_read(
signal msto : out wb_mst_out_type; -- Slave input
signal slvo : in wb_slv_out_type; -- Slave output
signal clk : in std_logic;
signal readdata : out std_logic_vector(WB_PORT_SIZE -1 downto 0);
constant NUMBURSTS : positive := 4;
constant ADR_OFFSET : integer := 0; -- Offset added to the access address
constant SIZE : std_logic_vector(WB_ADR_BOUND-1 downto 0) := "10"
) is
variable sel : std_logic_vector(WB_SEL_WIDTH-1 downto 0);
variable adr : std_logic_vector(31 downto 0);
variable i : integer := 1;
begin
adr := slvo.wbcfg(63 downto 32);
adr := std_logic_vector(unsigned(adr) + ADR_OFFSET);
sel := gen_select(adr(1 downto 0),SIZE);
--allow subsequent reads
if not rising_edge(clk) then
wait until rising_edge(clk);
end if;
msto <= wbm_out_none;
msto.cyc <= '1';
msto.stb <= '1';
msto.we <= '0';
msto.sel <= sel;
msto.adr <= adr;
msto.cti <= "010";
while i /= NUMBURSTS loop
wait until rising_edge(clk);
adr := std_logic_vector(unsigned(adr) + 4);
msto.adr <= adr(31 downto 2);
readdata <= dec_wb_dat(sel,slvo.dat);
i := i+1;
end loop;
msto.cti <= "111";
wait until rising_edge(clk);
msto.stb <= '0';
msto.cti <= (others => '-');
msto.dat <= (others => '-');
msto.sel <= (others => '-');
if slvo.ack = '1' then
readdata <= dec_wb_dat(sel,slvo.dat);
end if;
wait until rising_edge(clk);
msto <= wbm_out_none;
end procedure;
end wb_tp;