diff --git a/cr_file.vhdl b/cr_file.vhdl index 8ad8570..fa56dd9 100644 --- a/cr_file.vhdl +++ b/cr_file.vhdl @@ -6,55 +6,55 @@ library work; use work.common.all; entity cr_file is - port( - clk : in std_logic; + port( + clk : in std_logic; - d_in : in Decode2ToCrFileType; - d_out : out CrFileToDecode2Type; + d_in : in Decode2ToCrFileType; + d_out : out CrFileToDecode2Type; - w_in : in WritebackToCrFileType - ); + w_in : in WritebackToCrFileType + ); end entity cr_file; architecture behaviour of cr_file is - signal crs : std_ulogic_vector(31 downto 0) := (others => '0'); - signal crs_updated : std_ulogic_vector(31 downto 0) := (others => '0'); + signal crs : std_ulogic_vector(31 downto 0) := (others => '0'); + signal crs_updated : std_ulogic_vector(31 downto 0) := (others => '0'); begin - cr_create_0: process(all) - variable hi, lo : integer := 0; - variable cr_tmp : std_ulogic_vector(31 downto 0) := (others => '0'); - begin - cr_tmp := crs; - - for i in 0 to 7 loop - if w_in.write_cr_mask(i) = '1' then - lo := i*4; - hi := lo + 3; - cr_tmp(hi downto lo) := w_in.write_cr_data(hi downto lo); - end if; - end loop; - - crs_updated <= cr_tmp; - end process; - - -- synchronous writes - cr_write_0: process(clk) - begin - if rising_edge(clk) then - if w_in.write_cr_enable = '1' then - report "Writing " & to_hstring(w_in.write_cr_data) & " to CR mask " & to_hstring(w_in.write_cr_mask); - end if; - crs <= crs_updated; - end if; - end process; - - -- asynchronous reads - cr_read_0: process(all) - begin - -- just return the entire CR to make mfcrf easier for now - if d_in.read = '1' then - report "Reading CR " & to_hstring(crs_updated); - end if; - d_out.read_cr_data <= crs_updated; - end process; + cr_create_0: process(all) + variable hi, lo : integer := 0; + variable cr_tmp : std_ulogic_vector(31 downto 0) := (others => '0'); + begin + cr_tmp := crs; + + for i in 0 to 7 loop + if w_in.write_cr_mask(i) = '1' then + lo := i*4; + hi := lo + 3; + cr_tmp(hi downto lo) := w_in.write_cr_data(hi downto lo); + end if; + end loop; + + crs_updated <= cr_tmp; + end process; + + -- synchronous writes + cr_write_0: process(clk) + begin + if rising_edge(clk) then + if w_in.write_cr_enable = '1' then + report "Writing " & to_hstring(w_in.write_cr_data) & " to CR mask " & to_hstring(w_in.write_cr_mask); + end if; + crs <= crs_updated; + end if; + end process; + + -- asynchronous reads + cr_read_0: process(all) + begin + -- just return the entire CR to make mfcrf easier for now + if d_in.read = '1' then + report "Reading CR " & to_hstring(crs_updated); + end if; + d_out.read_cr_data <= crs_updated; + end process; end architecture behaviour; diff --git a/execute2.vhdl b/execute2.vhdl index 7942274..9fdb1dd 100644 --- a/execute2.vhdl +++ b/execute2.vhdl @@ -11,47 +11,47 @@ use work.ppc_fx_insns.all; -- We handle rc form instructions here entity execute2 is - port ( - clk : in std_ulogic; + port ( + clk : in std_ulogic; - e_in : in Execute1ToExecute2Type; - e_out : out Execute2ToWritebackType - ); + e_in : in Execute1ToExecute2Type; + e_out : out Execute2ToWritebackType + ); end execute2; architecture behave of execute2 is - signal r, rin : Execute2ToWritebackType; + signal r, rin : Execute2ToWritebackType; begin - execute2_0: process(clk) - begin - if rising_edge(clk) then - r <= rin; - end if; - end process; - - execute2_1: process(all) - variable v : Execute2ToWritebackType; - begin - v := rin; - - v.valid := e_in.valid; - v.write_enable := e_in.write_enable; - v.write_reg := e_in.write_reg; - v.write_data := e_in.write_data; - v.write_cr_enable := e_in.write_cr_enable; - v.write_cr_mask := e_in.write_cr_mask; - v.write_cr_data := e_in.write_cr_data; - - if e_in.valid = '1' and e_in.rc = '1' then - v.write_cr_enable := '1'; - v.write_cr_mask := num_to_fxm(0); - v.write_cr_data := ppc_cmpi('1', e_in.write_data, x"0000") & x"0000000"; - end if; - - -- Update registers - rin <= v; - - -- Update outputs - e_out <= r; - end process; + execute2_0: process(clk) + begin + if rising_edge(clk) then + r <= rin; + end if; + end process; + + execute2_1: process(all) + variable v : Execute2ToWritebackType; + begin + v := rin; + + v.valid := e_in.valid; + v.write_enable := e_in.write_enable; + v.write_reg := e_in.write_reg; + v.write_data := e_in.write_data; + v.write_cr_enable := e_in.write_cr_enable; + v.write_cr_mask := e_in.write_cr_mask; + v.write_cr_data := e_in.write_cr_data; + + if e_in.valid = '1' and e_in.rc = '1' then + v.write_cr_enable := '1'; + v.write_cr_mask := num_to_fxm(0); + v.write_cr_data := ppc_cmpi('1', e_in.write_data, x"0000") & x"0000000"; + end if; + + -- Update registers + rin <= v; + + -- Update outputs + e_out <= r; + end process; end; diff --git a/glibc_random.vhdl b/glibc_random.vhdl index 2284e04..c66d7ec 100644 --- a/glibc_random.vhdl +++ b/glibc_random.vhdl @@ -6,33 +6,33 @@ library work; use work.glibc_random_helpers.all; package glibc_random is - function pseudorand(a: integer) return std_ulogic_vector; - function pseudorand1 return std_ulogic; + function pseudorand(a: integer) return std_ulogic_vector; + function pseudorand1 return std_ulogic; end package glibc_random; package body glibc_random is - function pseudorand(a: integer) return std_ulogic_vector is - variable tmp1, tmp2, tmp3, tmp4: std_ulogic_vector(31 downto 0); - variable ret: std_ulogic_vector(63 downto 0); - begin - tmp1 := std_ulogic_vector(to_unsigned(random, 32)); - tmp2 := std_ulogic_vector(to_unsigned(random, 32)); - if a <= 32 then - ret := tmp1 & tmp2; - else - tmp3 := std_ulogic_vector(to_unsigned(random, 32)); - tmp4 := std_ulogic_vector(to_unsigned(random, 32)); + function pseudorand(a: integer) return std_ulogic_vector is + variable tmp1, tmp2, tmp3, tmp4: std_ulogic_vector(31 downto 0); + variable ret: std_ulogic_vector(63 downto 0); + begin + tmp1 := std_ulogic_vector(to_unsigned(random, 32)); + tmp2 := std_ulogic_vector(to_unsigned(random, 32)); + if a <= 32 then + ret := tmp1 & tmp2; + else + tmp3 := std_ulogic_vector(to_unsigned(random, 32)); + tmp4 := std_ulogic_vector(to_unsigned(random, 32)); - ret := tmp1(15 downto 0) & tmp2(15 downto 0) & tmp3(15 downto 0) & tmp4(15 downto 0); - end if; + ret := tmp1(15 downto 0) & tmp2(15 downto 0) & tmp3(15 downto 0) & tmp4(15 downto 0); + end if; - return ret((a-1) downto 0); - end; + return ret((a-1) downto 0); + end; - function pseudorand1 return std_ulogic is - variable tmp: std_ulogic_vector(31 downto 0); - begin - tmp := std_ulogic_vector(to_unsigned(random, 32)); - return tmp(0); - end; + function pseudorand1 return std_ulogic is + variable tmp: std_ulogic_vector(31 downto 0); + begin + tmp := std_ulogic_vector(to_unsigned(random, 32)); + return tmp(0); + end; end package body glibc_random; diff --git a/glibc_random_helpers.vhdl b/glibc_random_helpers.vhdl index ee89645..04e1d16 100644 --- a/glibc_random_helpers.vhdl +++ b/glibc_random_helpers.vhdl @@ -1,19 +1,19 @@ package glibc_random_helpers is - procedure srand (v : integer); - attribute foreign of srand : procedure is "VHPIDIRECT srand"; + procedure srand (v : integer); + attribute foreign of srand : procedure is "VHPIDIRECT srand"; - function random return integer; - attribute foreign of random : function is "VHPIDIRECT random"; + function random return integer; + attribute foreign of random : function is "VHPIDIRECT random"; end glibc_random_helpers; package body glibc_random_helpers is - procedure srand (v : integer) is - begin - assert false severity failure; - end srand; + procedure srand (v : integer) is + begin + assert false severity failure; + end srand; - function random return integer is - begin - assert false severity failure; - end random; + function random return integer is + begin + assert false severity failure; + end random; end glibc_random_helpers; diff --git a/multiply_tb.vhdl b/multiply_tb.vhdl index ee448a0..95c3199 100644 --- a/multiply_tb.vhdl +++ b/multiply_tb.vhdl @@ -12,252 +12,252 @@ entity multiply_tb is end multiply_tb; architecture behave of multiply_tb is - signal clk : std_ulogic; - constant clk_period : time := 10 ns; + signal clk : std_ulogic; + constant clk_period : time := 10 ns; - constant pipeline_depth: integer := 4; + constant pipeline_depth : integer := 4; - signal m1 : Decode2ToMultiplyType; - signal m2 : MultiplyToWritebackType; + signal m1 : Decode2ToMultiplyType; + signal m2 : MultiplyToWritebackType; begin - multiply_0: entity work.multiply - generic map (PIPELINE_DEPTH => pipeline_depth) - port map (clk => clk, m_in => m1, m_out => m2); + multiply_0: entity work.multiply + generic map (PIPELINE_DEPTH => pipeline_depth) + port map (clk => clk, m_in => m1, m_out => m2); - clk_process: process - begin - clk <= '0'; - wait for clk_period/2; - clk <= '1'; - wait for clk_period/2; - end process; + clk_process: process + begin + clk <= '0'; + wait for clk_period/2; + clk <= '1'; + wait for clk_period/2; + end process; - stim_process: process - variable ra, rb, rt, behave_rt: std_ulogic_vector(63 downto 0); - variable si: std_ulogic_vector(15 downto 0); - begin - wait for clk_period; + stim_process: process + variable ra, rb, rt, behave_rt: std_ulogic_vector(63 downto 0); + variable si: std_ulogic_vector(15 downto 0); + begin + wait for clk_period; - m1.valid <= '1'; - m1.insn_type <= OP_MUL_L64; - m1.write_reg <= "10001"; - m1.data1 <= '0' & x"0000000000001000"; - m1.data2 <= '0' & x"0000000000001111"; - m1.rc <= '0'; + m1.valid <= '1'; + m1.insn_type <= OP_MUL_L64; + m1.write_reg <= "10001"; + m1.data1 <= '0' & x"0000000000001000"; + m1.data2 <= '0' & x"0000000000001111"; + m1.rc <= '0'; - wait for clk_period; - assert m2.valid = '0'; + wait for clk_period; + assert m2.valid = '0'; - m1.valid <= '0'; + m1.valid <= '0'; - wait for clk_period; - assert m2.valid = '0'; + wait for clk_period; + assert m2.valid = '0'; - wait for clk_period; - assert m2.valid = '0'; + wait for clk_period; + assert m2.valid = '0'; - wait for clk_period; - assert m2.valid = '1'; - assert m2.write_reg_enable = '1'; - assert m2.write_reg_nr = "10001"; - assert m2.write_reg_data = x"0000000001111000"; - assert m2.write_cr_enable = '0'; + wait for clk_period; + assert m2.valid = '1'; + assert m2.write_reg_enable = '1'; + assert m2.write_reg_nr = "10001"; + assert m2.write_reg_data = x"0000000001111000"; + assert m2.write_cr_enable = '0'; - wait for clk_period; - assert m2.valid = '0'; + wait for clk_period; + assert m2.valid = '0'; - m1.valid <= '1'; - m1.rc <= '1'; + m1.valid <= '1'; + m1.rc <= '1'; - wait for clk_period; - assert m2.valid = '0'; + wait for clk_period; + assert m2.valid = '0'; - m1.valid <= '0'; + m1.valid <= '0'; - wait for clk_period * (pipeline_depth-1); - assert m2.valid = '1'; - assert m2.write_reg_enable = '1'; - assert m2.write_reg_nr = "10001"; - assert m2.write_reg_data = x"0000000001111000"; - assert m2.write_cr_enable = '1'; - assert m2.write_cr_data = x"40000000"; + wait for clk_period * (pipeline_depth-1); + assert m2.valid = '1'; + assert m2.write_reg_enable = '1'; + assert m2.write_reg_nr = "10001"; + assert m2.write_reg_data = x"0000000001111000"; + assert m2.write_cr_enable = '1'; + assert m2.write_cr_data = x"40000000"; - -- test mulld - mulld_loop : for i in 0 to 1000 loop - ra := pseudorand(ra'length); - rb := pseudorand(rb'length); + -- test mulld + mulld_loop : for i in 0 to 1000 loop + ra := pseudorand(ra'length); + rb := pseudorand(rb'length); - behave_rt := ppc_mulld(ra, rb); + behave_rt := ppc_mulld(ra, rb); - m1.data1 <= '0' & ra; - m1.data2 <= '0' & rb; - m1.valid <= '1'; - m1.insn_type <= OP_MUL_L64; + m1.data1 <= '0' & ra; + m1.data2 <= '0' & rb; + m1.valid <= '1'; + m1.insn_type <= OP_MUL_L64; - wait for clk_period; + wait for clk_period; - m1.valid <= '0'; + m1.valid <= '0'; - wait for clk_period * (pipeline_depth-1); + wait for clk_period * (pipeline_depth-1); - assert m2.valid = '1'; + assert m2.valid = '1'; - assert to_hstring(behave_rt) = to_hstring(m2.write_reg_data) - report "bad mulld expected " & to_hstring(behave_rt) & " got " & to_hstring(m2.write_reg_data); - end loop; + assert to_hstring(behave_rt) = to_hstring(m2.write_reg_data) + report "bad mulld expected " & to_hstring(behave_rt) & " got " & to_hstring(m2.write_reg_data); + end loop; - -- test mulhdu - mulhdu_loop : for i in 0 to 1000 loop - ra := pseudorand(ra'length); - rb := pseudorand(rb'length); + -- test mulhdu + mulhdu_loop : for i in 0 to 1000 loop + ra := pseudorand(ra'length); + rb := pseudorand(rb'length); - behave_rt := ppc_mulhdu(ra, rb); + behave_rt := ppc_mulhdu(ra, rb); - m1.data1 <= '0' & ra; - m1.data2 <= '0' & rb; - m1.valid <= '1'; - m1.insn_type <= OP_MUL_H64; + m1.data1 <= '0' & ra; + m1.data2 <= '0' & rb; + m1.valid <= '1'; + m1.insn_type <= OP_MUL_H64; - wait for clk_period; + wait for clk_period; - m1.valid <= '0'; + m1.valid <= '0'; - wait for clk_period * (pipeline_depth-1); + wait for clk_period * (pipeline_depth-1); - assert m2.valid = '1'; + assert m2.valid = '1'; - assert to_hstring(behave_rt) = to_hstring(m2.write_reg_data) - report "bad mulhdu expected " & to_hstring(behave_rt) & " got " & to_hstring(m2.write_reg_data); - end loop; + assert to_hstring(behave_rt) = to_hstring(m2.write_reg_data) + report "bad mulhdu expected " & to_hstring(behave_rt) & " got " & to_hstring(m2.write_reg_data); + end loop; - -- test mulhd - mulhd_loop : for i in 0 to 1000 loop - ra := pseudorand(ra'length); - rb := pseudorand(rb'length); + -- test mulhd + mulhd_loop : for i in 0 to 1000 loop + ra := pseudorand(ra'length); + rb := pseudorand(rb'length); - behave_rt := ppc_mulhd(ra, rb); + behave_rt := ppc_mulhd(ra, rb); - m1.data1 <= ra(63) & ra; - m1.data2 <= rb(63) & rb; - m1.valid <= '1'; - m1.insn_type <= OP_MUL_H64; + m1.data1 <= ra(63) & ra; + m1.data2 <= rb(63) & rb; + m1.valid <= '1'; + m1.insn_type <= OP_MUL_H64; - wait for clk_period; + wait for clk_period; - m1.valid <= '0'; + m1.valid <= '0'; - wait for clk_period * (pipeline_depth-1); + wait for clk_period * (pipeline_depth-1); - assert m2.valid = '1'; + assert m2.valid = '1'; - assert to_hstring(behave_rt) = to_hstring(m2.write_reg_data) - report "bad mulhd expected " & to_hstring(behave_rt) & " got " & to_hstring(m2.write_reg_data); - end loop; + assert to_hstring(behave_rt) = to_hstring(m2.write_reg_data) + report "bad mulhd expected " & to_hstring(behave_rt) & " got " & to_hstring(m2.write_reg_data); + end loop; - -- test mullw - mullw_loop : for i in 0 to 1000 loop - ra := pseudorand(ra'length); - rb := pseudorand(rb'length); + -- test mullw + mullw_loop : for i in 0 to 1000 loop + ra := pseudorand(ra'length); + rb := pseudorand(rb'length); - behave_rt := ppc_mullw(ra, rb); + behave_rt := ppc_mullw(ra, rb); - m1.data1 <= (others => ra(31)); - m1.data1(31 downto 0) <= ra(31 downto 0); - m1.data2 <= (others => rb(31)); - m1.data2(31 downto 0) <= rb(31 downto 0); - m1.valid <= '1'; - m1.insn_type <= OP_MUL_L64; + m1.data1 <= (others => ra(31)); + m1.data1(31 downto 0) <= ra(31 downto 0); + m1.data2 <= (others => rb(31)); + m1.data2(31 downto 0) <= rb(31 downto 0); + m1.valid <= '1'; + m1.insn_type <= OP_MUL_L64; - wait for clk_period; + wait for clk_period; - m1.valid <= '0'; + m1.valid <= '0'; - wait for clk_period * (pipeline_depth-1); + wait for clk_period * (pipeline_depth-1); - assert m2.valid = '1'; + assert m2.valid = '1'; - assert to_hstring(behave_rt) = to_hstring(m2.write_reg_data) - report "bad mullw expected " & to_hstring(behave_rt) & " got " & to_hstring(m2.write_reg_data); - end loop; + assert to_hstring(behave_rt) = to_hstring(m2.write_reg_data) + report "bad mullw expected " & to_hstring(behave_rt) & " got " & to_hstring(m2.write_reg_data); + end loop; - -- test mulhw - mulhw_loop : for i in 0 to 1000 loop - ra := pseudorand(ra'length); - rb := pseudorand(rb'length); + -- test mulhw + mulhw_loop : for i in 0 to 1000 loop + ra := pseudorand(ra'length); + rb := pseudorand(rb'length); - behave_rt := ppc_mulhw(ra, rb); + behave_rt := ppc_mulhw(ra, rb); - m1.data1 <= (others => ra(31)); - m1.data1(31 downto 0) <= ra(31 downto 0); - m1.data2 <= (others => rb(31)); - m1.data2(31 downto 0) <= rb(31 downto 0); - m1.valid <= '1'; - m1.insn_type <= OP_MUL_H32; + m1.data1 <= (others => ra(31)); + m1.data1(31 downto 0) <= ra(31 downto 0); + m1.data2 <= (others => rb(31)); + m1.data2(31 downto 0) <= rb(31 downto 0); + m1.valid <= '1'; + m1.insn_type <= OP_MUL_H32; - wait for clk_period; + wait for clk_period; - m1.valid <= '0'; + m1.valid <= '0'; - wait for clk_period * (pipeline_depth-1); + wait for clk_period * (pipeline_depth-1); - assert m2.valid = '1'; + assert m2.valid = '1'; - assert to_hstring(behave_rt) = to_hstring(m2.write_reg_data) - report "bad mulhw expected " & to_hstring(behave_rt) & " got " & to_hstring(m2.write_reg_data); - end loop; + assert to_hstring(behave_rt) = to_hstring(m2.write_reg_data) + report "bad mulhw expected " & to_hstring(behave_rt) & " got " & to_hstring(m2.write_reg_data); + end loop; - -- test mulhwu - mulhwu_loop : for i in 0 to 1000 loop - ra := pseudorand(ra'length); - rb := pseudorand(rb'length); + -- test mulhwu + mulhwu_loop : for i in 0 to 1000 loop + ra := pseudorand(ra'length); + rb := pseudorand(rb'length); - behave_rt := ppc_mulhwu(ra, rb); + behave_rt := ppc_mulhwu(ra, rb); - m1.data1 <= (others => '0'); - m1.data1(31 downto 0) <= ra(31 downto 0); - m1.data2 <= (others => '0'); - m1.data2(31 downto 0) <= rb(31 downto 0); - m1.valid <= '1'; - m1.insn_type <= OP_MUL_H32; + m1.data1 <= (others => '0'); + m1.data1(31 downto 0) <= ra(31 downto 0); + m1.data2 <= (others => '0'); + m1.data2(31 downto 0) <= rb(31 downto 0); + m1.valid <= '1'; + m1.insn_type <= OP_MUL_H32; - wait for clk_period; + wait for clk_period; - m1.valid <= '0'; + m1.valid <= '0'; - wait for clk_period * (pipeline_depth-1); + wait for clk_period * (pipeline_depth-1); - assert m2.valid = '1'; + assert m2.valid = '1'; - assert to_hstring(behave_rt) = to_hstring(m2.write_reg_data) - report "bad mulhwu expected " & to_hstring(behave_rt) & " got " & to_hstring(m2.write_reg_data); - end loop; + assert to_hstring(behave_rt) = to_hstring(m2.write_reg_data) + report "bad mulhwu expected " & to_hstring(behave_rt) & " got " & to_hstring(m2.write_reg_data); + end loop; - -- test mulli - mulli_loop : for i in 0 to 1000 loop - ra := pseudorand(ra'length); - si := pseudorand(si'length); + -- test mulli + mulli_loop : for i in 0 to 1000 loop + ra := pseudorand(ra'length); + si := pseudorand(si'length); - behave_rt := ppc_mulli(ra, si); + behave_rt := ppc_mulli(ra, si); - m1.data1 <= ra(63) & ra; - m1.data2 <= (others => si(15)); - m1.data2(15 downto 0) <= si; - m1.valid <= '1'; - m1.insn_type <= OP_MUL_L64; + m1.data1 <= ra(63) & ra; + m1.data2 <= (others => si(15)); + m1.data2(15 downto 0) <= si; + m1.valid <= '1'; + m1.insn_type <= OP_MUL_L64; - wait for clk_period; + wait for clk_period; - m1.valid <= '0'; + m1.valid <= '0'; - wait for clk_period * (pipeline_depth-1); + wait for clk_period * (pipeline_depth-1); - assert m2.valid = '1'; + assert m2.valid = '1'; - assert to_hstring(behave_rt) = to_hstring(m2.write_reg_data) - report "bad mulli expected " & to_hstring(behave_rt) & " got " & to_hstring(m2.write_reg_data); - end loop; + assert to_hstring(behave_rt) = to_hstring(m2.write_reg_data) + report "bad mulli expected " & to_hstring(behave_rt) & " got " & to_hstring(m2.write_reg_data); + end loop; - assert false report "end of test" severity failure; - wait; - end process; + assert false report "end of test" severity failure; + wait; + end process; end behave; diff --git a/register_file.vhdl b/register_file.vhdl index bc6ef1c..65ecefd 100644 --- a/register_file.vhdl +++ b/register_file.vhdl @@ -6,64 +6,64 @@ library work; use work.common.all; entity register_file is - port( - clk : in std_logic; + port( + clk : in std_logic; - d_in : in Decode2ToRegisterFileType; - d_out : out RegisterFileToDecode2Type; + d_in : in Decode2ToRegisterFileType; + d_out : out RegisterFileToDecode2Type; - w_in : in WritebackToRegisterFileType; + w_in : in WritebackToRegisterFileType; - -- debug - registers_out : out regfile - ); + -- debug + registers_out : out regfile + ); end entity register_file; architecture behaviour of register_file is - signal registers : regfile := (others => (others => '0')); + signal registers : regfile := (others => (others => '0')); begin - -- synchronous writes - register_write_0: process(clk) - begin - if rising_edge(clk) then - if w_in.write_enable = '1' then - assert not(is_x(w_in.write_data)) and not(is_x(w_in.write_reg)) severity failure; - report "Writing GPR " & to_hstring(w_in.write_reg) & " " & to_hstring(w_in.write_data); - registers(to_integer(unsigned(w_in.write_reg))) <= w_in.write_data; - end if; - end if; - end process register_write_0; + -- synchronous writes + register_write_0: process(clk) + begin + if rising_edge(clk) then + if w_in.write_enable = '1' then + assert not(is_x(w_in.write_data)) and not(is_x(w_in.write_reg)) severity failure; + report "Writing GPR " & to_hstring(w_in.write_reg) & " " & to_hstring(w_in.write_data); + registers(to_integer(unsigned(w_in.write_reg))) <= w_in.write_data; + end if; + end if; + end process register_write_0; - -- asynchronous reads - register_read_0: process(all) - begin - if d_in.read1_enable = '1' then - report "Reading GPR " & to_hstring(d_in.read1_reg) & " " & to_hstring(registers(to_integer(unsigned(d_in.read1_reg)))); - end if; - if d_in.read2_enable = '1' then - report "Reading GPR " & to_hstring(d_in.read2_reg) & " " & to_hstring(registers(to_integer(unsigned(d_in.read2_reg)))); - end if; - if d_in.read3_enable = '1' then - report "Reading GPR " & to_hstring(d_in.read3_reg) & " " & to_hstring(registers(to_integer(unsigned(d_in.read3_reg)))); - end if; - d_out.read1_data <= registers(to_integer(unsigned(d_in.read1_reg))); - d_out.read2_data <= registers(to_integer(unsigned(d_in.read2_reg))); - d_out.read3_data <= registers(to_integer(unsigned(d_in.read3_reg))); + -- asynchronous reads + register_read_0: process(all) + begin + if d_in.read1_enable = '1' then + report "Reading GPR " & to_hstring(d_in.read1_reg) & " " & to_hstring(registers(to_integer(unsigned(d_in.read1_reg)))); + end if; + if d_in.read2_enable = '1' then + report "Reading GPR " & to_hstring(d_in.read2_reg) & " " & to_hstring(registers(to_integer(unsigned(d_in.read2_reg)))); + end if; + if d_in.read3_enable = '1' then + report "Reading GPR " & to_hstring(d_in.read3_reg) & " " & to_hstring(registers(to_integer(unsigned(d_in.read3_reg)))); + end if; + d_out.read1_data <= registers(to_integer(unsigned(d_in.read1_reg))); + d_out.read2_data <= registers(to_integer(unsigned(d_in.read2_reg))); + d_out.read3_data <= registers(to_integer(unsigned(d_in.read3_reg))); - -- Forward any written data - if w_in.write_enable = '1' then - if d_in.read1_reg = w_in.write_reg then - d_out.read1_data <= w_in.write_data; - end if; - if d_in.read2_reg = w_in.write_reg then - d_out.read2_data <= w_in.write_data; - end if; - if d_in.read3_reg = w_in.write_reg then - d_out.read3_data <= w_in.write_data; - end if; - end if; - end process register_read_0; + -- Forward any written data + if w_in.write_enable = '1' then + if d_in.read1_reg = w_in.write_reg then + d_out.read1_data <= w_in.write_data; + end if; + if d_in.read2_reg = w_in.write_reg then + d_out.read2_data <= w_in.write_data; + end if; + if d_in.read3_reg = w_in.write_reg then + d_out.read3_data <= w_in.write_data; + end if; + end if; + end process register_read_0; - -- debug - registers_out <= registers; + -- debug + registers_out <= registers; end architecture behaviour; diff --git a/sim_console.vhdl b/sim_console.vhdl index 2f431bf..1bc52b7 100644 --- a/sim_console.vhdl +++ b/sim_console.vhdl @@ -2,29 +2,29 @@ library ieee; use ieee.std_logic_1164.all; package sim_console is - procedure sim_console_read (val: out std_ulogic_vector(63 downto 0)); - attribute foreign of sim_console_read : procedure is "VHPIDIRECT sim_console_read"; + procedure sim_console_read (val: out std_ulogic_vector(63 downto 0)); + attribute foreign of sim_console_read : procedure is "VHPIDIRECT sim_console_read"; - procedure sim_console_poll (val: out std_ulogic_vector(63 downto 0)); - attribute foreign of sim_console_poll : procedure is "VHPIDIRECT sim_console_poll"; + procedure sim_console_poll (val: out std_ulogic_vector(63 downto 0)); + attribute foreign of sim_console_poll : procedure is "VHPIDIRECT sim_console_poll"; - procedure sim_console_write (val: std_ulogic_vector(63 downto 0)); - attribute foreign of sim_console_write : procedure is "VHPIDIRECT sim_console_write"; + procedure sim_console_write (val: std_ulogic_vector(63 downto 0)); + attribute foreign of sim_console_write : procedure is "VHPIDIRECT sim_console_write"; end sim_console; package body sim_console is - procedure sim_console_read (val: out std_ulogic_vector(63 downto 0)) is - begin - assert false report "VHPI" severity failure; - end sim_console_read; + procedure sim_console_read (val: out std_ulogic_vector(63 downto 0)) is + begin + assert false report "VHPI" severity failure; + end sim_console_read; - procedure sim_console_poll (val: out std_ulogic_vector(63 downto 0)) is - begin - assert false report "VHPI" severity failure; - end sim_console_poll; + procedure sim_console_poll (val: out std_ulogic_vector(63 downto 0)) is + begin + assert false report "VHPI" severity failure; + end sim_console_poll; - procedure sim_console_write (val: std_ulogic_vector(63 downto 0)) is - begin - assert false report "VHPI" severity failure; - end sim_console_write; + procedure sim_console_write (val: std_ulogic_vector(63 downto 0)) is + begin + assert false report "VHPI" severity failure; + end sim_console_write; end sim_console; diff --git a/simple_ram_behavioural.vhdl b/simple_ram_behavioural.vhdl index 2ccee79..afc3d51 100644 --- a/simple_ram_behavioural.vhdl +++ b/simple_ram_behavioural.vhdl @@ -8,70 +8,70 @@ use work.wishbone_types.all; use work.simple_ram_behavioural_helpers.all; entity mw_soc_memory is - generic ( - RAM_INIT_FILE : string; - MEMORY_SIZE : integer - ); + generic ( + RAM_INIT_FILE : string; + MEMORY_SIZE : integer + ); - port ( - clk : in std_ulogic; - rst : in std_ulogic; + port ( + clk : in std_ulogic; + rst : in std_ulogic; - wishbone_in : in wishbone_master_out; - wishbone_out : out wishbone_slave_out - ); + wishbone_in : in wishbone_master_out; + wishbone_out : out wishbone_slave_out + ); end mw_soc_memory; architecture behave of mw_soc_memory is - type wishbone_state_t is (IDLE, ACK); + type wishbone_state_t is (IDLE, ACK); - signal state : wishbone_state_t := IDLE; - signal ret_ack : std_ulogic := '0'; - signal identifier : integer := behavioural_initialize(filename => RAM_INIT_FILE, size => MEMORY_SIZE); - signal reload : integer := 0; + signal state : wishbone_state_t := IDLE; + signal ret_ack : std_ulogic := '0'; + signal identifier : integer := behavioural_initialize(filename => RAM_INIT_FILE, size => MEMORY_SIZE); + signal reload : integer := 0; begin - wishbone_process: process(clk) - variable ret_dat: std_ulogic_vector(63 downto 0) := (others => '0'); - begin - wishbone_out.ack <= ret_ack and wishbone_in.cyc and wishbone_in.stb; - wishbone_out.dat <= ret_dat; + wishbone_process: process(clk) + variable ret_dat: std_ulogic_vector(63 downto 0) := (others => '0'); + begin + wishbone_out.ack <= ret_ack and wishbone_in.cyc and wishbone_in.stb; + wishbone_out.dat <= ret_dat; - if rising_edge(clk) then - if rst = '1' then - state <= IDLE; - ret_ack <= '0'; - else - ret_dat := x"FFFFFFFFFFFFFFFF"; + if rising_edge(clk) then + if rst = '1' then + state <= IDLE; + ret_ack <= '0'; + else + ret_dat := x"FFFFFFFFFFFFFFFF"; - -- Active - if wishbone_in.cyc = '1' then - case state is - when IDLE => - if wishbone_in.stb = '1' then - -- write - if wishbone_in.we = '1' then - assert not(is_x(wishbone_in.dat)) and not(is_x(wishbone_in.adr)) severity failure; - report "RAM writing " & to_hstring(wishbone_in.dat) & " to " & to_hstring(wishbone_in.adr); - behavioural_write(wishbone_in.dat, wishbone_in.adr, to_integer(unsigned(wishbone_in.sel)), identifier); - reload <= reload + 1; - ret_ack <= '1'; - state <= ACK; - else - behavioural_read(ret_dat, wishbone_in.adr, to_integer(unsigned(wishbone_in.sel)), identifier, reload); - report "RAM reading from " & to_hstring(wishbone_in.adr) & " returns " & to_hstring(ret_dat); - ret_ack <= '1'; - state <= ACK; - end if; - end if; - when ACK => - ret_ack <= '0'; - state <= IDLE; - end case; - else - ret_ack <= '0'; - state <= IDLE; - end if; - end if; - end if; - end process; + -- Active + if wishbone_in.cyc = '1' then + case state is + when IDLE => + if wishbone_in.stb = '1' then + -- write + if wishbone_in.we = '1' then + assert not(is_x(wishbone_in.dat)) and not(is_x(wishbone_in.adr)) severity failure; + report "RAM writing " & to_hstring(wishbone_in.dat) & " to " & to_hstring(wishbone_in.adr); + behavioural_write(wishbone_in.dat, wishbone_in.adr, to_integer(unsigned(wishbone_in.sel)), identifier); + reload <= reload + 1; + ret_ack <= '1'; + state <= ACK; + else + behavioural_read(ret_dat, wishbone_in.adr, to_integer(unsigned(wishbone_in.sel)), identifier, reload); + report "RAM reading from " & to_hstring(wishbone_in.adr) & " returns " & to_hstring(ret_dat); + ret_ack <= '1'; + state <= ACK; + end if; + end if; + when ACK => + ret_ack <= '0'; + state <= IDLE; + end case; + else + ret_ack <= '0'; + state <= IDLE; + end if; + end if; + end if; + end process; end behave; diff --git a/simple_ram_behavioural_helpers.vhdl b/simple_ram_behavioural_helpers.vhdl index 8540fa0..507594f 100644 --- a/simple_ram_behavioural_helpers.vhdl +++ b/simple_ram_behavioural_helpers.vhdl @@ -2,29 +2,29 @@ library ieee; use ieee.std_logic_1164.all; package simple_ram_behavioural_helpers is - function behavioural_initialize (filename: String; size: integer) return integer; - attribute foreign of behavioural_initialize : function is "VHPIDIRECT behavioural_initialize"; + function behavioural_initialize (filename: String; size: integer) return integer; + attribute foreign of behavioural_initialize : function is "VHPIDIRECT behavioural_initialize"; - procedure behavioural_read (val: out std_ulogic_vector(63 downto 0); addr: std_ulogic_vector(63 downto 0); length: integer; identifier: integer; reload: integer); - attribute foreign of behavioural_read : procedure is "VHPIDIRECT behavioural_read"; + procedure behavioural_read (val: out std_ulogic_vector(63 downto 0); addr: std_ulogic_vector(63 downto 0); length: integer; identifier: integer; reload: integer); + attribute foreign of behavioural_read : procedure is "VHPIDIRECT behavioural_read"; - procedure behavioural_write (val: std_ulogic_vector(63 downto 0); addr: std_ulogic_vector(63 downto 0); length: integer; identifier: integer); - attribute foreign of behavioural_write : procedure is "VHPIDIRECT behavioural_write"; + procedure behavioural_write (val: std_ulogic_vector(63 downto 0); addr: std_ulogic_vector(63 downto 0); length: integer; identifier: integer); + attribute foreign of behavioural_write : procedure is "VHPIDIRECT behavioural_write"; end simple_ram_behavioural_helpers; package body simple_ram_behavioural_helpers is - function behavioural_initialize (filename: String; size: integer) return integer is - begin - assert false report "VHPI" severity failure; - end behavioural_initialize; + function behavioural_initialize (filename: String; size: integer) return integer is + begin + assert false report "VHPI" severity failure; + end behavioural_initialize; - procedure behavioural_read (val: out std_ulogic_vector(63 downto 0); addr: std_ulogic_vector(63 downto 0); length: integer; identifier: integer; reload: integer) is - begin - assert false report "VHPI" severity failure; - end behavioural_read; + procedure behavioural_read (val: out std_ulogic_vector(63 downto 0); addr: std_ulogic_vector(63 downto 0); length: integer; identifier: integer; reload: integer) is + begin + assert false report "VHPI" severity failure; + end behavioural_read; - procedure behavioural_write (val: std_ulogic_vector(63 downto 0); addr: std_ulogic_vector(63 downto 0); length: integer; identifier: integer) is - begin - assert false report "VHPI" severity failure; - end behavioural_write; + procedure behavioural_write (val: std_ulogic_vector(63 downto 0); addr: std_ulogic_vector(63 downto 0); length: integer; identifier: integer) is + begin + assert false report "VHPI" severity failure; + end behavioural_write; end simple_ram_behavioural_helpers; diff --git a/simple_ram_behavioural_tb.vhdl b/simple_ram_behavioural_tb.vhdl index 9523cd1..1527801 100644 --- a/simple_ram_behavioural_tb.vhdl +++ b/simple_ram_behavioural_tb.vhdl @@ -9,225 +9,233 @@ entity simple_ram_behavioural_tb is end simple_ram_behavioural_tb; architecture behave of simple_ram_behavioural_tb is - signal clk : std_ulogic; - signal rst : std_ulogic := '1'; + signal clk : std_ulogic; + signal rst : std_ulogic := '1'; - constant clk_period : time := 10 ns; + constant clk_period : time := 10 ns; - signal w_in : wishbone_slave_out; - signal w_out : wishbone_master_out; + signal w_in : wishbone_slave_out; + signal w_out : wishbone_master_out; begin - simple_ram_0: entity work.mw_soc_memory - generic map ( RAM_INIT_FILE => "simple_ram_behavioural_tb.bin", MEMORY_SIZE => 16 ) - port map (clk => clk, rst => rst, wishbone_out => w_in, wishbone_in => w_out); - - clock: process - begin - clk <= '1'; - wait for clk_period / 2; - clk <= '0'; - wait for clk_period / 2; - end process clock; - - stim: process - begin - w_out.adr <= (others => '0'); - w_out.dat <= (others => '0'); - w_out.cyc <= '0'; - w_out.stb <= '0'; - w_out.sel <= (others => '0'); - w_out.we <= '0'; - - wait for clk_period; - rst <= '0'; - - wait for clk_period; - - w_out.cyc <= '1'; - - -- test various read lengths and alignments - w_out.stb <= '1'; - w_out.sel <= "00000001"; - w_out.adr <= x"0000000000000000"; - assert w_in.ack = '0'; - wait for clk_period; - assert w_in.ack = '1'; - assert w_in.dat(7 downto 0) = x"00" report to_hstring(w_in.dat); - w_out.stb <= '0'; - wait for clk_period; - assert w_in.ack = '0'; - - w_out.stb <= '1'; - w_out.sel <= "00000001"; - w_out.adr <= x"0000000000000001"; - assert w_in.ack = '0'; - wait for clk_period; - assert w_in.ack = '1'; - assert w_in.dat(7 downto 0) = x"01" report to_hstring(w_in.dat); - w_out.stb <= '0'; - wait for clk_period; - assert w_in.ack = '0'; - - w_out.stb <= '1'; - w_out.sel <= "00000001"; - w_out.adr <= x"0000000000000007"; - assert w_in.ack = '0'; - wait for clk_period; - assert w_in.ack = '1'; - assert w_in.dat(7 downto 0) = x"07" report to_hstring(w_in.dat); - w_out.stb <= '0'; - wait for clk_period; - assert w_in.ack = '0'; - - w_out.stb <= '1'; - w_out.sel <= "00000011"; - w_out.adr <= x"0000000000000000"; - assert w_in.ack = '0'; - wait for clk_period; - assert w_in.ack = '1'; - assert w_in.dat(15 downto 0) = x"0100" report to_hstring(w_in.dat); - w_out.stb <= '0'; - wait for clk_period; - assert w_in.ack = '0'; - - w_out.stb <= '1'; - w_out.sel <= "00000011"; - w_out.adr <= x"0000000000000001"; - assert w_in.ack = '0'; - wait for clk_period; - assert w_in.ack = '1'; - assert w_in.dat(15 downto 0) = x"0201" report to_hstring(w_in.dat); - w_out.stb <= '0'; - wait for clk_period; - assert w_in.ack = '0'; - - w_out.stb <= '1'; - w_out.sel <= "00000011"; - w_out.adr <= x"0000000000000007"; - assert w_in.ack = '0'; - wait for clk_period; - assert w_in.ack = '1'; - assert w_in.dat(15 downto 0) = x"0807" report to_hstring(w_in.dat); - w_out.stb <= '0'; - wait for clk_period; - assert w_in.ack = '0'; - - w_out.stb <= '1'; - w_out.sel <= "00001111"; - w_out.adr <= x"0000000000000000"; - assert w_in.ack = '0'; - wait for clk_period; - assert w_in.ack = '1'; - assert w_in.dat(31 downto 0) = x"03020100" report to_hstring(w_in.dat); - w_out.stb <= '0'; - wait for clk_period; - assert w_in.ack = '0'; - - w_out.stb <= '1'; - w_out.sel <= "00001111"; - w_out.adr <= x"0000000000000001"; - assert w_in.ack = '0'; - wait for clk_period; - assert w_in.ack = '1'; - assert w_in.dat(31 downto 0) = x"04030201" report to_hstring(w_in.dat); - w_out.stb <= '0'; - wait for clk_period; - assert w_in.ack = '0'; - - w_out.stb <= '1'; - w_out.sel <= "00001111"; - w_out.adr <= x"0000000000000007"; - assert w_in.ack = '0'; - wait for clk_period; - assert w_in.ack = '1'; - assert w_in.dat(31 downto 0) = x"0A090807" report to_hstring(w_in.dat); - w_out.stb <= '0'; - wait for clk_period; - assert w_in.ack = '0'; - - w_out.stb <= '1'; - w_out.sel <= "11111111"; - w_out.adr <= x"0000000000000000"; - assert w_in.ack = '0'; - wait for clk_period; - assert w_in.ack = '1'; - assert w_in.dat(63 downto 0) = x"0706050403020100" report to_hstring(w_in.dat); - w_out.stb <= '0'; - wait for clk_period; - assert w_in.ack = '0'; - - w_out.stb <= '1'; - w_out.sel <= "11111111"; - w_out.adr <= x"0000000000000001"; - assert w_in.ack = '0'; - wait for clk_period; - assert w_in.ack = '1'; - assert w_in.dat(63 downto 0) = x"0807060504030201" report to_hstring(w_in.dat); - w_out.stb <= '0'; - wait for clk_period; - assert w_in.ack = '0'; - - w_out.stb <= '1'; - w_out.sel <= "11111111"; - w_out.adr <= x"0000000000000007"; - assert w_in.ack = '0'; - wait for clk_period; - assert w_in.ack = '1'; - assert w_in.dat(63 downto 0) = x"0E0D0C0B0A090807" report to_hstring(w_in.dat); - w_out.stb <= '0'; - wait for clk_period; - assert w_in.ack = '0'; - - -- test various write lengths and alignments - w_out.stb <= '1'; - w_out.sel <= "00000001"; - w_out.adr <= x"0000000000000000"; - w_out.we <= '1'; - w_out.dat(7 downto 0) <= x"0F"; - assert w_in.ack = '0'; - wait for clk_period; - assert w_in.ack = '1'; - w_out.stb <= '0'; - wait for clk_period; - assert w_in.ack = '0'; - - w_out.stb <= '1'; - w_out.sel <= "00000001"; - w_out.adr <= x"0000000000000000"; - w_out.we <= '0'; - assert w_in.ack = '0'; - wait for clk_period; - assert w_in.ack = '1'; - assert w_in.dat(7 downto 0) = x"0F" report to_hstring(w_in.dat); - w_out.stb <= '0'; - wait for clk_period; - assert w_in.ack = '0'; - - w_out.stb <= '1'; - w_out.sel <= "11111111"; - w_out.adr <= x"0000000000000007"; - w_out.we <= '1'; - w_out.dat <= x"BADC0FFEBADC0FFE"; - assert w_in.ack = '0'; - wait for clk_period; - assert w_in.ack = '1'; - w_out.stb <= '0'; - wait for clk_period; - assert w_in.ack = '0'; - - w_out.stb <= '1'; - w_out.sel <= "11111111"; - w_out.adr <= x"0000000000000007"; - w_out.we <= '0'; - assert w_in.ack = '0'; - wait for clk_period; - assert w_in.ack = '1'; - assert w_in.dat = x"BADC0FFEBADC0FFE" report to_hstring(w_in.dat); - w_out.stb <= '0'; - wait for clk_period; - assert w_in.ack = '0'; - - assert false report "end of test" severity failure; - wait; - end process; + simple_ram_0: entity work.mw_soc_memory + generic map ( + RAM_INIT_FILE => "simple_ram_behavioural_tb.bin", + MEMORY_SIZE => 16 + ) + port map ( + clk => clk, + rst => rst, + wishbone_out => w_in, + wishbone_in => w_out + ); + + clock: process + begin + clk <= '1'; + wait for clk_period / 2; + clk <= '0'; + wait for clk_period / 2; + end process clock; + + stim: process + begin + w_out.adr <= (others => '0'); + w_out.dat <= (others => '0'); + w_out.cyc <= '0'; + w_out.stb <= '0'; + w_out.sel <= (others => '0'); + w_out.we <= '0'; + + wait for clk_period; + rst <= '0'; + + wait for clk_period; + + w_out.cyc <= '1'; + + -- test various read lengths and alignments + w_out.stb <= '1'; + w_out.sel <= "00000001"; + w_out.adr <= x"0000000000000000"; + assert w_in.ack = '0'; + wait for clk_period; + assert w_in.ack = '1'; + assert w_in.dat(7 downto 0) = x"00" report to_hstring(w_in.dat); + w_out.stb <= '0'; + wait for clk_period; + assert w_in.ack = '0'; + + w_out.stb <= '1'; + w_out.sel <= "00000001"; + w_out.adr <= x"0000000000000001"; + assert w_in.ack = '0'; + wait for clk_period; + assert w_in.ack = '1'; + assert w_in.dat(7 downto 0) = x"01" report to_hstring(w_in.dat); + w_out.stb <= '0'; + wait for clk_period; + assert w_in.ack = '0'; + + w_out.stb <= '1'; + w_out.sel <= "00000001"; + w_out.adr <= x"0000000000000007"; + assert w_in.ack = '0'; + wait for clk_period; + assert w_in.ack = '1'; + assert w_in.dat(7 downto 0) = x"07" report to_hstring(w_in.dat); + w_out.stb <= '0'; + wait for clk_period; + assert w_in.ack = '0'; + + w_out.stb <= '1'; + w_out.sel <= "00000011"; + w_out.adr <= x"0000000000000000"; + assert w_in.ack = '0'; + wait for clk_period; + assert w_in.ack = '1'; + assert w_in.dat(15 downto 0) = x"0100" report to_hstring(w_in.dat); + w_out.stb <= '0'; + wait for clk_period; + assert w_in.ack = '0'; + + w_out.stb <= '1'; + w_out.sel <= "00000011"; + w_out.adr <= x"0000000000000001"; + assert w_in.ack = '0'; + wait for clk_period; + assert w_in.ack = '1'; + assert w_in.dat(15 downto 0) = x"0201" report to_hstring(w_in.dat); + w_out.stb <= '0'; + wait for clk_period; + assert w_in.ack = '0'; + + w_out.stb <= '1'; + w_out.sel <= "00000011"; + w_out.adr <= x"0000000000000007"; + assert w_in.ack = '0'; + wait for clk_period; + assert w_in.ack = '1'; + assert w_in.dat(15 downto 0) = x"0807" report to_hstring(w_in.dat); + w_out.stb <= '0'; + wait for clk_period; + assert w_in.ack = '0'; + + w_out.stb <= '1'; + w_out.sel <= "00001111"; + w_out.adr <= x"0000000000000000"; + assert w_in.ack = '0'; + wait for clk_period; + assert w_in.ack = '1'; + assert w_in.dat(31 downto 0) = x"03020100" report to_hstring(w_in.dat); + w_out.stb <= '0'; + wait for clk_period; + assert w_in.ack = '0'; + + w_out.stb <= '1'; + w_out.sel <= "00001111"; + w_out.adr <= x"0000000000000001"; + assert w_in.ack = '0'; + wait for clk_period; + assert w_in.ack = '1'; + assert w_in.dat(31 downto 0) = x"04030201" report to_hstring(w_in.dat); + w_out.stb <= '0'; + wait for clk_period; + assert w_in.ack = '0'; + + w_out.stb <= '1'; + w_out.sel <= "00001111"; + w_out.adr <= x"0000000000000007"; + assert w_in.ack = '0'; + wait for clk_period; + assert w_in.ack = '1'; + assert w_in.dat(31 downto 0) = x"0A090807" report to_hstring(w_in.dat); + w_out.stb <= '0'; + wait for clk_period; + assert w_in.ack = '0'; + + w_out.stb <= '1'; + w_out.sel <= "11111111"; + w_out.adr <= x"0000000000000000"; + assert w_in.ack = '0'; + wait for clk_period; + assert w_in.ack = '1'; + assert w_in.dat(63 downto 0) = x"0706050403020100" report to_hstring(w_in.dat); + w_out.stb <= '0'; + wait for clk_period; + assert w_in.ack = '0'; + + w_out.stb <= '1'; + w_out.sel <= "11111111"; + w_out.adr <= x"0000000000000001"; + assert w_in.ack = '0'; + wait for clk_period; + assert w_in.ack = '1'; + assert w_in.dat(63 downto 0) = x"0807060504030201" report to_hstring(w_in.dat); + w_out.stb <= '0'; + wait for clk_period; + assert w_in.ack = '0'; + + w_out.stb <= '1'; + w_out.sel <= "11111111"; + w_out.adr <= x"0000000000000007"; + assert w_in.ack = '0'; + wait for clk_period; + assert w_in.ack = '1'; + assert w_in.dat(63 downto 0) = x"0E0D0C0B0A090807" report to_hstring(w_in.dat); + w_out.stb <= '0'; + wait for clk_period; + assert w_in.ack = '0'; + + -- test various write lengths and alignments + w_out.stb <= '1'; + w_out.sel <= "00000001"; + w_out.adr <= x"0000000000000000"; + w_out.we <= '1'; + w_out.dat(7 downto 0) <= x"0F"; + assert w_in.ack = '0'; + wait for clk_period; + assert w_in.ack = '1'; + w_out.stb <= '0'; + wait for clk_period; + assert w_in.ack = '0'; + + w_out.stb <= '1'; + w_out.sel <= "00000001"; + w_out.adr <= x"0000000000000000"; + w_out.we <= '0'; + assert w_in.ack = '0'; + wait for clk_period; + assert w_in.ack = '1'; + assert w_in.dat(7 downto 0) = x"0F" report to_hstring(w_in.dat); + w_out.stb <= '0'; + wait for clk_period; + assert w_in.ack = '0'; + + w_out.stb <= '1'; + w_out.sel <= "11111111"; + w_out.adr <= x"0000000000000007"; + w_out.we <= '1'; + w_out.dat <= x"BADC0FFEBADC0FFE"; + assert w_in.ack = '0'; + wait for clk_period; + assert w_in.ack = '1'; + w_out.stb <= '0'; + wait for clk_period; + assert w_in.ack = '0'; + + w_out.stb <= '1'; + w_out.sel <= "11111111"; + w_out.adr <= x"0000000000000007"; + w_out.we <= '0'; + assert w_in.ack = '0'; + wait for clk_period; + assert w_in.ack = '1'; + assert w_in.dat = x"BADC0FFEBADC0FFE" report to_hstring(w_in.dat); + w_out.stb <= '0'; + wait for clk_period; + assert w_in.ack = '0'; + + assert false report "end of test" severity failure; + wait; + end process; end behave; diff --git a/wishbone_arbiter.vhdl b/wishbone_arbiter.vhdl index c7d249a..7d5cbcd 100644 --- a/wishbone_arbiter.vhdl +++ b/wishbone_arbiter.vhdl @@ -5,53 +5,53 @@ library work; use work.wishbone_types.all; entity wishbone_arbiter is - port ( - clk : in std_ulogic; - rst : in std_ulogic; + port ( + clk : in std_ulogic; + rst : in std_ulogic; - wb1_in : in wishbone_master_out; - wb1_out : out wishbone_slave_out; + wb1_in : in wishbone_master_out; + wb1_out : out wishbone_slave_out; - wb2_in : in wishbone_master_out; - wb2_out : out wishbone_slave_out; + wb2_in : in wishbone_master_out; + wb2_out : out wishbone_slave_out; - wb_out : out wishbone_master_out; - wb_in : in wishbone_slave_out - ); + wb_out : out wishbone_master_out; + wb_in : in wishbone_slave_out + ); end wishbone_arbiter; architecture behave of wishbone_arbiter is - type wishbone_arbiter_state_t is (IDLE, WB1_BUSY, WB2_BUSY); - signal state : wishbone_arbiter_state_t := IDLE; + type wishbone_arbiter_state_t is (IDLE, WB1_BUSY, WB2_BUSY); + signal state : wishbone_arbiter_state_t := IDLE; begin - wb1_out <= wb_in when state = WB1_BUSY else wishbone_slave_out_init; - wb2_out <= wb_in when state = WB2_BUSY else wishbone_slave_out_init; - - wb_out <= wb1_in when state = WB1_BUSY else wb2_in when state = WB2_BUSY else wishbone_master_out_init; - - wishbone_arbiter_process: process(clk) - begin - if rising_edge(clk) then - if rst = '1' then - state <= IDLE; - else - case state is - when IDLE => - if wb1_in.cyc = '1' then - state <= WB1_BUSY; - elsif wb2_in.cyc = '1' then - state <= WB2_BUSY; - end if; - when WB1_BUSY => - if wb1_in.cyc = '0' then - state <= IDLE; - end if; - when WB2_BUSY => - if wb2_in.cyc = '0' then - state <= IDLE; - end if; - end case; - end if; - end if; - end process; + wb1_out <= wb_in when state = WB1_BUSY else wishbone_slave_out_init; + wb2_out <= wb_in when state = WB2_BUSY else wishbone_slave_out_init; + + wb_out <= wb1_in when state = WB1_BUSY else wb2_in when state = WB2_BUSY else wishbone_master_out_init; + + wishbone_arbiter_process: process(clk) + begin + if rising_edge(clk) then + if rst = '1' then + state <= IDLE; + else + case state is + when IDLE => + if wb1_in.cyc = '1' then + state <= WB1_BUSY; + elsif wb2_in.cyc = '1' then + state <= WB2_BUSY; + end if; + when WB1_BUSY => + if wb1_in.cyc = '0' then + state <= IDLE; + end if; + when WB2_BUSY => + if wb2_in.cyc = '0' then + state <= IDLE; + end if; + end case; + end if; + end if; + end process; end behave; diff --git a/wishbone_types.vhdl b/wishbone_types.vhdl index 6055d9c..3db03aa 100644 --- a/wishbone_types.vhdl +++ b/wishbone_types.vhdl @@ -2,26 +2,26 @@ library ieee; use ieee.std_logic_1164.all; package wishbone_types is - constant wishbone_addr_bits : integer := 64; - constant wishbone_data_bits : integer := 64; + constant wishbone_addr_bits : integer := 64; + constant wishbone_data_bits : integer := 64; - subtype wishbone_addr_type is std_ulogic_vector(wishbone_addr_bits-1 downto 0); - subtype wishbone_data_type is std_ulogic_vector(wishbone_data_bits-1 downto 0); + subtype wishbone_addr_type is std_ulogic_vector(wishbone_addr_bits-1 downto 0); + subtype wishbone_data_type is std_ulogic_vector(wishbone_data_bits-1 downto 0); - type wishbone_master_out is record - adr : wishbone_addr_type; - dat : wishbone_data_type; - cyc : std_ulogic; - stb : std_ulogic; - sel : std_ulogic_vector(7 downto 0); - we : std_ulogic; - end record; - constant wishbone_master_out_init : wishbone_master_out := (cyc => '0', stb => '0', we => '0', others => (others => '0')); + type wishbone_master_out is record + adr : wishbone_addr_type; + dat : wishbone_data_type; + cyc : std_ulogic; + stb : std_ulogic; + sel : std_ulogic_vector(7 downto 0); + we : std_ulogic; + end record; + constant wishbone_master_out_init : wishbone_master_out := (cyc => '0', stb => '0', we => '0', others => (others => '0')); - type wishbone_slave_out is record - dat : wishbone_data_type; - ack : std_ulogic; - end record; - constant wishbone_slave_out_init : wishbone_slave_out := (ack => '0', others => (others => '0')); + type wishbone_slave_out is record + dat : wishbone_data_type; + ack : std_ulogic; + end record; + constant wishbone_slave_out_init : wishbone_slave_out := (ack => '0', others => (others => '0')); end package wishbone_types;