Browse Source

add simple wishbone master and slave with support of classic single write and read as specified in the wishbone spec b4; add unit tests for wishbone m,aster & slave

pull/1/head
T. Meissner 10 years ago
parent
commit
7d60f0ae1b
4 changed files with 476 additions and 0 deletions
  1. +119
    -0
      syn/WishBoneMasterE.vhd
  2. +90
    -0
      syn/WishBoneSlaveE.vhd
  3. +8
    -0
      test/Makefile
  4. +259
    -0
      test/WishBoneT.vhd

+ 119
- 0
syn/WishBoneMasterE.vhd View File

@ -0,0 +1,119 @@
library ieee;
use ieee.std_logic_1164.all;
entity WishBoneMasterE is
generic (
G_ADR_WIDTH : positive := 8; --* address bus width
G_DATA_WIDTH : positive := 8 --* data bus width
);
port (
--+ wishbone system if
WbRst_i : in std_logic;
WbClk_i : in std_logic;
--+ wishbone outputs
WbCyc_o : out std_logic;
WbStb_o : out std_logic;
WbWe_o : out std_logic;
WbAdr_o : out std_logic_vector(G_ADR_WIDTH-1 downto 0);
WbDat_o : out std_logic_vector(G_DATA_WIDTH-1 downto 0);
--+ wishbone inputs
WbDat_i : in std_logic_vector(G_DATA_WIDTH-1 downto 0);
WbAck_i : in std_logic;
WbErr_i : in std_logic;
--+ local register if
LocalWen_i : in std_logic;
LocalRen_i : in std_logic;
LocalAdress_i : in std_logic_vector(G_ADR_WIDTH-1 downto 0);
LocalData_i : in std_logic_vector(G_DATA_WIDTH-1 downto 0);
LocalData_o : out std_logic_vector(G_DATA_WIDTH-1 downto 0);
LocalAck_o : out std_logic;
LocalError_o : out std_logic
);
end entity WishBoneMasterE;
architecture rtl of WishBoneMasterE is
type t_wb_master_fsm is (IDLE, ADDRESS, DATA);
signal s_wb_master_fsm : t_wb_master_fsm;
signal s_wb_wen : std_logic;
begin
--+ Wishbone master control state machine
WbMasterStatesP : process (WbClk_i) is
begin
if (rising_edge(WbClk_i)) then
if (WbRst_i = '1') then
s_wb_master_fsm <= IDLE;
else
WbReadC : case s_wb_master_fsm is
when IDLE =>
if (LocalWen_i = '1' or LocalRen_i = '1') then
s_wb_master_fsm <= ADDRESS;
end if;
when ADDRESS =>
if (WbErr_i = '0') then
s_wb_master_fsm <= DATA;
else
s_wb_master_fsm <= IDLE;
end if;
when DATA =>
if (WbErr_i = '1' or WbAck_i = '1') then
s_wb_master_fsm <= IDLE;
end if;
when others =>
s_wb_master_fsm <= IDLE;
end case;
end if;
end if;
end process WbMasterStatesP;
--+ combinatoral local register if outputs
LocalData_o <= WbDat_i when s_wb_master_fsm = DATA else (others => '0');
LocalError_o <= WbErr_i when s_wb_master_fsm /= IDLE else '0';
LocalAck_o <= WbAck_i when s_wb_master_fsm = DATA and WbErr_i = '0' else '0';
--+ combinatoral wishbone if outputs
WbStb_o <= '1' when s_wb_master_fsm /= IDLE else '0';
WbCyc_o <= '1' when s_wb_master_fsm /= IDLE else '0';
WbWe_o <= s_wb_wen when s_wb_master_fsm /= IDLE else '0';
--+ registered wishbone if outputs
OutRegsP : process (WbClk_i) is
begin
if(rising_edge(WbClk_i)) then
if(WbRst_i = '1') then
WbAdr_o <= (others => '0');
WbDat_o <= (others => '0');
s_wb_wen <= '0';
else
if (s_wb_master_fsm = IDLE) then
if (LocalWen_i = '1' or LocalRen_i = '1') then
WbAdr_o <= LocalAdress_i;
s_wb_wen <= LocalWen_i;
end if;
if (LocalWen_i = '1') then
WbDat_o <= LocalData_i;
end if;
end if;
end if;
end if;
end process OutRegsP;
end architecture rtl;

+ 90
- 0
syn/WishBoneSlaveE.vhd View File

@ -0,0 +1,90 @@
library ieee;
use ieee.std_logic_1164.all;
entity WishBoneSlaveE is
generic (
G_ADR_WIDTH : positive := 8; --* address bus width
G_DATA_WIDTH : positive := 8 --* data bus width
);
port (
--+ wishbone system if
WbRst_i : in std_logic;
WbClk_i : in std_logic;
--+ wishbone inputs
WbCyc_i : in std_logic;
WbStb_i : in std_logic;
WbWe_i : in std_logic;
WbAdr_i : in std_logic_vector(G_ADR_WIDTH-1 downto 0);
WbDat_i : in std_logic_vector(G_DATA_WIDTH-1 downto 0);
--+ wishbone outputs
WbDat_o : out std_logic_vector(G_DATA_WIDTH-1 downto 0);
WbAck_o : out std_logic;
WbErr_o : out std_logic;
--+ local register if
LocalWen_o : out std_logic;
LocalRen_o : out std_logic;
LocalAdress_o : out std_logic_vector(G_ADR_WIDTH-1 downto 0);
LocalData_o : out std_logic_vector(G_DATA_WIDTH-1 downto 0);
LocalData_i : in std_logic_vector(G_DATA_WIDTH-1 downto 0)
);
end entity WishBoneSlaveE;
architecture rtl of WishBoneSlaveE is
type t_wb_slave_fsm is (IDLE, ADDRESS, DATA);
signal s_wb_slave_fsm : t_wb_slave_fsm;
signal s_wb_active : boolean;
begin
WbSlaveControlP : process (WbClk_i) is
begin
if (rising_edge(WbClk_i)) then
if (WbRst_i = '1') then
s_wb_slave_fsm <= IDLE;
else
WbReadC : case s_wb_slave_fsm is
when IDLE =>
s_wb_slave_fsm <= ADDRESS;
when ADDRESS =>
if s_wb_active then
s_wb_slave_fsm <= DATA;
end if;
when DATA =>
s_wb_slave_fsm <= ADDRESS;
when others =>
s_wb_slave_fsm <= IDLE;
end case;
end if;
end if;
end process WbSlaveControlP;
s_wb_active <= true when s_wb_slave_fsm /= IDLE and WbCyc_i = '1' and WbStb_i = '1' else false;
--+ local register if outputs
LocalWen_o <= WbWe_i when s_wb_slave_fsm = DATA and s_wb_active else '0';
LocalRen_o <= not(WbWe_i) when s_wb_slave_fsm = ADDRESS and s_wb_active else '0';
LocalAdress_o <= WbAdr_i when s_wb_slave_fsm /= IDLE and s_wb_active else (others => '0');
LocalData_o <= WbDat_i when s_wb_slave_fsm = DATA and s_wb_active and WbWe_i = '1' else (others => '0');
--+ wishbone if outputs
WbDat_o <= LocalData_i when s_wb_slave_fsm = DATA and WbWe_i = '0' else (others => '0');
WbAck_o <= '1' when s_wb_slave_fsm = DATA else '0';
WbErr_o <= '0';
end architecture rtl;

+ 8
- 0
test/Makefile View File

@ -36,6 +36,13 @@ spit : vhdl2008 osvvm SpiT.vhd $(SIM_SRC)/AssertP.vhd $(SIM_SRC)/SimP.vhd $(SIM_
ghdl -e --std=$(VHD_STD) --ieee=synopsys SpiT ghdl -e --std=$(VHD_STD) --ieee=synopsys SpiT
ghdl -r --std=$(VHD_STD) SpiT --wave=spit.ghw ghdl -r --std=$(VHD_STD) SpiT --wave=spit.ghw
wishbonet : vhdl2008 osvvm WishBoneT.vhd $(SYN_SRC)/WishBoneMasterE.vhd $(SYN_SRC)/WishBoneSlaveE.vhd
ghdl -a --std=$(VHD_STD) --work=libvhdl $(SIM_SRC)/AssertP.vhd $(SIM_SRC)/SimP.vhd $(SIM_SRC)/QueueP.vhd
ghdl -a --std=$(VHD_STD) -fpsl $(SYN_SRC)/WishBoneMasterE.vhd $(SYN_SRC)/WishBoneSlaveE.vhd
ghdl -a --std=$(VHD_STD) --ieee=synopsys WishBoneT.vhd
ghdl -e --std=$(VHD_STD) --ieee=synopsys WishBoneT
ghdl -r --std=$(VHD_STD) --ieee=synopsys WishBoneT --wave=wishbonet.ghw
.PHONY: clean .PHONY: clean
clean: clean:
rm -f *.o rm -f *.o
@ -45,6 +52,7 @@ clean:
rm -f stringt rm -f stringt
rm -f simt rm -f simt
rm -f spit rm -f spit
rm -f wishbonet
.PHONY: distclean .PHONY: distclean
distclean: clean distclean: clean


+ 259
- 0
test/WishBoneT.vhd View File

@ -0,0 +1,259 @@
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
--+ including vhdl 2008 libraries
--+ These lines can be commented out when using
--+ a simulator with built-in VHDL 2008 support
library ieee_proposed;
use ieee_proposed.standard_additions.all;
use ieee_proposed.std_logic_1164_additions.all;
use ieee_proposed.numeric_std_additions.all;
library osvvm;
use osvvm.RandomPkg.all;
library libvhdl;
use libvhdl.AssertP.all;
use libvhdl.SimP.all;
use libvhdl.QueueP.all;
entity WishBoneT is
end entity WishBoneT;
architecture sim of WishBoneT is
component WishBoneMasterE is
generic (
G_ADR_WIDTH : positive := 8; --* address bus width
G_DATA_WIDTH : positive := 8 --* data bus width
);
port (
--+ wishbone system if
WbRst_i : in std_logic;
WbClk_i : in std_logic;
--+ wishbone outputs
WbCyc_o : out std_logic;
WbStb_o : out std_logic;
WbWe_o : out std_logic;
WbAdr_o : out std_logic_vector(G_ADR_WIDTH-1 downto 0);
WbDat_o : out std_logic_vector(G_DATA_WIDTH-1 downto 0);
--+ wishbone inputs
WbDat_i : in std_logic_vector(G_DATA_WIDTH-1 downto 0);
WbAck_i : in std_logic;
WbErr_i : in std_logic;
--+ local register if
LocalWen_i : in std_logic;
LocalRen_i : in std_logic;
LocalAdress_i : in std_logic_vector(G_ADR_WIDTH-1 downto 0);
LocalData_i : in std_logic_vector(G_DATA_WIDTH-1 downto 0);
LocalData_o : out std_logic_vector(G_DATA_WIDTH-1 downto 0);
LocalAck_o : out std_logic;
LocalError_o : out std_logic
);
end component WishBoneMasterE;
component WishBoneSlaveE is
generic (
G_ADR_WIDTH : positive := 8; --* address bus width
G_DATA_WIDTH : positive := 8 --* data bus width
);
port (
--+ wishbone system if
WbRst_i : in std_logic;
WbClk_i : in std_logic;
--+ wishbone inputs
WbCyc_i : in std_logic;
WbStb_i : in std_logic;
WbWe_i : in std_logic;
WbAdr_i : in std_logic_vector(G_ADR_WIDTH-1 downto 0);
WbDat_i : in std_logic_vector(G_DATA_WIDTH-1 downto 0);
--* wishbone outputs
WbDat_o : out std_logic_vector(G_DATA_WIDTH-1 downto 0);
WbAck_o : out std_logic;
WbErr_o : out std_logic;
--+ local register if
LocalWen_o : out std_logic;
LocalRen_o : out std_logic;
LocalAdress_o : out std_logic_vector(G_ADR_WIDTH-1 downto 0);
LocalData_o : out std_logic_vector(G_DATA_WIDTH-1 downto 0);
LocalData_i : in std_logic_vector(G_DATA_WIDTH-1 downto 0)
);
end component WishBoneSlaveE;
--* testbench global clock period
constant C_PERIOD : time := 5 ns;
--* Wishbone data width
constant C_DATA_WIDTH : natural := 8;
--* Wishbone address width
constant C_ADDRESS_WIDTH : natural := 8;
--* testbench global clock
signal s_wb_clk : std_logic := '1';
--* testbench global reset
signal s_wb_reset : std_logic := '1';
--+ test done array with entry for each test
signal s_test_done : boolean;
signal s_wb_cyc : std_logic;
signal s_wb_stb : std_logic;
signal s_wb_we : std_logic;
signal s_wb_adr : std_logic_vector(C_ADDRESS_WIDTH-1 downto 0);
signal s_wb_master_data : std_logic_vector(C_DATA_WIDTH-1 downto 0);
signal s_wb_slave_data : std_logic_vector(C_DATA_WIDTH-1 downto 0);
signal s_wb_ack : std_logic;
signal s_wb_err : std_logic;
signal s_master_local_wen : std_logic;
signal s_master_local_ren : std_logic;
signal s_master_local_adress : std_logic_vector(C_ADDRESS_WIDTH-1 downto 0);
signal s_master_local_din : std_logic_vector(C_DATA_WIDTH-1 downto 0);
signal s_master_local_dout : std_logic_vector(C_DATA_WIDTH-1 downto 0);
signal s_master_local_ack : std_logic;
signal s_master_local_error : std_logic;
signal s_slave_local_wen : std_logic;
signal s_slave_local_ren : std_logic;
signal s_slave_local_adress : std_logic_vector(C_ADDRESS_WIDTH-1 downto 0);
signal s_slave_local_dout : std_logic_vector(C_DATA_WIDTH-1 downto 0);
signal s_slave_local_din : std_logic_vector(C_DATA_WIDTH-1 downto 0);
type t_register is array (0 to integer'(2**C_ADDRESS_WIDTH-1)) of std_logic_vector(C_DATA_WIDTH-1 downto 0);
shared variable sv_wishbone_queue : t_list_queue;
begin
--* testbench global clock
s_wb_clk <= not(s_wb_clk) after C_PERIOD/2 when not(s_test_done) else '0';
--* testbench global reset
s_wb_reset <= '0' after C_PERIOD * 5;
WbMasterLocalP : process is
variable v_random : RandomPType;
variable v_wbmaster_data : std_logic_vector(C_DATA_WIDTH-1 downto 0);
begin
v_random.InitSeed(v_random'instance_name);
v_wbmaster_data := (others => '0');
s_master_local_din <= (others => '0');
s_master_local_adress <= (others => '0');
s_master_local_wen <= '0';
s_master_local_ren <= '0';
wait until s_wb_reset = '0';
-- write the wishbone slave registers
for i in 0 to integer'(2**C_ADDRESS_WIDTH-1) loop
v_wbmaster_data := v_random.RandSlv(C_DATA_WIDTH);
s_master_local_din <= v_wbmaster_data;
s_master_local_adress <= std_logic_vector(to_unsigned(i, C_ADDRESS_WIDTH));
s_master_local_wen <= '1';
wait until rising_edge(s_wb_clk);
s_master_local_din <= (others => '0');
s_master_local_adress <= (others => '0');
s_master_local_wen <= '0';
wait until rising_edge(s_wb_clk) and s_master_local_ack = '1';
sv_wishbone_queue.push(v_wbmaster_data);
end loop;
-- read back and check the wishbone slave registers
for i in 0 to integer'(2**C_ADDRESS_WIDTH-1) loop
s_master_local_adress <= std_logic_vector(to_unsigned(i, C_ADDRESS_WIDTH));
s_master_local_ren <= '1';
wait until rising_edge(s_wb_clk);
s_master_local_adress <= (others => '0');
s_master_local_ren <= '0';
wait until rising_edge(s_wb_clk) and s_master_local_ack = '1';
sv_wishbone_queue.pop(v_wbmaster_data);
assert_equal(s_master_local_dout, v_wbmaster_data);
end loop;
report "INFO: Test successfully finished!";
s_test_done <= true;
wait;
end process WbMasterLocalP;
i_WishBoneMasterE : WishBoneMasterE
generic map (
G_ADR_WIDTH => C_ADDRESS_WIDTH,
G_DATA_WIDTH => C_DATA_WIDTH
)
port map (
--+ wishbone system if
WbRst_i => s_wb_reset,
WbClk_i => s_wb_clk,
--+ wishbone outputs
WbCyc_o => s_wb_cyc,
WbStb_o => s_wb_stb,
WbWe_o => s_wb_we,
WbAdr_o => s_wb_adr,
WbDat_o => s_wb_master_data,
--+ wishbone inputs
WbDat_i => s_wb_slave_data,
WbAck_i => s_wb_ack,
WbErr_i => s_wb_err,
--+ local register if
LocalWen_i => s_master_local_wen,
LocalRen_i => s_master_local_ren,
LocalAdress_i => s_master_local_adress,
LocalData_i => s_master_local_din,
LocalData_o => s_master_local_dout,
LocalAck_o => s_master_local_ack,
LocalError_o => s_master_local_error
);
i_WishBoneSlaveE : WishBoneSlaveE
generic map (
G_ADR_WIDTH => C_ADDRESS_WIDTH,
G_DATA_WIDTH => C_DATA_WIDTH
)
port map (
--+ wishbone system if
WbRst_i => s_wb_reset,
WbClk_i => s_wb_clk,
--+ wishbone inputs
WbCyc_i => s_wb_cyc,
WbStb_i => s_wb_stb,
WbWe_i => s_wb_we,
WbAdr_i => s_wb_adr,
WbDat_i => s_wb_master_data,
--* wishbone outputs
WbDat_o => s_wb_slave_data,
WbAck_o => s_wb_ack,
WbErr_o => s_wb_err,
--+ local register if
LocalWen_o => s_slave_local_wen,
LocalRen_o => s_slave_local_ren,
LocalAdress_o => s_slave_local_adress,
LocalData_o => s_slave_local_dout,
LocalData_i => s_slave_local_din
);
WbSlaveLocalP : process (s_wb_clk) is
variable v_register : t_register := (others => (others => '0'));
begin
if (rising_edge(s_wb_clk)) then
if (s_wb_reset = '1') then
v_register := (others => (others => '0'));
s_slave_local_din <= (others => '0');
else
if (s_slave_local_wen = '1') then
v_register(to_integer(unsigned(s_slave_local_adress))) := s_slave_local_dout;
elsif (s_slave_local_ren = '1') then
s_slave_local_din <= v_register(to_integer(unsigned(s_slave_local_adress)));
end if;
end if;
end if;
end process WbSlaveLocalP;
end architecture sim;

Loading…
Cancel
Save