diff --git a/modules/common/Manifest.py b/modules/common/Manifest.py index 75363ef26c606c3256dbc2271108a6682a58e98d..c70c7e906fb083e8cd22a2998d94adcdedc3e582 100644 --- a/modules/common/Manifest.py +++ b/modules/common/Manifest.py @@ -6,5 +6,8 @@ files = [ "gencores_pkg.vhd", "gc_dual_pi_controller.vhd", "gc_serial_dac.vhd", "gc_sync_ffs.vhd", + "gc_arbitrated_mux.vhd", "gc_pulse_synchronizer.vhd", - "gc_frequency_meter.vhd"]; + "gc_frequency_meter.vhd", + "gc_dual_clock_ram.vhd", + "gc_wfifo.vhd"]; diff --git a/modules/common/gc_arbitrated_mux.vhd b/modules/common/gc_arbitrated_mux.vhd new file mode 100644 index 0000000000000000000000000000000000000000..818f654f056aa02fa1638020b7c410dbd783a186 --- /dev/null +++ b/modules/common/gc_arbitrated_mux.vhd @@ -0,0 +1,151 @@ +------------------------------------------------------------------------------- +-- Title : Multiplexer with round-robin arbitration +-- Project : General Cores Collection library +------------------------------------------------------------------------------- +-- File : gc_arbitrated_mux.vhd +-- Author : Tomasz Wlostowski +-- Company : CERN +-- Created : 2011-08-24 +-- Last update: 2012-02-21 +-- Platform : FPGA-generic +-- Standard : VHDL'93 +------------------------------------------------------------------------------- +-- Description: An N-channel time-division multiplexer with round robin +-- arbitration. +------------------------------------------------------------------------------- +-- +-- Copyright (c) 2011 CERN / BE-CO-HT +-- +-- This source file is free software; you can redistribute it +-- and/or modify it under the terms of the GNU Lesser General +-- Public License as published by the Free Software Foundation; +-- either version 2.1 of the License, or (at your option) any +-- later version. +-- +-- This source is distributed in the hope that it will be +-- useful, but WITHOUT ANY WARRANTY; without even the implied +-- warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +-- PURPOSE. See the GNU Lesser General Public License for more +-- details. +-- +-- You should have received a copy of the GNU Lesser General +-- Public License along with this source; if not, download it +-- from http://www.gnu.org/licenses/lgpl-2.1.html +-- +------------------------------------------------------------------------------- +-- Revisions : +-- Date Version Author Description +-- 2011-08-24 1.0 twlostow Created +------------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +use work.gencores_pkg.all; +use work.genram_pkg.all; + +entity gc_arbitrated_mux is + + generic ( + -- number of arbitrated inputs + g_num_inputs : integer; + -- data width + g_width : integer); + + port ( + clk_i : in std_logic; + rst_n_i : in std_logic; + + -- data (all inputs joined together) + d_i : in std_logic_vector(g_num_inputs * g_width-1 downto 0); + -- 1: data word on input N is valid. Can be asserted only if corresponding + -- d_req_o(N) == 1 + d_valid_i : in std_logic_vector(g_num_inputs-1 downto 0); + + -- 1: input N is ready to accept next data word + d_req_o : out std_logic_vector(g_num_inputs-1 downto 0); + + -- Mux output + q_o : out std_logic_vector(g_width-1 downto 0); + -- 1: q_o contains valid data word + q_valid_o : out std_logic; + + -- Index of the input, to which came the currently outputted data word. + q_input_id_o : out std_logic_vector(f_log2_size(g_num_inputs)-1 downto 0) + ); + +end gc_arbitrated_mux; + +architecture rtl of gc_arbitrated_mux is + + function f_onehot_decode + (x : std_logic_vector) return integer is + begin + for i in 0 to x'length-1 loop + if(x(i) = '1') then + return i; + end if; + end loop; -- i + return 0; + end f_onehot_decode; + + + type t_data_array is array(0 to g_num_inputs-1) of std_logic_vector(g_width-1 downto 0); + + signal req_masked, req, grant : std_logic_vector(g_num_inputs-1 downto 0); + signal dregs : t_data_array; + + + +begin -- rtl + + + gen_inputs : for i in 0 to g_num_inputs-1 generate + + p_input_reg : process(clk_i) + begin + if rising_edge(clk_i) then + if rst_n_i = '0' then + req(i) <= '0'; + else + if(grant(i) = '1') then + req(i) <= '0'; + elsif(d_valid_i(i) = '1') then + dregs(i) <= d_i(g_width * (i+1) - 1 downto g_width * i); + req(i) <= '1'; + end if; + end if; + end if; + end process; + + d_req_o(i) <= not req(i); + end generate gen_inputs; + + req_masked <= req and not grant; + p_arbitrate : process(clk_i) + begin + if rising_edge(clk_i) then + if rst_n_i = '0' then + q_valid_o <= '0'; + grant <= (others => '0'); + else + + f_rr_arbitrate(req_masked , grant, grant); + + if(unsigned(grant) /= 0) then + q_o <= dregs(f_onehot_decode(grant)); + q_input_id_o <= std_logic_vector(to_unsigned(f_onehot_decode(grant), f_log2_size(g_num_inputs))); + q_valid_o <= '1'; + else + q_o <= (others => 'X'); + q_input_id_o <= (others => 'X'); + q_valid_o <= '0'; + end if; + end if; + end if; + end process; + +end rtl; + + diff --git a/modules/common/gc_dual_clock_ram.vhd b/modules/common/gc_dual_clock_ram.vhd new file mode 100644 index 0000000000000000000000000000000000000000..1f6e28a8f87d23f629308cf6804959a78b72f0cf --- /dev/null +++ b/modules/common/gc_dual_clock_ram.vhd @@ -0,0 +1,48 @@ +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +-- Read during write has an undefined result +entity gc_dual_clock_ram is + generic( + addr_width : natural := 4; + data_width : natural := 32); + port( + -- write port + w_clk_i : in std_logic; + w_en_i : in std_logic; + w_addr_i : in std_logic_vector(addr_width-1 downto 0); + w_data_i : in std_logic_vector(data_width-1 downto 0); + -- read port + r_clk_i : in std_logic; + r_en_i : in std_logic; + r_addr_i : in std_logic_vector(addr_width-1 downto 0); + r_data_o : out std_logic_vector(data_width-1 downto 0)); +end gc_dual_clock_ram; + +architecture rtl of gc_dual_clock_ram is + type ram_t is array(2**addr_width-1 downto 0) of std_logic_vector(data_width-1 downto 0); + signal ram : ram_t := (others => (others => '0')); + + -- Tell synthesizer we do not care about read during write behaviour + attribute ramstyle : string; + attribute ramstyle of ram : signal is "no_rw_check"; +begin + write : process(w_clk_i) + begin + if rising_edge(w_clk_i) then + if w_en_i = '1' then + ram(to_integer(unsigned(w_addr_i))) <= w_data_i; + end if; + end if; + end process; + + read : process(r_clk_i) + begin + if rising_edge(r_clk_i) then + if r_en_i = '1' then + r_data_o <= ram(to_integer(unsigned(r_addr_i))); + end if; + end if; + end process; +end rtl; diff --git a/modules/common/gc_wfifo.vhd b/modules/common/gc_wfifo.vhd new file mode 100644 index 0000000000000000000000000000000000000000..c457bef689908261564c02a872125c7c56b8d34d --- /dev/null +++ b/modules/common/gc_wfifo.vhd @@ -0,0 +1,150 @@ +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; +use work.gencores_pkg.all; + +entity gc_wfifo is + generic( + sync_depth : natural := 3; + gray_code : boolean := true; + addr_width : natural := 4; + data_width : natural := 32); + port( + rst_n_i : in std_logic; + -- write port, only set w_en when w_rdy + w_clk_i : in std_logic; + w_rdy_o : out std_logic; + w_en_i : in std_logic; + w_data_i : in std_logic_vector(data_width-1 downto 0); + -- (pre)alloc port, can be unused + a_clk_i : in std_logic; + a_rdy_o : out std_logic; + a_en_i : in std_logic; + -- read port, only set r_en when r_rdy + -- data is valid the cycle after r_en raised + r_clk_i : in std_logic; + r_rdy_o : out std_logic; + r_en_i : in std_logic; + r_data_o : out std_logic_vector(data_width-1 downto 0)); +end gc_wfifo; + +architecture rtl of gc_wfifo is + subtype counter is unsigned(addr_width downto 0); + type counter_shift is array(sync_depth downto 0) of counter; + + signal r_idx_bnry : counter; + signal r_idx_gray : counter; + signal w_idx_bnry : counter; + signal w_idx_gray : counter; + signal a_idx_bnry : counter; + signal a_idx_gray : counter; + + signal r_idx_shift_w : counter_shift; -- r_idx_gray in w_clk + signal r_idx_shift_a : counter_shift; -- r_idx_gray in a_clk + signal w_idx_shift_r : counter_shift; -- w_idx_gray in r_clk + + function bin2gray(a : unsigned) return unsigned is + variable o : unsigned(a'length downto 0); + begin + if gray_code then + o := (a & '0') xor ('0' & a); + else + o := (a & '0'); + end if; + return o(a'length downto 1); + end bin2gray; + + function index(a : counter) return std_logic_vector is + begin + return std_logic_vector(a(addr_width-1 downto 0)); + end index; + + function empty(a, b : counter) return std_logic is + begin + if a = b then + return '1'; + else + return '0'; + end if; + end empty; + + function full(a, b : counter) return std_logic is + variable mask : counter := (others => '0'); + begin + -- In binary a full FIFO has indexes (a XOR 1000...00) = b + -- bin2gray is a linear function, thus: + -- a XOR 1000..00 = b iff + -- bin2gray(a XOR 1000...00) = bin2gray(b) iff + -- bin2gray(a) XOR bin2gray(1000...00) = bin2gray(b) iif + -- bin2gray(a) XOR 1100..00 = bin2gray(b) + mask(addr_width) := '1'; + mask := bin2gray(mask); + if (a xor mask) = b then + return '1'; + else + return '0'; + end if; + end full; +begin + ram : gc_dual_clock_ram + generic map(addr_width => addr_width, data_width => data_width) + port map(w_clk_i => w_clk_i, w_en_i => w_en_i, w_addr_i => index(w_idx_bnry), w_data_i => w_data_i, + r_clk_i => r_clk_i, r_en_i => r_en_i, r_addr_i => index(r_idx_bnry), r_data_o => r_data_o); + + read : process(r_clk_i) + variable idx : counter; + begin + if rising_edge(r_clk_i) then + if rst_n_i = '0' then + idx := (others => '0'); + elsif r_en_i = '1' then + idx := r_idx_bnry + 1; + else + idx := r_idx_bnry; + end if; + r_idx_bnry <= idx; + r_idx_gray <= bin2gray(idx); + w_idx_shift_r(sync_depth downto 1) <= w_idx_shift_r(sync_depth-1 downto 0); + end if; + end process; + w_idx_shift_r(0) <= w_idx_gray; + r_rdy_o <= not empty(r_idx_gray, w_idx_shift_r(sync_depth)); + + write : process(w_clk_i) + variable idx : counter; + begin + if rising_edge(w_clk_i) then + if rst_n_i = '0' then + idx := (others => '0'); + elsif w_en_i = '1' then + idx := w_idx_bnry + 1; + else + idx := w_idx_bnry; + end if; + w_idx_bnry <= idx; + w_idx_gray <= bin2gray(idx); + r_idx_shift_w(sync_depth downto 1) <= r_idx_shift_w(sync_depth-1 downto 0); + end if; + end process; + r_idx_shift_w(0) <= r_idx_gray; + w_rdy_o <= not full(w_idx_gray, r_idx_shift_w(sync_depth)); + + alloc : process(a_clk_i) + variable idx : counter; + begin + if rising_edge(a_clk_i) then + if rst_n_i = '0' then + idx := (others => '0'); + elsif a_en_i = '1' then + idx := a_idx_bnry + 1; + else + idx := a_idx_bnry; + end if; + a_idx_bnry <= idx; + a_idx_gray <= bin2gray(idx); + r_idx_shift_a(sync_depth downto 1) <= r_idx_shift_a(sync_depth-1 downto 0); + end if; + end process; + r_idx_shift_a(0) <= r_idx_gray; + a_rdy_o <= not full(a_idx_gray, r_idx_shift_a(sync_depth)); +end rtl; diff --git a/modules/common/gencores_pkg.vhd b/modules/common/gencores_pkg.vhd index 582b8565bcfa99298fe2b215adb90931ae326064..be126a17386593dc39fc7ca8b49898cb621c07b8 100644 --- a/modules/common/gencores_pkg.vhd +++ b/modules/common/gencores_pkg.vhd @@ -6,7 +6,7 @@ -- Author : Tomasz Wlostowski -- Company : CERN -- Created : 2009-09-01 --- Last update: 2012-01-17 +-- Last update: 2012-03-12 -- Platform : FPGA-generic -- Standard : VHDL '93 ------------------------------------------------------------------------------- @@ -15,7 +15,7 @@ -- in the WR and other OHWR projects. ------------------------------------------------------------------------------- -- --- Copyright (c) 2009-2011 CERN +-- Copyright (c) 2009-2012 CERN -- -- This source file is free software; you can redistribute it -- and/or modify it under the terms of the GNU Lesser General @@ -44,8 +44,11 @@ library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; +use work.genram_pkg.all; + package gencores_pkg is + component gc_extend_pulse generic ( g_width : natural); @@ -58,14 +61,14 @@ package gencores_pkg is component gc_crc_gen generic ( - g_polynomial : std_logic_vector := x"04C11DB7"; - g_init_value : std_logic_vector := x"ffffffff"; - g_residue : std_logic_vector := x"38fb2284"; + g_polynomial : std_logic_vector := x"04C11DB7"; + g_init_value : std_logic_vector := x"ffffffff"; + g_residue : std_logic_vector := x"38fb2284"; g_data_width : integer range 2 to 256 := 16; g_half_width : integer range 2 to 256 := 8; - g_sync_reset : integer range 0 to 1 := 1; - g_dual_width : integer range 0 to 1 := 0; - g_registered_match_output : boolean := true); + g_sync_reset : integer range 0 to 1 := 1; + g_dual_width : integer range 0 to 1 := 0; + g_registered_match_output : boolean := true); port ( clk_i : in std_logic; rst_i : in std_logic; @@ -115,7 +118,7 @@ package gencores_pkg is pll_pbgr_p_ki_i : in std_logic_vector(g_coef_bits-1 downto 0)); end component; - + component gc_serial_dac generic ( g_num_data_bits : integer; @@ -133,7 +136,7 @@ package gencores_pkg is dac_sclk_o : out std_logic; dac_sdata_o : out std_logic; busy_o : out std_logic); - end component; + end component; component gc_sync_ffs generic ( @@ -170,6 +173,115 @@ package gencores_pkg is freq_o : out std_logic_vector(g_counter_bits-1 downto 0); freq_valid_o : out std_logic); end component; + + component gc_arbitrated_mux + generic ( + g_num_inputs : integer; + g_width : integer); + port ( + clk_i : in std_logic; + rst_n_i : in std_logic; + d_i : in std_logic_vector(g_num_inputs * g_width-1 downto 0); + d_valid_i : in std_logic_vector(g_num_inputs-1 downto 0); + d_req_o : out std_logic_vector(g_num_inputs-1 downto 0); + q_o : out std_logic_vector(g_width-1 downto 0); + q_valid_o : out std_logic; + q_input_id_o : out std_logic_vector(f_log2_size(g_num_inputs)-1 downto 0)); + end component; + -- Read during write has an undefined result + component gc_dual_clock_ram is + generic( + addr_width : natural := 4; + data_width : natural := 32); + port( + -- write port + w_clk_i : in std_logic; + w_en_i : in std_logic; + w_addr_i : in std_logic_vector(addr_width-1 downto 0); + w_data_i : in std_logic_vector(data_width-1 downto 0); + -- read port + r_clk_i : in std_logic; + r_en_i : in std_logic; + r_addr_i : in std_logic_vector(addr_width-1 downto 0); + r_data_o : out std_logic_vector(data_width-1 downto 0)); + end component; + + -- A 'Wes' FIFO. Generic FIFO using inferred memory. + -- Supports clock domain crossing + -- Should be safe from fast->slow or reversed + -- Set sync_depth := 0 and gray_code := false if only one clock + component gc_wfifo is + generic( + sync_depth : natural := 3; + gray_code : boolean := true; + addr_width : natural := 4; + data_width : natural := 32); + port( + rst_n_i : in std_logic; + -- write port, only set w_en when w_rdy + w_clk_i : in std_logic; + w_rdy_o : out std_logic; + w_en_i : in std_logic; + w_data_i : in std_logic_vector(data_width-1 downto 0); + -- (pre)alloc port, can be unused + a_clk_i : in std_logic; + a_rdy_o : out std_logic; + a_en_i : in std_logic; + -- read port, only set r_en when r_rdy + -- data is valid the cycle after r_en raised + r_clk_i : in std_logic; + r_rdy_o : out std_logic; + r_en_i : in std_logic; + r_data_o : out std_logic_vector(data_width-1 downto 0)); + end component; + + procedure f_rr_arbitrate ( + signal req : in std_logic_vector; + signal pre_grant : in std_logic_vector; + signal grant : out std_logic_vector); + end package; +package body gencores_pkg is + +-- Simple round-robin arbiter: +-- req = requests (1 = pending request), +-- pre_grant = previous grant vector (1 cycle delay) +-- grant = new grant vector + + procedure f_rr_arbitrate ( + signal req : in std_logic_vector; + signal pre_grant : in std_logic_vector; + signal grant : out std_logic_vector)is + + variable reqs : std_logic_vector(req'length - 1 downto 0); + variable gnts : std_logic_vector(req'length - 1 downto 0); + variable gnt : std_logic_vector(req'length - 1 downto 0); + variable gntM : std_logic_vector(req'length - 1 downto 0); + variable zeros : std_logic_vector(req'length - 1 downto 0); + + begin + zeros := (others => '0'); + + -- bit twiddling magic : + gnt := req and std_logic_vector(unsigned(not req) + 1); + reqs := req and not (std_logic_vector(unsigned(pre_grant) - 1) or pre_grant); + gnts := reqs and std_logic_vector(unsigned(not reqs)+1); + + if(reqs = zeros) then + gntM := gnt; + else + gntM := gnts; + end if; + + if((req and pre_grant) = zeros) then + grant <= gntM; + else + grant <= pre_grant; + end if; + + end f_rr_arbitrate; + +end gencores_pkg; + diff --git a/modules/genrams/.gitignore b/modules/genrams/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..57272a1ed24331695137015f1bf44153ce4a4aca --- /dev/null +++ b/modules/genrams/.gitignore @@ -0,0 +1 @@ +coregen_ip \ No newline at end of file diff --git a/modules/genrams/Manifest.py b/modules/genrams/Manifest.py index 7560e0c97a6e998ec18d7083a507eaf373a79ed2..a2518533bb7c7eb9aff9901ca5e6fdda57d6b4ee 100644 --- a/modules/genrams/Manifest.py +++ b/modules/genrams/Manifest.py @@ -39,10 +39,16 @@ def __import_coregen_module(path, name, work_dir): def __import_coregen_files(): xilinx_dir = __os.getenv("XILINX"); if xilinx_dir == None: - print("[genrams] FATAL ERROR: XILINX environment variable not set. Do you have ISE installed?") + print("[genrams] FATAL ERROR: XILINX environment variable not set. It must provide the path to ISE_DS directory in ISE installation folder (follow Xilinx instructions).") __os.exit(-1) + + coregen_path = xilinx_dir + "/ISE/coregen/ip/xilinx/primary/com/xilinx/ip/" + if not __os.path.isdir(coregen_path): + print("[genrams]: FATAL ERROR: XILINX environment variable seems to be set incorrectly. It must point to ISE_DS directory in the ISE installation folder. For example: XILINX=/opt/Xilinx/ISE_DS") + __os.exit(-1) + work_dir = __manifest + "/coregen_ip"; @@ -61,7 +67,7 @@ def __import_coregen_files(): ## "Normal" manifest ## ############################## -print ("[genrams] action = " + action + ", target = " + target, ", syn_device = ", syn_device[0:4].upper()) +#print ("[genrams] action = " + action + ", target = " + target, ", syn_device = ", syn_device[0:4].upper()) if (target == "altera"): modules = {"local" : "altera"} @@ -72,6 +78,6 @@ elif (target == "xilinx" and action == "synthesis" and syn_device[0:4].upper()== __import_coregen_files() modules = {"local" : ["xilinx", "xilinx/virtex6", "coregen_ip/blk_mem_gen_v4_1", "coregen_ip/fifo_generator_v6_1"]} elif (target == "xilinx" and action == "simulation"): - modules = {"local" : ["xilinx/spartan6", "xilinx/sim_stub"]} + modules = {"local" : ["xilinx", "xilinx/spartan6", "xilinx/sim_stub"]} else: - modules = {"local" : "altera"} \ No newline at end of file + modules = {"local" : "altera"} diff --git a/modules/genrams/altera/generic_dpram.vhd b/modules/genrams/altera/generic_dpram.vhd index dc9a33751d0e47b0ac180f65d10adfaf8c34ba0d..9ba20a9e2f1b4e37ea993e8d34f4601231f91028 100644 --- a/modules/genrams/altera/generic_dpram.vhd +++ b/modules/genrams/altera/generic_dpram.vhd @@ -6,7 +6,7 @@ -- Author : Tomasz Wlostowski -- Company : CERN BE-CO-HT -- Created : 2011-01-25 --- Last update: 2011-10-05 +-- Last update: 2012-01-20 -- Platform : -- Standard : VHDL'93 ------------------------------------------------------------------------------- @@ -21,6 +21,7 @@ -- Revisions : -- Date Version Author Description -- 2011-01-25 1.0 twlostow Created +-- 2012-03-13 1.1 wterpstra Added initial value as array ------------------------------------------------------------------------------- @@ -41,6 +42,7 @@ entity generic_dpram is g_with_byte_enable : boolean := false; g_addr_conflict_resolution : string := "read_first"; g_init_file : string := ""; + g_init_value : t_generic_ram_init := c_generic_ram_nothing; g_dual_clock : boolean := true; g_fail_if_file_not_found : boolean := true ); @@ -72,7 +74,7 @@ architecture syn of generic_dpram is constant c_num_bytes : integer := g_data_width/8; type t_ram_type is array(0 to g_size-1) of std_logic_vector(g_data_width-1 downto 0); - type t_ram_word_bs is array (0 to 7) of std_logic_vector(7 downto 0); + type t_ram_word_bs is array (0 to 63) of std_logic_vector(7 downto 0); type t_ram_type_bs is array (0 to g_size - 1) of t_ram_word_bs; function f_memarray_to_ramtype(arr : t_meminit_array) return t_ram_type is @@ -115,12 +117,18 @@ architecture syn of generic_dpram is return tmp; end f_memarray_to_ramtype_bs; - - shared variable ram : t_ram_type := f_memarray_to_ramtype( - f_load_mem_from_file(g_init_file, g_size, g_data_width, g_fail_if_file_not_found)); - - shared variable ram_bs : t_ram_type_bs:=f_memarray_to_ramtype_bs( - f_load_mem_from_file(g_init_file, g_size, g_data_width, g_fail_if_file_not_found)); + function f_file_contents return t_meminit_array is + begin + if g_init_value'length > 0 then + return g_init_value; + else + return f_load_mem_from_file(g_init_file, g_size, g_data_width, g_fail_if_file_not_found); + end if; + end f_file_contents; + + shared variable ram : t_ram_type := f_memarray_to_ramtype(f_file_contents); + shared variable ram_bs : t_ram_type_bs:=f_memarray_to_ramtype_bs(f_file_contents); + signal q_local_a : t_ram_word_bs; signal q_local_b : t_ram_word_bs; diff --git a/modules/genrams/generic_shiftreg_fifo.vhd b/modules/genrams/generic_shiftreg_fifo.vhd index b90e808a53368c1ed88846fc704aa93f47414099..47d5432781e3fe9f46882b5c53f4eaa740a37937 100644 --- a/modules/genrams/generic_shiftreg_fifo.vhd +++ b/modules/genrams/generic_shiftreg_fifo.vhd @@ -65,7 +65,7 @@ entity generic_shiftreg_fifo is full_o : out std_logic; almost_full_o : out std_logic; - q_valid_o: out std_logic + q_valid_o : out std_logic ); end generic_shiftreg_fifo; @@ -79,12 +79,12 @@ architecture rtl of generic_shiftreg_fifo is signal fifo_store : t_srl_array; signal pointer : integer range 0 to c_srl_length - 1; - signal pointer_zero : std_logic; - signal pointer_full : std_logic; - signal pointer_almost_full : STD_LOGIC; - signal empty : std_logic := '1'; - signal valid_count : std_logic; - signal do_write : std_logic; + signal pointer_zero : std_logic; + signal pointer_full : std_logic; + signal pointer_almost_full : std_logic; + signal empty : std_logic := '1'; + signal valid_count : std_logic; + signal do_write : std_logic; begin -- Valid write, high when valid to write data to the store. @@ -96,7 +96,11 @@ begin p_data_srl : process(clk_i) begin if rising_edge(clk_i) then - if do_write = '1' then + if rst_n_i = '0'then + for i in 0 to c_srl_length-1 loop + fifo_store(i) <= (others => '0'); + end loop; -- i + elsif do_write = '1' then fifo_store <= fifo_store(fifo_store'left - 1 downto 0) & d_i; end if; end if; @@ -144,13 +148,13 @@ begin end process; -- Detect when pointer is zero and maximum - pointer_zero <= '1' when pointer = 0 else '0'; - pointer_full <= '1' when pointer = c_srl_length - 1 else '0'; + pointer_zero <= '1' when pointer = 0 else '0'; + pointer_full <= '1' when pointer = c_srl_length - 1 else '0'; pointer_almost_full <= '1' when pointer_full = '1' or pointer = c_srl_length - 2 else '0'; -- assign internal signals to outputs full_o <= pointer_full; almost_full_o <= pointer_almost_full; - q_valid_o <= not empty; + q_valid_o <= not empty; end rtl; diff --git a/modules/genrams/genram_pkg.vhd b/modules/genrams/genram_pkg.vhd index f716349ceb3765b24cfdb156daba51cb2e82915b..633da8983e7da8a6aeb3cdbe97cb35a99f6d6203 100644 --- a/modules/genrams/genram_pkg.vhd +++ b/modules/genrams/genram_pkg.vhd @@ -6,7 +6,7 @@ -- Author : Tomasz Wlostowski -- Company : CERN BE-CO-HT -- Created : 2011-01-25 --- Last update: 2012-01-17 +-- Last update: 2012-01-24 -- Platform : -- Standard : VHDL'93 ------------------------------------------------------------------------------- @@ -41,7 +41,14 @@ use ieee.std_logic_1164.all; package genram_pkg is - function f_log2_size (A : natural) return natural; + function f_log2_size (A : natural) return natural; + function f_gen_dummy_vec (val : std_logic; size : natural) return std_logic_vector; + + type t_generic_ram_init is array (integer range <>, integer range <>) of std_logic; + + -- Generic RAM initialized with nothing. + constant c_generic_ram_nothing : t_generic_ram_init(-1 downto 0, -1 downto 0) := + (others => (others => '0')); -- Single-port synchronous RAM component generic_spram @@ -54,10 +61,10 @@ package genram_pkg is port ( rst_n_i : in std_logic; clk_i : in std_logic; - bwe_i : in std_logic_vector((g_data_width+7)/8-1 downto 0); + bwe_i : in std_logic_vector((g_data_width+7)/8-1 downto 0):= f_gen_dummy_vec('1', (g_data_width+7)/8); we_i : in std_logic; a_i : in std_logic_vector(f_log2_size(g_size)-1 downto 0); - d_i : in std_logic_vector(g_data_width-1 downto 0); + d_i : in std_logic_vector(g_data_width-1 downto 0) := f_gen_dummy_vec('0', g_data_width); q_o : out std_logic_vector(g_data_width-1 downto 0)); end component; @@ -68,20 +75,21 @@ package genram_pkg is g_with_byte_enable : boolean := false; g_addr_conflict_resolution : string := "read_first"; g_init_file : string := ""; + g_init_value : t_generic_ram_init := c_generic_ram_nothing; g_dual_clock : boolean := true); port ( rst_n_i : in std_logic := '1'; clka_i : in std_logic; - bwea_i : in std_logic_vector((g_data_width+7)/8-1 downto 0); - wea_i : in std_logic; + bwea_i : in std_logic_vector((g_data_width+7)/8-1 downto 0) := f_gen_dummy_vec('1', (g_data_width+7)/8); + wea_i : in std_logic := '0'; aa_i : in std_logic_vector(f_log2_size(g_size)-1 downto 0); - da_i : in std_logic_vector(g_data_width-1 downto 0); + da_i : in std_logic_vector(g_data_width-1 downto 0) := f_gen_dummy_vec('0', g_data_width); qa_o : out std_logic_vector(g_data_width-1 downto 0); clkb_i : in std_logic; - bweb_i : in std_logic_vector((g_data_width+7)/8-1 downto 0); - web_i : in std_logic; + bweb_i : in std_logic_vector((g_data_width+7)/8-1 downto 0) := f_gen_dummy_vec('1', (g_data_width+7)/8); + web_i : in std_logic := '0'; ab_i : in std_logic_vector(f_log2_size(g_size)-1 downto 0); - db_i : in std_logic_vector(g_data_width-1 downto 0); + db_i : in std_logic_vector(g_data_width-1 downto 0) := f_gen_dummy_vec('0', g_data_width); qb_o : out std_logic_vector(g_data_width-1 downto 0)); end component; @@ -180,5 +188,14 @@ package body genram_pkg is return(63); end function f_log2_size; + function f_gen_dummy_vec (val : std_logic; size : natural) return std_logic_vector is + variable tmp : std_logic_vector(size-1 downto 0); + begin + for i in 0 to size-1 loop + tmp(i) := val; + end loop; -- i + return tmp; + end f_gen_dummy_vec; + end genram_pkg; diff --git a/modules/genrams/memory_loader_pkg.vhd b/modules/genrams/memory_loader_pkg.vhd index 966a3cafb2d27063bd67c8826e341a20dd055756..8bc4aff1d0a11f250a38c33221538bd99b810871 100644 --- a/modules/genrams/memory_loader_pkg.vhd +++ b/modules/genrams/memory_loader_pkg.vhd @@ -5,9 +5,12 @@ use ieee.numeric_std.all; library std; use std.textio.all; +library work; +use work.genram_pkg.all; + package memory_loader_pkg is - type t_meminit_array is array (integer range <>, integer range <>) of std_logic; + subtype t_meminit_array is t_generic_ram_init; function f_hexchar_to_slv (c : character) return std_logic_vector; function f_hexstring_to_slv (s : string; n_digits : integer) return std_logic_vector; diff --git a/modules/genrams/xilinx/Manifest.py b/modules/genrams/xilinx/Manifest.py index 2a3ee93b452e1524956f645798321be22b40996b..baa93959036d46ffdf8deecac5ec36425a581083 100644 --- a/modules/genrams/xilinx/Manifest.py +++ b/modules/genrams/xilinx/Manifest.py @@ -1,4 +1,6 @@ files = [ "generic_dpram.vhd", -"generic_spram.vhd", -] \ No newline at end of file +"generic_dpram_sameclock.vhd", +"generic_dpram_dualclock.vhd", +"generic_spram.vhd" +] diff --git a/modules/genrams/xilinx/generic_dpram.vhd b/modules/genrams/xilinx/generic_dpram.vhd index ebcf662cbc8ad6e561e03f5bfca229844800f577..acbfdb52eb3e11a5efd0011650b0237614c93a74 100644 --- a/modules/genrams/xilinx/generic_dpram.vhd +++ b/modules/genrams/xilinx/generic_dpram.vhd @@ -6,7 +6,7 @@ -- Author : Tomasz Wlostowski -- Company : CERN BE-CO-HT -- Created : 2011-01-25 --- Last update: 2011-10-05 +-- Last update: 2012-03-16 -- Platform : -- Standard : VHDL'93 ------------------------------------------------------------------------------- @@ -23,6 +23,7 @@ -- Revisions : -- Date Version Author Description -- 2011-01-25 1.0 twlostow Created +-- 2012-03-13 1.1 wterpstra Added initial value as array ------------------------------------------------------------------------------- @@ -39,14 +40,13 @@ entity generic_dpram is generic ( -- standard parameters ---G g_data_width : natural; ---G g_size : natural; g_data_width : natural := 32; g_size : natural := 16384; g_with_byte_enable : boolean := false; g_addr_conflict_resolution : string := "read_first"; g_init_file : string := ""; + g_init_value : t_generic_ram_init := c_generic_ram_nothing; g_dual_clock : boolean := true; g_fail_if_file_not_found : boolean := true ); @@ -77,151 +77,108 @@ end generic_dpram; architecture syn of generic_dpram is - constant c_num_bytes : integer := (g_data_width+7)/8; - - - type t_ram_type is array(0 to g_size-1) of std_logic_vector(g_data_width-1 downto 0); - - function f_memarray_to_ramtype(arr : t_meminit_array) return t_ram_type is - variable tmp : t_ram_type; - variable n, pos : integer; - begin - pos := 0; - while(pos < g_size)loop - n := 0; - -- avoid ISE loop iteration limit - while (pos < g_size and n < 4096) loop - for i in 0 to g_data_width-1 loop - tmp(pos)(i) := arr(pos, i); - end loop; -- i - n := n+1; - pos := pos + 1; - end loop; - pos := pos + 1; - end loop; - return tmp; - end f_memarray_to_ramtype; - - shared variable ram : t_ram_type := f_memarray_to_ramtype( - f_load_mem_from_file(g_init_file, g_size, g_data_width, g_fail_if_file_not_found)); - - signal s_we_a : std_logic_vector(c_num_bytes-1 downto 0); - signal s_ram_in_a : std_logic_vector(g_data_width-1 downto 0); - signal s_we_b : std_logic_vector(c_num_bytes-1 downto 0); - signal s_ram_in_b : std_logic_vector(g_data_width-1 downto 0); - - signal clka_int : std_logic; - signal clkb_int : std_logic; - - signal wea_rep, web_rep : std_logic_vector(c_num_bytes-1 downto 0); + component generic_dpram_sameclock + generic ( + g_data_width : natural; + g_size : natural; + g_with_byte_enable : boolean; + g_addr_conflict_resolution : string; + g_init_file : string; + g_init_value : t_generic_ram_init; + g_fail_if_file_not_found : boolean); + port ( + rst_n_i : in std_logic := '1'; + clk_i : in std_logic; + bwea_i : in std_logic_vector((g_data_width+7)/8-1 downto 0); + wea_i : in std_logic; + aa_i : in std_logic_vector(f_log2_size(g_size)-1 downto 0); + da_i : in std_logic_vector(g_data_width-1 downto 0); + qa_o : out std_logic_vector(g_data_width-1 downto 0); + bweb_i : in std_logic_vector((g_data_width+7)/8-1 downto 0); + web_i : in std_logic; + ab_i : in std_logic_vector(f_log2_size(g_size)-1 downto 0); + db_i : in std_logic_vector(g_data_width-1 downto 0); + qb_o : out std_logic_vector(g_data_width-1 downto 0)); + end component; + + component generic_dpram_dualclock + generic ( + g_data_width : natural; + g_size : natural; + g_with_byte_enable : boolean; + g_addr_conflict_resolution : string; + g_init_file : string; + g_init_value : t_generic_ram_init; + g_fail_if_file_not_found : boolean); + port ( + rst_n_i : in std_logic := '1'; + clka_i : in std_logic; + bwea_i : in std_logic_vector((g_data_width+7)/8-1 downto 0); + wea_i : in std_logic; + aa_i : in std_logic_vector(f_log2_size(g_size)-1 downto 0); + da_i : in std_logic_vector(g_data_width-1 downto 0); + qa_o : out std_logic_vector(g_data_width-1 downto 0); + clkb_i : in std_logic; + bweb_i : in std_logic_vector((g_data_width+7)/8-1 downto 0); + web_i : in std_logic; + ab_i : in std_logic_vector(f_log2_size(g_size)-1 downto 0); + db_i : in std_logic_vector(g_data_width-1 downto 0); + qb_o : out std_logic_vector(g_data_width-1 downto 0)); + end component; begin - gen_single_clock : if(g_dual_clock = false) generate - clka_int <= clka_i;-- after 1ns; - clkb_int <= clka_i;-- after 1ns; - end generate gen_single_clock; - - gen_dual_clock : if(g_dual_clock = true) generate - clka_int <= clka_i;-- after 1ns; - clkb_int <= clkb_i;-- after 1ns; - end generate gen_dual_clock; - - wea_rep <= (others => wea_i); - web_rep <= (others => web_i); - - s_we_a <= bwea_i and wea_rep; - s_we_b <= bweb_i and web_rep; - - gen_with_byte_enable_readfirst : if(g_with_byte_enable = true and g_addr_conflict_resolution = "read_first") generate - - - process (clka_int) - begin - if rising_edge(clka_int) then - qa_o <= ram(to_integer(unsigned(aa_i))); - for i in 0 to c_num_bytes-1 loop - if s_we_a(i) = '1' then - ram(to_integer(unsigned(aa_i)))((i+1)*8-1 downto i*8) := da_i((i+1)*8-1 downto i*8); - end if; - end loop; - end if; - end process; - - - process (clkb_int) - begin - if rising_edge(clkb_int) then - qb_o <= ram(to_integer(unsigned(ab_i))); - for i in 0 to c_num_bytes-1 loop - if s_we_b(i) = '1' then - ram(to_integer(unsigned(ab_i)))((i+1)*8-1 downto i*8) - := db_i((i+1)*8-1 downto i*8); - end if; - end loop; - end if; - end process; - - - - - end generate gen_with_byte_enable_readfirst; - + gen_single_clk : if(g_dual_clock = false) generate + U_RAM_SC: generic_dpram_sameclock + generic map ( + g_data_width => g_data_width, + g_size => g_size, + g_with_byte_enable => g_with_byte_enable, + g_addr_conflict_resolution => g_addr_conflict_resolution, + g_init_file => g_init_file, + g_init_value => g_init_value, + g_fail_if_file_not_found => g_fail_if_file_not_found) + port map ( + rst_n_i => rst_n_i, + clk_i => clka_i, + bwea_i => bwea_i, + wea_i => wea_i, + aa_i => aa_i, + da_i => da_i, + qa_o => qa_o, + bweb_i => bweb_i, + web_i => web_i, + ab_i => ab_i, + db_i => db_i, + qb_o => qb_o); - - gen_without_byte_enable_readfirst : if(g_with_byte_enable = false and g_addr_conflict_resolution = "read_first") generate - - process(clka_int) - begin - if rising_edge(clka_int) then - qa_o <= ram(to_integer(unsigned(aa_i))); - if(wea_i = '1') then - ram(to_integer(unsigned(aa_i))) := da_i; - end if; - end if; - end process; - - - process(clkb_int) - begin - if rising_edge(clkb_int) then - qb_o <= ram(to_integer(unsigned(ab_i))); - if(web_i = '1') then - ram(to_integer(unsigned(ab_i))) := db_i; - end if; - end if; - end process; - - end generate gen_without_byte_enable_readfirst; - - - gen_without_byte_enable_writefirst : if(g_with_byte_enable = false and g_addr_conflict_resolution = "write_first") generate - - process(clka_int) - begin - if rising_edge(clka_int) then - if(wea_i = '1') then - ram(to_integer(unsigned(aa_i))) := da_i; - qa_o <= da_i; - else - qa_o <= ram(to_integer(unsigned(aa_i))); - end if; - end if; - end process; - - - process(clkb_int) - begin - if rising_edge(clkb_int) then - if(web_i = '1') then - ram(to_integer(unsigned(ab_i))) := db_i; - qb_o <= db_i; - else - qb_o <= ram(to_integer(unsigned(ab_i))); - end if; - end if; - end process; - end generate gen_without_byte_enable_writefirst; - + + end generate gen_single_clk; + + gen_dual_clk : if(g_dual_clock = true) generate + U_RAM_DC: generic_dpram_dualclock + generic map ( + g_data_width => g_data_width, + g_size => g_size, + g_with_byte_enable => g_with_byte_enable, + g_addr_conflict_resolution => g_addr_conflict_resolution, + g_init_file => g_init_file, + g_init_value => g_init_value, + g_fail_if_file_not_found => g_fail_if_file_not_found) + port map ( + rst_n_i => rst_n_i, + clka_i => clka_i, + bwea_i => bwea_i, + wea_i => wea_i, + aa_i => aa_i, + da_i => da_i, + qa_o => qa_o, + clkb_i => clkb_i, + bweb_i => bweb_i, + web_i => web_i, + ab_i => ab_i, + db_i => db_i, + qb_o => qb_o); + end generate gen_dual_clk; end syn; diff --git a/modules/genrams/xilinx/generic_dpram_dualclock.vhd b/modules/genrams/xilinx/generic_dpram_dualclock.vhd new file mode 100644 index 0000000000000000000000000000000000000000..b04792762956c57ba11f18f4858be491802f7a05 --- /dev/null +++ b/modules/genrams/xilinx/generic_dpram_dualclock.vhd @@ -0,0 +1,249 @@ +------------------------------------------------------------------------------- +-- Title : Parametrizable dual-port synchronous RAM (Xilinx version) +-- Project : Generics RAMs and FIFOs collection +------------------------------------------------------------------------------- +-- File : generic_dpram.vhd +-- Author : Tomasz Wlostowski +-- Company : CERN BE-CO-HT +-- Created : 2011-01-25 +-- Last update: 2012-03-28 +-- Platform : +-- Standard : VHDL'93 +------------------------------------------------------------------------------- +-- Description: True dual-port synchronous RAM for Xilinx FPGAs with: +-- - configurable address and data bus width +-- - byte-addressing mode (data bus width restricted to multiple of 8 bits) +-- Todo: +-- - loading initial contents from file +-- - add support for read-first/write-first address conflict resulution (only +-- supported by Xilinx in VHDL templates) +------------------------------------------------------------------------------- +-- Copyright (c) 2011 CERN +------------------------------------------------------------------------------- +-- Revisions : +-- Date Version Author Description +-- 2011-01-25 1.0 twlostow Created +------------------------------------------------------------------------------- + + +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; +use std.textio.all; + +library work; +use work.genram_pkg.all; +use work.memory_loader_pkg.all; + +entity generic_dpram_dualclock is + + generic ( + -- standard parameters + g_data_width : natural := 32; + g_size : natural := 16384; + + g_with_byte_enable : boolean := false; + g_addr_conflict_resolution : string := "read_first"; + g_init_file : string := ""; + g_init_value : t_generic_ram_init := c_generic_ram_nothing; + g_fail_if_file_not_found : boolean := true + ); + + port ( + rst_n_i : in std_logic := '1'; -- synchronous reset, active LO + + -- Port A + clka_i : in std_logic; + bwea_i : in std_logic_vector((g_data_width+7)/8-1 downto 0); + wea_i : in std_logic; + aa_i : in std_logic_vector(f_log2_size(g_size)-1 downto 0); + da_i : in std_logic_vector(g_data_width-1 downto 0); + qa_o : out std_logic_vector(g_data_width-1 downto 0); + -- Port B + + clkb_i : in std_logic; + bweb_i : in std_logic_vector((g_data_width+7)/8-1 downto 0); + web_i : in std_logic; + ab_i : in std_logic_vector(f_log2_size(g_size)-1 downto 0); + db_i : in std_logic_vector(g_data_width-1 downto 0); + qb_o : out std_logic_vector(g_data_width-1 downto 0) + ); + +end generic_dpram_dualclock; + + + +architecture syn of generic_dpram_dualclock is + + constant c_num_bytes : integer := (g_data_width+7)/8; + + + type t_ram_type is array(0 to g_size-1) of std_logic_vector(g_data_width-1 downto 0); + + function f_memarray_to_ramtype(arr : t_meminit_array) return t_ram_type is + variable tmp : t_ram_type; + variable n, pos : integer; + begin + pos := 0; + while(pos < g_size)loop + n := 0; + -- avoid ISE loop iteration limit + while (pos < g_size and n < 4096) loop + for i in 0 to g_data_width-1 loop + tmp(pos)(i) := arr(pos, i); + end loop; -- i + n := n+1; + pos := pos + 1; + end loop; + end loop; + return tmp; + end f_memarray_to_ramtype; + + function f_file_contents return t_meminit_array is + begin + if g_init_value'length > 0 then + return g_init_value; + else + return f_load_mem_from_file(g_init_file, g_size, g_data_width, g_fail_if_file_not_found); + end if; + end f_file_contents; + + shared variable ram : t_ram_type := f_memarray_to_ramtype(f_file_contents); + + signal s_we_a : std_logic_vector(c_num_bytes-1 downto 0); + signal s_ram_in_a : std_logic_vector(g_data_width-1 downto 0); + signal s_we_b : std_logic_vector(c_num_bytes-1 downto 0); + signal s_ram_in_b : std_logic_vector(g_data_width-1 downto 0); + + signal clka_int : std_logic; + signal clkb_int : std_logic; + + signal wea_rep, web_rep : std_logic_vector(c_num_bytes-1 downto 0); + +begin + + wea_rep <= (others => wea_i); + web_rep <= (others => web_i); + + s_we_a <= bwea_i and wea_rep; + s_we_b <= bweb_i and web_rep; + + gen_with_byte_enable_readfirst : if(g_with_byte_enable = true and g_addr_conflict_resolution = "read_first") generate + + + process (clka_i) + begin + if rising_edge(clka_i) then + qa_o <= ram(to_integer(unsigned(aa_i))); + for i in 0 to c_num_bytes-1 loop + if s_we_a(i) = '1' then + ram(to_integer(unsigned(aa_i)))((i+1)*8-1 downto i*8) := da_i((i+1)*8-1 downto i*8); + end if; + end loop; + end if; + end process; + + + process (clkb_i) + begin + if rising_edge(clkb_i) then + qb_o <= ram(to_integer(unsigned(ab_i))); + for i in 0 to c_num_bytes-1 loop + if s_we_b(i) = '1' then + ram(to_integer(unsigned(ab_i)))((i+1)*8-1 downto i*8) + := db_i((i+1)*8-1 downto i*8); + end if; + end loop; + end if; + end process; + + + + + end generate gen_with_byte_enable_readfirst; + + + + gen_without_byte_enable_readfirst : if(g_with_byte_enable = false and g_addr_conflict_resolution = "read_first") generate + + process(clka_i) + begin + if rising_edge(clka_i) then + qa_o <= ram(to_integer(unsigned(aa_i))); + if(wea_i = '1') then + ram(to_integer(unsigned(aa_i))) := da_i; + end if; + end if; + end process; + + + process(clkb_i) + begin + if rising_edge(clkb_i) then + qb_o <= ram(to_integer(unsigned(ab_i))); + if(web_i = '1') then + ram(to_integer(unsigned(ab_i))) := db_i; + end if; + end if; + end process; + + end generate gen_without_byte_enable_readfirst; + + + gen_without_byte_enable_writefirst : if(g_with_byte_enable = false and g_addr_conflict_resolution = "write_first") generate + + process(clka_i) + begin + if rising_edge(clka_i) then + if(wea_i = '1') then + ram(to_integer(unsigned(aa_i))) := da_i; + qa_o <= da_i; + else + qa_o <= ram(to_integer(unsigned(aa_i))); + end if; + end if; + end process; + + + process(clkb_i) + begin + if rising_edge(clkb_i) then + if(web_i = '1') then + ram(to_integer(unsigned(ab_i))) := db_i; + qb_o <= db_i; + else + qb_o <= ram(to_integer(unsigned(ab_i))); + end if; + end if; + end process; + end generate gen_without_byte_enable_writefirst; + + + gen_without_byte_enable_nochange : if(g_with_byte_enable = false and g_addr_conflict_resolution = "no_change") generate + + process(clka_i) + begin + if rising_edge(clka_i) then + if(wea_i = '1') then + ram(to_integer(unsigned(aa_i))) := da_i; + else + qa_o <= ram(to_integer(unsigned(aa_i))); + end if; + end if; + end process; + + + process(clkb_i) + begin + if rising_edge(clkb_i) then + if(web_i = '1') then + ram(to_integer(unsigned(ab_i))) := db_i; + else + qb_o <= ram(to_integer(unsigned(ab_i))); + end if; + end if; + end process; + end generate gen_without_byte_enable_nochange; + + +end syn; diff --git a/modules/genrams/xilinx/generic_dpram_sameclock.vhd b/modules/genrams/xilinx/generic_dpram_sameclock.vhd new file mode 100644 index 0000000000000000000000000000000000000000..6d6b158bb003fb2602067d2ad613bb77e33a9e56 --- /dev/null +++ b/modules/genrams/xilinx/generic_dpram_sameclock.vhd @@ -0,0 +1,213 @@ +------------------------------------------------------------------------------- +-- Title : Parametrizable dual-port synchronous RAM (Xilinx version) +-- Project : Generics RAMs and FIFOs collection +------------------------------------------------------------------------------- +-- File : generic_dpram_sameclock.vhd +-- Author : Tomasz Wlostowski +-- Company : CERN BE-CO-HT +-- Created : 2011-01-25 +-- Last update: 2012-03-28 +-- Platform : +-- Standard : VHDL'93 +------------------------------------------------------------------------------- +-- Description: True dual-port synchronous RAM for Xilinx FPGAs with: +-- - configurable address and data bus width +-- - byte-addressing mode (data bus width restricted to multiple of 8 bits) +-- Todo: +-- - loading initial contents from file +-- - add support for read-first/write-first address conflict resulution (only +-- supported by Xilinx in VHDL templates) +------------------------------------------------------------------------------- +-- Copyright (c) 2011 CERN +------------------------------------------------------------------------------- +-- Revisions : +-- Date Version Author Description +-- 2011-01-25 1.0 twlostow Created +------------------------------------------------------------------------------- + + +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; +use std.textio.all; + +library work; +use work.genram_pkg.all; +use work.memory_loader_pkg.all; + +entity generic_dpram_sameclock is + + generic ( + g_data_width : natural := 32; + g_size : natural := 16384; + + g_with_byte_enable : boolean := false; + g_addr_conflict_resolution : string := "read_first"; + g_init_file : string := ""; + g_init_value : t_generic_ram_init := c_generic_ram_nothing; + g_fail_if_file_not_found : boolean := true + ); + + port ( + rst_n_i : in std_logic := '1'; -- synchronous reset, active LO + + -- Port A + clk_i : in std_logic; + + bwea_i : in std_logic_vector((g_data_width+7)/8-1 downto 0); + wea_i : in std_logic; + aa_i : in std_logic_vector(f_log2_size(g_size)-1 downto 0); + da_i : in std_logic_vector(g_data_width-1 downto 0); + qa_o : out std_logic_vector(g_data_width-1 downto 0); + + -- Port B + bweb_i : in std_logic_vector((g_data_width+7)/8-1 downto 0); + web_i : in std_logic; + ab_i : in std_logic_vector(f_log2_size(g_size)-1 downto 0); + db_i : in std_logic_vector(g_data_width-1 downto 0); + qb_o : out std_logic_vector(g_data_width-1 downto 0) + ); + +end generic_dpram_sameclock; + + + +architecture syn of generic_dpram_sameclock is + + constant c_num_bytes : integer := (g_data_width+7)/8; + + + type t_ram_type is array(0 to g_size-1) of std_logic_vector(g_data_width-1 downto 0); + + function f_memarray_to_ramtype(arr : t_meminit_array) return t_ram_type is + variable tmp : t_ram_type; + variable n, pos : integer; + begin + pos := 0; + while(pos < g_size)loop + n := 0; + -- avoid ISE loop iteration limit + while (pos < g_size and n < 4096) loop + for i in 0 to g_data_width-1 loop + tmp(pos)(i) := arr(pos, i); + end loop; -- i + n := n+1; + pos := pos + 1; + end loop; + end loop; + return tmp; + end f_memarray_to_ramtype; + + function f_file_contents return t_meminit_array is + begin + if g_init_value'length > 0 then + return g_init_value; + else + return f_load_mem_from_file(g_init_file, g_size, g_data_width, g_fail_if_file_not_found); + end if; + end f_file_contents; + + shared variable ram : t_ram_type := f_memarray_to_ramtype(f_file_contents); + + signal s_we_a : std_logic_vector(c_num_bytes-1 downto 0); + signal s_ram_in_a : std_logic_vector(g_data_width-1 downto 0); + signal s_we_b : std_logic_vector(c_num_bytes-1 downto 0); + signal s_ram_in_b : std_logic_vector(g_data_width-1 downto 0); + + + signal wea_rep, web_rep : std_logic_vector(c_num_bytes-1 downto 0); + +begin + + wea_rep <= (others => wea_i); + web_rep <= (others => web_i); + + s_we_a <= bwea_i and wea_rep; + s_we_b <= bweb_i and web_rep; + + gen_with_byte_enable_readfirst : if(g_with_byte_enable = true and g_addr_conflict_resolution = "read_first") generate + + process (clk_i) + begin + if rising_edge(clk_i) then + qa_o <= ram(to_integer(unsigned(aa_i))); + qb_o <= ram(to_integer(unsigned(ab_i))); + for i in 0 to c_num_bytes-1 loop + if s_we_a(i) = '1' then + ram(to_integer(unsigned(aa_i)))((i+1)*8-1 downto i*8) := da_i((i+1)*8-1 downto i*8); + end if; + if(s_we_b(i) = '1') then + ram(to_integer(unsigned(ab_i)))((i+1)*8-1 downto i*8) := db_i((i+1)*8-1 downto i*8); + end if; + end loop; + end if; + end process; + + end generate gen_with_byte_enable_readfirst; + + + + gen_without_byte_enable_readfirst : if(g_with_byte_enable = false and g_addr_conflict_resolution = "read_first") generate + + process(clk_i) + begin + if rising_edge(clk_i) then + qa_o <= ram(to_integer(unsigned(aa_i))); + qb_o <= ram(to_integer(unsigned(ab_i))); + if(wea_i = '1') then + ram(to_integer(unsigned(aa_i))) := da_i; + end if; + if(web_i = '1') then + ram(to_integer(unsigned(ab_i))) := db_i; + end if; + end if; + end process; + end generate gen_without_byte_enable_readfirst; + + gen_without_byte_enable_writefirst : if(g_with_byte_enable = false and g_addr_conflict_resolution = "write_first") generate + + process(clk_i) + begin + if rising_edge(clk_i) then + if(wea_i = '1') then + ram(to_integer(unsigned(aa_i))) := da_i; + qa_o <= da_i; + else + qa_o <= ram(to_integer(unsigned(aa_i))); + end if; + if(web_i = '1') then + ram(to_integer(unsigned(ab_i))) := db_i; + qb_o <= db_i; + else + qb_o <= ram(to_integer(unsigned(ab_i))); + end if; + end if; + + end process; + end generate gen_without_byte_enable_writefirst; + + + gen_without_byte_enable_nochange : if(g_with_byte_enable = false and g_addr_conflict_resolution = "no_change") generate + + process(clk_i) + begin + if rising_edge(clk_i) then + if(wea_i = '1') then + ram(to_integer(unsigned(aa_i))) := da_i; + else + qa_o <= ram(to_integer(unsigned(aa_i))); + end if; + if(web_i = '1') then + ram(to_integer(unsigned(ab_i))) := db_i; + else + qb_o <= ram(to_integer(unsigned(ab_i))); + end if; + end if; + end process; + + + + end generate gen_without_byte_enable_nochange; + + +end syn; diff --git a/modules/wishbone/Manifest.py b/modules/wishbone/Manifest.py index c8ee88c09ac2ed77d4e2d532abd4f3b98bf7ed83..4048a80bd3c241e6781384df08abc30fe929feda 100644 --- a/modules/wishbone/Manifest.py +++ b/modules/wishbone/Manifest.py @@ -1,11 +1,9 @@ modules = { "local" : - [ "wb_async_bridge", "wb_onewire_master", "wb_i2c_master", "wb_bus_fanout", -# "wb_conmax", "wb_dpram", "wb_gpio_port", "wb_simple_timer", @@ -15,6 +13,9 @@ modules = { "local" : "wb_crossbar", "wb_lm32", "wb_slave_adapter", + "wb_xilinx_fpga_loader", + "wb_clock_crossing", + "wb_dma", "wbgen2" ]}; diff --git a/modules/wishbone/wb_clock_crossing/Manifest.py b/modules/wishbone/wb_clock_crossing/Manifest.py new file mode 100644 index 0000000000000000000000000000000000000000..ae25624eaa24e10cdda3f655c7ccb0d1885acf7b --- /dev/null +++ b/modules/wishbone/wb_clock_crossing/Manifest.py @@ -0,0 +1 @@ +files = [ "xwb_clock_crossing.vhd" ]; diff --git a/modules/wishbone/wb_clock_crossing/xwb_clock_crossing.vhd b/modules/wishbone/wb_clock_crossing/xwb_clock_crossing.vhd new file mode 100644 index 0000000000000000000000000000000000000000..73d7b784ea2eb944d62bf4b7788c3969bb0b86ba --- /dev/null +++ b/modules/wishbone/wb_clock_crossing/xwb_clock_crossing.vhd @@ -0,0 +1,150 @@ +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; +use work.wishbone_pkg.all; +use work.gencores_pkg.all; + +entity xwb_clock_crossing is + generic( + sync_depth : natural := 2; + log2fifo : natural := 4); + port( + -- Common wishbone signals + rst_n_i : in std_logic; + -- Slave control port + slave_clk_i : in std_logic; + slave_i : in t_wishbone_slave_in; + slave_o : out t_wishbone_slave_out; + -- Master reader port + master_clk_i : in std_logic; + master_i : in t_wishbone_master_in; + master_o : out t_wishbone_master_out); +end xwb_clock_crossing; + +architecture rtl of xwb_clock_crossing is + constant mCYC_start : natural := 0; + constant mCYC_end : natural := mCYC_start; + constant mWE_start : natural := mCYC_end + 1; + constant mWE_end : natural := mWE_start; + constant mADR_start : natural := mWE_end + 1; + constant mADR_end : natural := mADR_start + c_wishbone_address_width - 1; + constant mDAT_start : natural := mADR_end + 1; + constant mDAT_end : natural := mDAT_start + c_wishbone_data_width - 1; + constant mSEL_start : natural := mDAT_end + 1; + constant mSEL_end : natural := mSEL_start + (c_wishbone_data_width/8) - 1; + constant mlen : natural := mSEL_end + 1; + + signal msend, mrecv : t_wishbone_master_out; + signal msend_vect, mrecv_vect : std_logic_vector(mlen-1 downto 0); + signal mw_rdy, mw_en, mr_rdy, mr_en : std_logic; + + constant sACK_start : natural := 0; + constant sACK_end : natural := sACK_start; + constant sRTY_start : natural := sACK_end + 1; + constant sRTY_end : natural := sRTY_start; + constant sERR_start : natural := sRTY_end + 1; + constant sERR_end : natural := sERR_start; + constant sDAT_start : natural := sERR_end + 1; + constant sDAT_end : natural := sDAT_start + c_wishbone_data_width - 1; + constant slen : natural := sDAT_end + 1; + + signal ssend, srecv : t_wishbone_slave_out; + signal ssend_vect, srecv_vect : std_logic_vector(slen-1 downto 0); + signal sw_rdy, sw_en, sr_rdy, sr_en, sa_rdy, sa_en : std_logic; + + signal slave_CYC : std_logic; + signal master_o_STB : std_logic; + signal slave_o_PUSH : std_logic; +begin + mfifo : gc_wfifo + generic map(addr_width => log2fifo, data_width => mlen, sync_depth => sync_depth, gray_code => true) + port map(w_clk_i => slave_clk_i, w_rdy_o => mw_rdy, w_en_i => mw_en, w_data_i => msend_vect, + r_clk_i => master_clk_i, r_rdy_o => mr_rdy, r_en_i => mr_en, r_data_o => mrecv_vect, + a_clk_i => '0', a_rdy_o => open, a_en_i => '0', rst_n_i => rst_n_i); + + msend_vect(mCYC_start) <= msend.CYC; + msend_vect(mWE_start) <= msend.WE; + msend_vect(mADR_end downto mADR_start) <= msend.ADR; + msend_vect(mDAT_end downto mDAT_start) <= msend.DAT; + msend_vect(mSEL_end downto mSEL_start) <= msend.SEL; + + mrecv.CYC <= mrecv_vect(mCYC_start); + mrecv.WE <= mrecv_vect(mWE_start); + mrecv.ADR <= mrecv_vect(mADR_end downto mADR_start); + mrecv.DAT <= mrecv_vect(mDAT_end downto mDAT_start); + mrecv.SEL <= mrecv_vect(mSEL_end downto mSEL_start); + + sfifo : gc_wfifo + generic map(addr_width => log2fifo, data_width => slen, sync_depth => sync_depth, gray_code => true) + port map(w_clk_i => master_clk_i, w_rdy_o => open, w_en_i => sw_en, w_data_i => ssend_vect, + r_clk_i => slave_clk_i, r_rdy_o => sr_rdy, r_en_i => sr_en, r_data_o => srecv_vect, + a_clk_i => slave_clk_i, a_rdy_o => sa_rdy, a_en_i => sa_en, rst_n_i => rst_n_i); + + ssend_vect(sACK_start) <= ssend.ACK; + ssend_vect(sRTY_start) <= ssend.RTY; + ssend_vect(sERR_start) <= ssend.ERR; + ssend_vect(sDAT_end downto sDAT_start) <= ssend.DAT; + + srecv.ACK <= srecv_vect(sACK_start); + srecv.RTY <= srecv_vect(sRTY_start); + srecv.ERR <= srecv_vect(sERR_start); + srecv.DAT <= srecv_vect(sDAT_end downto sDAT_start); + + -- Slave clock domain: slave -> mFIFO + mw_en <= (mw_rdy and sa_rdy and slave_i.CYC and slave_i.STB) or + (not slave_i.CYC and slave_CYC); -- Masters may only drop cycle if FIFOs are empty + sa_en <= mw_rdy and sa_rdy and slave_i.CYC and slave_i.STB; + slave_o.STALL <= not mw_rdy or not sa_rdy; + msend.CYC <= slave_i.CYC; + msend.ADR <= slave_i.ADR; + msend.WE <= slave_i.WE; + msend.SEL <= slave_i.SEL; + msend.DAT <= slave_i.DAT; + + -- Master clock domain: mFIFO -> master + mr_en <= mr_rdy and (not master_o_STB or not master_i.STALL); + master_o.CYC <= mrecv.CYC; + master_o.STB <= master_o_STB; -- is high outside of CYC. that's ok; it should be ignored. + master_o.ADR <= mrecv.ADR; + master_o.WE <= mrecv.WE; + master_o.SEL <= mrecv.SEL; + master_o.DAT <= mrecv.DAT; + + drive_master_port : process(master_clk_i) + begin + if rising_edge(master_clk_i) then + if rst_n_i = '0' then + master_o_STB <= '0'; + else + master_o_STB <= mr_en or (master_o_STB and master_i.STALL); + end if; + end if; + end process; + + -- Master clock domain: master -> sFIFO + sw_en <= master_i.ACK or master_i.ERR or master_i.RTY; + ssend.ACK <= master_i.ACK; + ssend.ERR <= master_i.ERR; + ssend.RTY <= master_i.RTY; + ssend.DAT <= master_i.DAT; + + -- Slave clock domain: sFIFO -> slave + sr_en <= sr_rdy; + slave_o.DAT <= srecv.DAT; + slave_o.ACK <= srecv.ACK and slave_o_PUSH; + slave_o.RTY <= srecv.RTY and slave_o_PUSH; + slave_o.ERR <= srecv.ERR and slave_o_PUSH; + + drive_slave_port : process(slave_clk_i) + begin + if rising_edge(slave_clk_i) then + if rst_n_i = '0' then + slave_o_PUSH <= '0'; + slave_CYC <= '0'; + else + slave_o_PUSH <= sr_en; + slave_CYC <= slave_i.CYC; + end if; + end if; + end process; +end rtl; diff --git a/modules/wishbone/wb_crossbar/Manifest.py b/modules/wishbone/wb_crossbar/Manifest.py index df804aee948ff7aadc31166212295be74e9e0559..1b5f27370604bf5cae8c14247e954b47c5fab0a6 100644 --- a/modules/wishbone/wb_crossbar/Manifest.py +++ b/modules/wishbone/wb_crossbar/Manifest.py @@ -1 +1,4 @@ -files = ["xwb_crossbar.vhd"]; +files = [ + "sdwb_rom.vhd", + "xwb_crossbar.vhd", + "xwb_sdwb_crossbar.vhd" ]; diff --git a/modules/wishbone/wb_crossbar/sdwb_rom.vhd b/modules/wishbone/wb_crossbar/sdwb_rom.vhd new file mode 100644 index 0000000000000000000000000000000000000000..3655b2cc2459d153f9404b9e5f11b49359ffe9b0 --- /dev/null +++ b/modules/wishbone/wb_crossbar/sdwb_rom.vhd @@ -0,0 +1,104 @@ +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; +use work.wishbone_pkg.all; + +entity sdwb_rom is + generic( + g_layout : t_sdwb_device_array; + g_bus_end : unsigned(63 downto 0)); + port( + clk_sys_i : in std_logic; + slave_i : in t_wishbone_slave_in; + slave_o : out t_wishbone_slave_out); +end sdwb_rom; + +architecture rtl of sdwb_rom is + alias c_layout : t_sdwb_device_array(g_layout'length downto 1) is g_layout; + + constant c_version : natural := 1; + constant c_date : natural := 16#20120305#; + constant c_rom_description : string(1 to 16) := "WB4-Crossbar-GSI"; + + -- The ROM must describe all slaves and the crossbar itself + constant c_used_entries : natural := c_layout'length + 1; + constant c_rom_entries : natural := 2**f_ceil_log2(c_used_entries); -- next power of 2 + constant c_sdwb_words : natural := c_sdwb_device_length / c_wishbone_data_width; + constant c_rom_words : natural := c_rom_entries * c_sdwb_words; + constant c_rom_depth : natural := f_ceil_log2(c_rom_words); + constant c_rom_lowbits : natural := f_ceil_log2(c_wishbone_data_width / 8); + + type t_rom is array(c_rom_words-1 downto 0) of t_wishbone_data; + function f_build_rom + return t_rom is + variable res : t_rom := (others => (others => '0')); + variable sdwb_device : std_logic_vector(0 to c_sdwb_device_length-1) := (others => '0'); + begin + sdwb_device( 0 to 127) := not x"40f6e98c29eae24c7e6461ae8d2af247"; -- magic + sdwb_device(128 to 191) := std_logic_vector(g_bus_end); -- bus_end + sdwb_device(192 to 207) := std_logic_vector(to_unsigned(c_used_entries, 16)); -- sdwb_records + sdwb_device(208 to 215) := x"01"; -- sdwb_ver_major + sdwb_device(216 to 223) := x"00"; -- sdwb_ver_minor + sdwb_device(224 to 255) := x"00000651"; -- bus_vendor (GSI) + sdwb_device(256 to 287) := x"eef0b198"; -- bus_device + sdwb_device(288 to 319) := std_logic_vector(to_unsigned(c_version, 32)); -- bus_version + sdwb_device(320 to 351) := std_logic_vector(to_unsigned(c_date, 32)); -- bus_date + sdwb_device(352 to 383) := x"00000000"; -- bus_flags + for i in 1 to 16 loop + sdwb_device(376+i*8 to 383+i*8) := + std_logic_vector(to_unsigned(character'pos(c_rom_description(i)), 8)); + end loop; + + for i in 0 to c_sdwb_words-1 loop + res(i) := + sdwb_device(i*c_wishbone_data_width to (i+1)*c_wishbone_data_width-1); + end loop; + + for slave in 1 to c_used_entries-1 loop + sdwb_device( 0 to 63) := std_logic_vector(c_layout(slave).wbd_begin); + sdwb_device( 64 to 127) := std_logic_vector(c_layout(slave).wbd_end); + sdwb_device(128 to 191) := std_logic_vector(c_layout(slave).sdwb_child); + sdwb_device(192 to 199) := c_layout(slave).wbd_flags; + sdwb_device(200 to 207) := c_layout(slave).wbd_width; + sdwb_device(208 to 215) := std_logic_vector(c_layout(slave).abi_ver_major); + sdwb_device(216 to 223) := std_logic_vector(c_layout(slave).abi_ver_minor); + sdwb_device(224 to 255) := c_layout(slave).abi_class; + sdwb_device(256 to 287) := c_layout(slave).dev_vendor; + sdwb_device(288 to 319) := c_layout(slave).dev_device; + sdwb_device(320 to 351) := c_layout(slave).dev_version; + sdwb_device(352 to 383) := c_layout(slave).dev_date; + for i in 1 to 16 loop + -- string to ascii + sdwb_device(376+i*8 to 383+i*8) := + std_logic_vector(to_unsigned(character'pos(c_layout(slave).description(i)), 8)); + end loop; + + for i in 0 to c_sdwb_words-1 loop + res(slave*c_sdwb_words + i) := + sdwb_device(i*c_wishbone_data_width to (i+1)*c_wishbone_data_width-1); + end loop; + end loop; + return res; + end f_build_rom; + + signal rom : t_rom := f_build_rom; + signal adr_reg : unsigned(c_rom_depth-1 downto 0); + +begin + -- Simple ROM; ignore we/sel/dat + slave_o.err <= '0'; + slave_o.rty <= '0'; + slave_o.stall <= '0'; + slave_o.int <= '0'; -- Tom sucks! This should not be here. + + slave_o.dat <= rom(to_integer(adr_reg)); + + slave_clk : process(clk_sys_i) + begin + if (rising_edge(clk_sys_i)) then + adr_reg <= unsigned(slave_i.adr(c_rom_depth+c_rom_lowbits-1 downto c_rom_lowbits)); + slave_o.ack <= slave_i.cyc and slave_i.stb; + end if; + end process; + +end rtl; diff --git a/modules/wishbone/wb_crossbar/xwb_crossbar.vhd b/modules/wishbone/wb_crossbar/xwb_crossbar.vhd index 17dbe3427472eb8dbe29dc3f3804740c0490c4b5..26109c4294c266b8040dab6444dc7ff74ee1c55a 100644 --- a/modules/wishbone/wb_crossbar/xwb_crossbar.vhd +++ b/modules/wishbone/wb_crossbar/xwb_crossbar.vhd @@ -18,9 +18,8 @@ -- All participants must support the same data bus width. -- -- If a master raises STB_O with an address not mapped by the crossbar, --- ERR_I will be raised. If the crossbar has overlapping address ranges, --- the lowest numbered slave is selected. If two masters address the same --- slave simultaneously, the lowest numbered master is granted access. +-- ERR_I will be raised. If two masters address the same slave +-- simultaneously, the lowest numbered master is granted access. -- -- The implementation of this crossbar locks a master to a slave so long as -- CYC_O is held high. @@ -40,6 +39,7 @@ ------------------------------------------------------------------------------- -- Revisions : -- Date Version Author Description +-- 2012-03-05 3.0 wterpstra made address generic and check overlap -- 2011-11-04 2.0 wterpstra timing improvements -- 2011-06-08 1.0 wterpstra import from SVN ------------------------------------------------------------------------------- @@ -54,8 +54,10 @@ entity xwb_crossbar is generic( g_num_masters : integer := 2; g_num_slaves : integer := 1; - g_registered : boolean := false - ); + g_registered : boolean := false; + -- Address of the slaves connected + g_address : t_wishbone_address_array; + g_mask : t_wishbone_address_array); port( clk_sys_i : in std_logic; rst_n_i : in std_logic; @@ -64,14 +66,40 @@ entity xwb_crossbar is slave_o : out t_wishbone_slave_out_array(g_num_masters-1 downto 0); -- Slave connections (INTERCON is a master) master_i : in t_wishbone_master_in_array(g_num_slaves-1 downto 0); - master_o : out t_wishbone_master_out_array(g_num_slaves-1 downto 0); - -- Address of the slaves connected - cfg_address_i : in t_wishbone_address_array(g_num_slaves-1 downto 0); - cfg_mask_i : in t_wishbone_address_array(g_num_slaves-1 downto 0) - ); + master_o : out t_wishbone_master_out_array(g_num_slaves-1 downto 0)); end xwb_crossbar; architecture rtl of xwb_crossbar is + alias c_address : t_wishbone_address_array(g_num_slaves-1 downto 0) is g_address; + alias c_mask : t_wishbone_address_array(g_num_slaves-1 downto 0) is g_mask; + + -- Confirm that no address ranges overlap + function f_ranges_ok + return boolean + is + constant zero : t_wishbone_address := (others => '0'); + begin + for i in 0 to g_num_slaves-2 loop + for j in i+1 to g_num_slaves-1 loop + assert not (((c_mask(i) and c_mask(j)) and (c_address(i) xor c_address(j))) = zero) + report "Address ranges must be distinct (slaves " & + Integer'image(i) & "[" & Integer'image(to_integer(unsigned(c_address(i)))) & "/" & + Integer'image(to_integer(unsigned(c_mask(i)))) & "] & " & + Integer'image(j) & "[" & Integer'image(to_integer(unsigned(c_address(j)))) & "/" & + Integer'image(to_integer(unsigned(c_mask(j)))) & "])" + severity Failure; + end loop; + end loop; + for i in 0 to g_num_slaves-1 loop + report "Mapping slave #" & + Integer'image(i) & "[" & Integer'image(to_integer(unsigned(c_address(i)))) & "/" & + Integer'image(to_integer(unsigned(c_mask(i)))) & "]" + severity Note; + end loop; + return true; + end f_ranges_ok; + constant c_ok : boolean := f_ranges_ok; + -- Crossbar connection matrix type matrix is array (g_num_masters-1 downto 0, g_num_slaves downto 0) of std_logic; @@ -132,20 +160,24 @@ architecture rtl of xwb_crossbar is variable output : std_logic_vector(width-1 downto 0); begin prev := input; - for l in 0 to stages-1 loop - for i in 0 to width-1 loop - if i >= pow2(l) - then output(i) := prev(i) or prev(i-pow2(l)); - else output(i) := prev(i); - end if; + if stages = 0 then + output := prev; + else + for l in 0 to stages-1 loop + for i in 0 to width-1 loop + if i >= pow2(l) + then output(i) := prev(i) or prev(i-pow2(l)); + else output(i) := prev(i); + end if; + end loop; + prev := output; end loop; - prev := output; - end loop; + end if; return output; end ks_OR; - -- Impure because it accesses cfg_{address_i, mask_i} - impure function matrix_logic( + -- Impure because it accesses c_{address, mask} + function matrix_logic( matrix_old : matrix; slave_i : t_wishbone_slave_in_array(g_num_masters-1 downto 0)) return matrix @@ -182,7 +214,7 @@ architecture rtl of xwb_crossbar is -- Decode the request address to see if master wants access for master in g_num_masters-1 downto 0 loop for slave in g_num_slaves-1 downto 0 loop - tmp := not vector_OR((slave_i(master).ADR and cfg_mask_i(slave)) xor cfg_address_i(slave)); + tmp := not vector_OR((slave_i(master).ADR and c_mask(slave)) xor c_address(slave)); tmp_column(slave) := tmp; request(master, slave) := slave_i(master).CYC and slave_i(master).STB and tmp; end loop; @@ -202,10 +234,12 @@ architecture rtl of xwb_crossbar is -- Grant to highest priority master selected(0, slave) := request(0, slave); -- master 0 always wins - for master in 1 to g_num_masters-1 loop - selected(master, slave) := -- only if requested and no lower requests - not tmp_row(master-1) and request(master, slave); - end loop; + if g_num_masters > 1 then + for master in 1 to g_num_masters-1 loop + selected(master, slave) := -- only if requested and no lower requests + not tmp_row(master-1) and request(master, slave); + end loop; + end if; end loop; -- Determine the master granted access diff --git a/modules/wishbone/wb_crossbar/xwb_sdwb_crossbar.vhd b/modules/wishbone/wb_crossbar/xwb_sdwb_crossbar.vhd new file mode 100644 index 0000000000000000000000000000000000000000..2583a46c18f7063a81cb25b9d7dc7a5d08fe0b9f --- /dev/null +++ b/modules/wishbone/wb_crossbar/xwb_sdwb_crossbar.vhd @@ -0,0 +1,162 @@ +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; +use work.wishbone_pkg.all; + +entity xwb_sdwb_crossbar is + generic( + g_num_masters : natural := 1; + g_num_slaves : natural := 1; + g_registered : boolean := false; + g_wraparound : boolean := true; + g_layout : t_sdwb_device_array; + g_sdwb_addr : t_wishbone_address); + port( + clk_sys_i : in std_logic; + rst_n_i : in std_logic; + -- Master connections (INTERCON is a slave) + slave_i : in t_wishbone_slave_in_array(g_num_masters-1 downto 0); + slave_o : out t_wishbone_slave_out_array(g_num_masters-1 downto 0); + -- Slave connections (INTERCON is a master) + master_i : in t_wishbone_master_in_array(g_num_slaves-1 downto 0); + master_o : out t_wishbone_master_out_array(g_num_slaves-1 downto 0)); +end xwb_sdwb_crossbar; + +architecture rtl of xwb_sdwb_crossbar is + alias c_layout : t_sdwb_device_array(g_num_slaves-1 downto 0) is g_layout; + + -- Step 1. Place the SDWB ROM on the bus + -- How much space does the ROM need? + constant c_used_entries : natural := c_layout'length + 1; + constant c_rom_entries : natural := 2**f_ceil_log2(c_used_entries); -- next power of 2 + constant c_sdwb_bytes : natural := c_sdwb_device_length / 8; + constant c_rom_bytes : natural := c_rom_entries * c_sdwb_bytes; + + -- Step 2. Find the size of the bus + function f_bus_end return unsigned is + variable result : unsigned(63 downto 0); + constant zero : t_wishbone_address := (others => '0'); + begin + -- The SDWB block must be aligned + assert (g_sdwb_addr and std_logic_vector(to_unsigned(c_rom_bytes - 1, c_wishbone_address_width))) = zero + report "SDWB address is not aligned. This is not supported by the crossbar." + severity Failure; + + if not g_wraparound then + result := (others => '0'); + for i in 0 to c_wishbone_address_width-1 loop + result(i) := '1'; + end loop; + else + -- The ROM will be an addressed slave as well + result := (others => '0'); + result(c_wishbone_address_width-1 downto 0) := unsigned(g_sdwb_addr); + result := result + to_unsigned(c_rom_bytes, 64) - 1; + + for i in c_layout'range loop + if c_layout(i).wbd_end > result then + result := c_layout(i).wbd_end; + end if; + end loop; + -- round result up to a power of two -1 + for i in 62 downto 0 loop + result(i) := result(i) or result(i+1); + end loop; + end if; + return result; + end f_bus_end; + + constant c_bus_end : unsigned(63 downto 0) := f_bus_end; + + -- Step 3. Map device address begin values + function f_addresses return t_wishbone_address_array is + variable result : t_wishbone_address_array(c_layout'range); + variable extend : unsigned(63 downto 0) := (others => '0'); + begin + for i in c_layout'range loop + result(i) := std_logic_vector(c_layout(i).wbd_begin(c_wishbone_address_width-1 downto 0)); + + -- Range must be valid + assert c_layout(i).wbd_begin <= c_layout(i).wbd_end + report "Wishbone slave device #" & Integer'image(i) & " (" & c_layout(i).description & ") wbd_begin address must precede wbd_end address." + severity Failure; + + -- Address must fit + extend(c_wishbone_address_width-1 downto 0) := unsigned(result(i)); + assert c_layout(i).wbd_begin = extend + report "Wishbone slave device #" & Integer'image(i) & " (" & c_layout(i).description & ") wbd_begin does not fit in t_wishbone_address." + severity Failure; + end loop; + return result; + end f_addresses; + + -- Step 3. Map device address end values + function f_masks return t_wishbone_address_array is + variable result : t_wishbone_address_array(c_layout'range); + variable size : unsigned(63 downto 0); + constant zero : unsigned(63 downto 0) := (others => '0'); + begin + for i in c_layout'range loop + size := c_layout(i).wbd_end - c_layout(i).wbd_begin; + + -- size must be of the form 000000...00001111...1 + assert (size and (size + to_unsigned(1, 64))) = zero + report "Wishbone slave device #" & Integer'image(i) & " (" & c_layout(i).description & ") has an address range size that is not a power of 2 minus one (" & Integer'image(to_integer(size)) & "). This is not supported by the crossbar." + severity Warning; + + -- fix the size up to the form 000...0001111...11 + for j in c_wishbone_address_width-2 downto 0 loop + size(j) := size(j) or size(j+1); + end loop; + + -- the base address must be aligned to the size + assert (c_layout(i).wbd_begin and size) = zero + report "Wishbone slave device #" & Integer'image(i) & " (" & c_layout(i).description & ") wbd_begin address is not aligned. This is not supported by the crossbar." + severity Failure; + + size := c_bus_end - size; + result(i) := std_logic_vector(size(c_wishbone_address_width-1 downto 0)); + end loop; + return result; + end f_masks; + + constant c_rom_mask : unsigned(63 downto 0) := + c_bus_end - to_unsigned(c_rom_bytes-1, 64); + constant c_sdwb_mask : t_wishbone_address := + std_logic_vector(c_rom_mask(c_wishbone_address_width-1 downto 0)); + constant c_address : t_wishbone_address_array(g_num_slaves downto 0) := + + g_sdwb_addr & f_addresses; + constant c_mask : t_wishbone_address_array(g_num_slaves downto 0) := + c_sdwb_mask & f_masks; + + signal master_i_1 : t_wishbone_master_in_array(g_num_slaves downto 0); + signal master_o_1 : t_wishbone_master_out_array(g_num_slaves downto 0); +begin + master_i_1(g_num_slaves-1 downto 0) <= master_i; + master_o <= master_o_1(g_num_slaves-1 downto 0); + + rom : sdwb_rom + generic map( + g_layout => c_layout, + g_bus_end => c_bus_end) + port map( + clk_sys_i => clk_sys_i, + slave_i => master_o_1(g_num_slaves), + slave_o => master_i_1(g_num_slaves)); + + crossbar : xwb_crossbar + generic map( + g_num_masters => g_num_masters, + g_num_slaves => g_num_slaves + 1, + g_registered => g_registered, + g_address => c_address, + g_mask => c_mask) + port map( + clk_sys_i => clk_sys_i, + rst_n_i => rst_n_i, + slave_i => slave_i, + slave_o => slave_o, + master_i => master_i_1, + master_o => master_o_1); +end rtl; diff --git a/modules/wishbone/wb_dma/Manifest.py b/modules/wishbone/wb_dma/Manifest.py new file mode 100644 index 0000000000000000000000000000000000000000..9f267a12524b759e23426b4bc8af2e18456ddccc --- /dev/null +++ b/modules/wishbone/wb_dma/Manifest.py @@ -0,0 +1 @@ +files = [ "xwb_dma.vhd" ]; diff --git a/modules/wishbone/wb_dma/xwb_dma.vhd b/modules/wishbone/wb_dma/xwb_dma.vhd new file mode 100644 index 0000000000000000000000000000000000000000..2430d7e14560e0ef85ccbbba7972e2063f528f85 --- /dev/null +++ b/modules/wishbone/wb_dma/xwb_dma.vhd @@ -0,0 +1,263 @@ +-- Register map: +-- 0x00 = read issue address +-- 0x04 = write issue address +-- 0x08 = read stride +-- 0x0C = write stride +-- 0x10 = transfer count +-- +-- Behaviour: +-- While (transfer count > 0) { +-- mem[write_issue_address] = mem[read_issue_address] +-- read_issue_address += read_stride +-- write_issue_address += write_stride +-- } +-- interrupt = (transfer_count == 0) && (transfer_count_was == 1) +-- +-- Usage: +-- 1. Fill in the issue and stride registers +-- 2. Write non-zero to the counter to initiate transfer +-- +-- Status information: +-- All registers can be inspected during the transfer +-- Interrupt line is raised upon completion + +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; +use work.wishbone_pkg.all; + +-- Assumption: wishbone_data_width >= wishbone_address_Width +entity xwb_dma is + generic( + -- Value 0 cannot stream + -- Value 1 only slaves with async ACK can stream + -- Value 2 only slaves with combined latency = 2 can stream + -- Value 3 only slaves with combined latency = 6 can stream + -- Value 4 only slaves with combined latency = 14 can stream + -- .... + logRingLen : integer := 4 + ); + port( + -- Common wishbone signals + clk_i : in std_logic; + rst_n_i : in std_logic; + -- Slave control port + slave_i : in t_wishbone_slave_in; + slave_o : out t_wishbone_slave_out; + -- Master reader port + r_master_i : in t_wishbone_master_in; + r_master_o : out t_wishbone_master_out; + -- Master writer port + w_master_i : in t_wishbone_master_in; + w_master_o : out t_wishbone_master_out; + -- Pulsed high completion signal + interrupt_o : out std_logic + ); +end xwb_dma; + +architecture rtl of xwb_dma is + constant ringLen : integer := 2**logRingLen; + type ring_t is array (ringLen-1 downto 0) of t_wishbone_data; + + -- Ring buffer for shipping data from read master to write master + signal ring : ring_t; + + -- State registers (pointer into the ring) + -- Invariant: read_issue_offset >= read_result_offset >= write_issue_offset >= write_result_offset + -- read_issue_offset - write_result_offset <= ringLen (*NOT* strict '<') + signal read_issue_offset : unsigned(logRingLen downto 0); + signal read_result_offset : unsigned(logRingLen downto 0); + signal write_issue_offset : unsigned(logRingLen downto 0); + signal write_result_offset : unsigned(logRingLen downto 0); + + -- DMA control registers + signal read_issue_address : t_wishbone_address; + signal write_issue_address : t_wishbone_address; + signal read_stride : t_wishbone_address; + signal write_stride : t_wishbone_address; + signal transfer_count : t_wishbone_address; + -- result status: fail/ok ? + + -- Registered wishbone control signals + signal r_master_o_CYC : std_logic; + signal w_master_o_CYC : std_logic; + signal r_master_o_STB : std_logic; + signal w_master_o_STB : std_logic; + signal slave_o_ACK : std_logic; + signal slave_o_DAT : t_wishbone_data; + + function active_high(x : boolean) + return std_logic is + begin + if (x) then + return '1'; + else + return '0'; + end if; + end active_high; + + function index(x : unsigned(logRingLen downto 0)) + return integer is + begin + if logRingLen > 0 then + return to_integer(x(logRingLen-1 downto 0)); + else + return 0; + end if; + end index; + + procedure update(signal o : out t_wishbone_address) is + begin + for i in (c_wishbone_data_width/8)-1 downto 0 loop + if slave_i.SEL(i) = '1' then + o(i*8+7 downto i*8) <= slave_i.DAT(i*8+7 downto i*8); + end if; + end loop; + end update; + +begin + -- Hard-wired slave pins + slave_o.ACK <= slave_o_ACK; + slave_o.ERR <= '0'; + slave_o.RTY <= '0'; + slave_o.STALL <= '0'; + slave_o.DAT <= slave_o_DAT; + + -- Hard-wired master pins + r_master_o.CYC <= r_master_o_CYC; + w_master_o.CYC <= w_master_o_CYC; + r_master_o.STB <= r_master_o_STB; + w_master_o.STB <= w_master_o_STB; + r_master_o.ADR <= read_issue_address; + w_master_o.ADR <= write_issue_address; + r_master_o.SEL <= (others => '1'); + w_master_o.SEL <= (others => '1'); + r_master_o.WE <= '0'; + w_master_o.WE <= '1'; + r_master_o.DAT <= (others => '0'); + w_master_o.DAT <= ring(index(write_issue_offset)); + + main : process(clk_i) + variable read_issue_progress : boolean; + variable read_result_progress : boolean; + variable write_issue_progress : boolean; + variable write_result_progress : boolean; + + variable new_read_issue_offset : unsigned(logRingLen downto 0); + variable new_read_result_offset : unsigned(logRingLen downto 0); + variable new_write_issue_offset : unsigned(logRingLen downto 0); + variable new_write_result_offset : unsigned(logRingLen downto 0); + variable new_transfer_count : t_wishbone_address; + + variable ring_boundary : boolean; + variable ring_high : boolean; + variable ring_full : boolean; + variable ring_empty : boolean; + variable done_transfer : boolean; + begin + if (rising_edge(clk_i)) then + if (rst_n_i = '0') then + read_issue_offset <= (others => '0'); + read_result_offset <= (others => '0'); + write_issue_offset <= (others => '0'); + write_result_offset <= (others => '0'); + + read_issue_address <= (others => '0'); + write_issue_address <= (others => '0'); + read_stride <= (others => '0'); + write_stride <= (others => '0'); + transfer_count <= (others => '0'); + + r_master_o_CYC <= '0'; + w_master_o_CYC <= '0'; + r_master_o_STB <= '0'; + w_master_o_STB <= '0'; + slave_o_ACK <= '0'; + slave_o_DAT <= (others => '0'); + interrupt_o <= '0'; + else + -- Output any read the user requests + case to_integer(unsigned(slave_i.ADR(4 downto 2))) is + when 0 => slave_o_DAT <= read_issue_address; + when 1 => slave_o_DAT <= write_issue_address; + when 2 => slave_o_DAT <= read_stride; + when 3 => slave_o_DAT <= write_stride; + when 4 => slave_o_DAT <= transfer_count; + when others => slave_o_DAT <= (others => '0'); + end case; + + -- Detect bus progress + read_issue_progress := r_master_o_STB = '1' and r_master_i.STALL = '0'; + write_issue_progress := w_master_o_STB = '1' and w_master_i.STALL = '0'; + read_result_progress := r_master_o_CYC = '1' and (r_master_i.ACK = '1' or r_master_i.ERR = '1' or r_master_i.RTY = '1'); + write_result_progress := w_master_o_CYC = '1' and (w_master_i.ACK = '1' or w_master_i.ERR = '1' or w_master_i.RTY = '1'); + + -- Advance read pointers + if read_issue_progress then + read_issue_address <= std_logic_vector(unsigned(read_issue_address) + unsigned(read_stride)); + new_read_issue_offset := read_issue_offset + 1; + new_transfer_count := std_logic_vector(unsigned(transfer_count) - 1); + else + new_read_issue_offset := read_issue_offset; + new_transfer_count := transfer_count; + end if; + if read_result_progress then + ring(index(read_result_offset)) <= r_master_i.DAT; + new_read_result_offset := read_result_offset + 1; + else + new_read_result_offset := read_result_offset; + end if; + + -- Advance write pointers + if write_issue_progress then + write_issue_address <= std_logic_vector(unsigned(write_issue_address) + unsigned(write_stride)); + new_write_issue_offset := write_issue_offset + 1; + else + new_write_issue_offset := write_issue_offset; + end if; + if write_result_progress then + new_write_result_offset := write_result_offset + 1; + else + new_write_result_offset := write_result_offset; + end if; + + ring_boundary := index(new_read_issue_offset) = index(new_write_result_offset); + ring_high := new_read_issue_offset(logRingLen) /= new_write_result_offset(logRingLen); + ring_full := ring_boundary and ring_high; + ring_empty := ring_boundary and not ring_high; + + -- Shorten the critical path by comparing to the undecremented value + --done_transfer := unsigned(new_transfer_count) = 0; + done_transfer := unsigned(transfer_count(c_wishbone_address_width-1 downto 1)) = 0 + and (read_issue_progress or transfer_count(0) = '0'); + + r_master_o_STB <= active_high (not ring_full and not done_transfer); + r_master_o_CYC <= active_high((not ring_full and not done_transfer) or + (new_read_result_offset /= new_read_issue_offset)); + w_master_o_STB <= active_high (new_write_issue_offset /= new_read_result_offset); + w_master_o_CYC <= active_high (new_write_result_offset /= new_read_result_offset); + interrupt_o <= active_high (write_result_progress and done_transfer and ring_empty); + + transfer_count <= new_transfer_count; + read_issue_offset <= new_read_issue_offset; + read_result_offset <= new_read_result_offset; + write_issue_offset <= new_write_issue_offset; + write_result_offset <= new_write_result_offset; + + -- Control logic + if (slave_i.CYC = '1' and slave_i.STB = '1' and slave_i.WE = '1') then + case to_integer(unsigned(slave_i.ADR(4 downto 2))) is + when 0 => update(read_issue_address); + when 1 => update(write_issue_address); + when 2 => update(read_stride); + when 3 => update(write_stride); + when 4 => update(transfer_count); + when others => null; + end case; + end if; + + slave_o_ACK <= slave_i.CYC and slave_i.STB; + end if; + end if; + end process; +end rtl; diff --git a/modules/wishbone/wb_dpram/xwb_dpram.vhd b/modules/wishbone/wb_dpram/xwb_dpram.vhd index 1d7b6ca908eb2df50f90c653b3347b16ea2985d6..57b634145c7f72fe1a73c33283cbbc0b8c8a599a 100644 --- a/modules/wishbone/wb_dpram/xwb_dpram.vhd +++ b/modules/wishbone/wb_dpram/xwb_dpram.vhd @@ -36,6 +36,7 @@ entity xwb_dpram is generic( g_size : natural := 16384; g_init_file : string := ""; + g_init_value : t_xwb_dpram_init := c_xwb_dpram_init_nothing; g_must_have_init_file : boolean := true; g_slave1_interface_mode : t_wishbone_interface_mode; g_slave2_interface_mode : t_wishbone_interface_mode; @@ -116,6 +117,7 @@ begin g_with_byte_enable => true, g_addr_conflict_resolution => "read_first", g_init_file => g_init_file, + g_init_value => g_init_value, g_dual_clock => false ) port map( diff --git a/modules/wishbone/wb_lm32/gen_lmcores.py b/modules/wishbone/wb_lm32/gen_lmcores.py index 60faf97ac4ea0d27459b58e8169d352d420feba1..fc5248122f5c88f5efd7cfb68acf9eab98c23118 100755 --- a/modules/wishbone/wb_lm32/gen_lmcores.py +++ b/modules/wishbone/wb_lm32/gen_lmcores.py @@ -324,7 +324,7 @@ port map( if I_CYC = '1' and inst_was_busy = '0' then inst_addr := I_ADR; if I_CTI = "010" then - inst_length := dcache_burst_length; + inst_length := icache_burst_length; else inst_length := 1; end if; diff --git a/modules/wishbone/wb_lm32/generated/lm32_allprofiles.v b/modules/wishbone/wb_lm32/generated/lm32_allprofiles.v index 6465a38564d4f741a027b3501a1a005cb1efdfb6..e59b37b1007b8308eae561cb22f2faaf4be0466a 100644 --- a/modules/wishbone/wb_lm32/generated/lm32_allprofiles.v +++ b/modules/wishbone/wb_lm32/generated/lm32_allprofiles.v @@ -53,6 +53,8 @@ + + @@ -78,13 +80,20 @@ - - - - + + - + + + + + + + + + + @@ -222,24 +231,25 @@ - + + - - + + + + - - @@ -342,24 +352,34 @@ - - + + + + + + + + + + - + - + + + @@ -371,6 +391,8 @@ + + @@ -378,28 +400,29 @@ - - + - - + + + + + + + + + + + - - - - - - - - + @@ -557,7 +580,7 @@ -module lm32_top_full ( +module lm32_top_full_debug ( clk_i, rst_i, @@ -714,14 +737,15 @@ wire [ (2-1):0] D_BTE_O; - - - - - - - +wire [ 7:0] jtag_reg_d; +wire [ 7:0] jtag_reg_q; +wire jtag_update; +wire [2:0] jtag_reg_addr_d; +wire [2:0] jtag_reg_addr_q; +wire jtck; +wire jrstn; + @@ -800,7 +824,7 @@ endfunction -lm32_cpu_full cpu ( +lm32_cpu_full_debug cpu ( .clk_i (clk_i), @@ -821,12 +845,13 @@ lm32_cpu_full cpu ( - - - - - + + .jtag_clk (jtck), + .jtag_update (jtag_update), + .jtag_reg_q (jtag_reg_q), + .jtag_reg_addr_q (jtag_reg_addr_q), + @@ -855,9 +880,10 @@ lm32_cpu_full cpu ( - - + .jtag_reg_d (jtag_reg_d), + .jtag_reg_addr_d (jtag_reg_addr_d), + @@ -892,20 +918,21 @@ lm32_cpu_full cpu ( .D_BTE_O (D_BTE_O) ); - - + + +jtag_cores jtag_cores ( - - - - - - - - + .reg_d (jtag_reg_d), + .reg_addr_d (jtag_reg_addr_d), - + .reg_update (jtag_update), + .reg_q (jtag_reg_q), + .reg_addr_q (jtag_reg_addr_q), + .jtck (jtck), + .jrstn (jrstn) + ); + endmodule @@ -1277,7 +1304,7 @@ endmodule -module lm32_mc_arithmetic_full ( +module lm32_mc_arithmetic_full_debug ( clk_i, rst_i, @@ -1943,7 +1970,7 @@ endmodule -module lm32_cpu_full ( +module lm32_cpu_full_debug ( clk_i, @@ -1964,12 +1991,13 @@ module lm32_cpu_full ( - - - - - + + jtag_clk, + jtag_update, + jtag_reg_q, + jtag_reg_addr_q, + @@ -1998,9 +2026,10 @@ module lm32_cpu_full ( - - + jtag_reg_d, + jtag_reg_addr_d, + @@ -2041,8 +2070,9 @@ module lm32_cpu_full ( parameter eba_reset = 32'h00000000; - +parameter deba_reset = 32'h10000000; + @@ -2078,11 +2108,11 @@ parameter dcache_limit = 32'h7fffffff; - - -parameter watchpoints = 0; +parameter watchpoints = 32'h4; + + @@ -2124,11 +2154,12 @@ input [ (32-1):0] interrupt; - - - - +input jtag_clk; +input jtag_update; +input [ 7:0] jtag_reg_q; +input [2:0] jtag_reg_addr_q; + @@ -2168,11 +2199,12 @@ input D_RTY_I; - - - - +output [ 7:0] jtag_reg_d; +wire [ 7:0] jtag_reg_d; +output [2:0] jtag_reg_addr_d; +wire [2:0] jtag_reg_addr_d; + @@ -2352,14 +2384,15 @@ wire [ (5-1):0] write_idx_d; reg [ (5-1):0] write_idx_x; reg [ (5-1):0] write_idx_m; reg [ (5-1):0] write_idx_w; -wire [ (3-1):0] csr_d; -reg [ (3-1):0] csr_x; +wire [ (5-1):0] csr_d; +reg [ (5-1):0] csr_x; wire [ (3-1):0] condition_d; reg [ (3-1):0] condition_x; - - +wire break_d; +reg break_x; + wire scall_d; reg scall_x; @@ -2372,14 +2405,16 @@ reg eret_m; - - - - - + +wire bret_d; +reg bret_x; +wire bret_q_x; +reg bret_m; + + wire csr_write_enable_d; reg csr_write_enable_x; @@ -2585,25 +2620,32 @@ wire stall_wb_load; - - - - - - - - + +wire [ (32-1):0] jtx_csr_read_data; +wire [ (32-1):0] jrx_csr_read_data; + - - +wire jtag_csr_write_enable; +wire [ (32-1):0] jtag_csr_write_data; +wire [ (5-1):0] jtag_csr; +wire jtag_read_enable; +wire [ 7:0] jtag_read_data; +wire jtag_write_enable; +wire [ 7:0] jtag_write_data; +wire [ (32-1):0] jtag_address; +wire jtag_access_complete; - + +wire jtag_break; + + + @@ -2636,8 +2678,9 @@ wire kill_w; reg [ (clogb2(32'h7fffffff-32'h0)-2)+2-1:8] eba; - +reg [ (clogb2(32'h7fffffff-32'h0)-2)+2-1:8] deba; + reg [ (3-1):0] eid_x; @@ -2647,34 +2690,39 @@ reg [ (3-1):0] eid_x; - - - - - - - + + +wire dc_ss; + +wire dc_re; +wire exception_x; +reg exception_m; +wire debug_exception_x; +reg debug_exception_m; +reg debug_exception_w; +wire debug_exception_q_w; +wire non_debug_exception_x; +reg non_debug_exception_m; +reg non_debug_exception_w; +wire non_debug_exception_q_w; - + -wire exception_x; -reg exception_m; -reg exception_w; -wire exception_q_w; - + - - +wire reset_exception; + + @@ -2682,9 +2730,10 @@ wire interrupt_exception; - - +wire breakpoint_exception; +wire watchpoint_exception; + @@ -2768,7 +2817,7 @@ endfunction -lm32_instruction_unit_full #( +lm32_instruction_unit_full_debug #( .associativity (icache_associativity), .sets (icache_sets), .bytes_per_line (icache_bytes_per_line), @@ -2827,11 +2876,12 @@ lm32_instruction_unit_full #( - - - - + .jtag_read_enable (jtag_read_enable), + .jtag_write_enable (jtag_write_enable), + .jtag_write_data (jtag_write_data), + .jtag_address (jtag_address), + @@ -2867,9 +2917,10 @@ lm32_instruction_unit_full #( - - + .jtag_read_data (jtag_read_data), + .jtag_access_complete (jtag_access_complete), + @@ -2885,7 +2936,7 @@ lm32_instruction_unit_full #( ); -lm32_decoder_full decoder ( +lm32_decoder_full_debug decoder ( .instruction (instruction_d), @@ -2966,14 +3017,16 @@ lm32_decoder_full decoder ( .branch_reg (branch_reg_d), .condition (condition_d), - + .break_opcode (break_d), + .scall (scall_d), .eret (eret_d), - + .bret (bret_d), + @@ -2983,7 +3036,7 @@ lm32_decoder_full decoder ( ); -lm32_load_store_unit_full #( +lm32_load_store_unit_full_debug #( .associativity (dcache_associativity), .sets (dcache_sets), .bytes_per_line (dcache_bytes_per_line), @@ -3119,7 +3172,7 @@ lm32_multiplier multiplier ( -lm32_mc_arithmetic_full mc_arithmetic ( +lm32_mc_arithmetic_full_debug mc_arithmetic ( .clk_i (clk_i), .rst_i (rst_i), @@ -3158,7 +3211,7 @@ lm32_mc_arithmetic_full mc_arithmetic ( -lm32_interrupt_full interrupt_unit ( +lm32_interrupt_full_debug interrupt_unit ( .clk_i (clk_i), .rst_i (rst_i), @@ -3167,17 +3220,18 @@ lm32_interrupt_full interrupt_unit ( .stall_x (stall_x), - - - - .exception (exception_q_w), + .non_debug_exception (non_debug_exception_q_w), + .debug_exception (debug_exception_q_w), + + .eret_q_x (eret_q_x), - + .bret_q_x (bret_q_x), + .csr (csr_x), .csr_write_data (operand_1_x), @@ -3192,95 +3246,117 @@ lm32_interrupt_full interrupt_unit ( - + +lm32_jtag_full_debug jtag ( - - + .clk_i (clk_i), + .rst_i (rst_i), - - - - + .jtag_clk (jtag_clk), + .jtag_update (jtag_update), + .jtag_reg_q (jtag_reg_q), + .jtag_reg_addr_q (jtag_reg_addr_q), + + + .csr (csr_x), + .csr_write_data (operand_1_x), + .csr_write_enable (csr_write_enable_q_x), + .stall_x (stall_x), - - - - + + + .jtag_read_data (jtag_read_data), + .jtag_access_complete (jtag_access_complete), - - + + + .exception_q_w (debug_exception_q_w || non_debug_exception_q_w), - + + + .jtx_csr_read_data (jtx_csr_read_data), + .jrx_csr_read_data (jrx_csr_read_data), - - + + + .jtag_csr_write_enable (jtag_csr_write_enable), + .jtag_csr_write_data (jtag_csr_write_data), + .jtag_csr (jtag_csr), + .jtag_read_enable (jtag_read_enable), + .jtag_write_enable (jtag_write_enable), + .jtag_write_data (jtag_write_data), + .jtag_address (jtag_address), - - - - - - - + + + .jtag_break (jtag_break), + .jtag_reset (reset_exception), - - - - - - + .jtag_reg_d (jtag_reg_d), + .jtag_reg_addr_d (jtag_reg_addr_d) + ); + - - - - + +lm32_debug_full_debug #( + .breakpoints (breakpoints), + .watchpoints (watchpoints) + ) hw_debug ( - - - - - - - - - - - - - + .clk_i (clk_i), + .rst_i (rst_i), + .pc_x (pc_x), + .load_x (load_x), + .store_x (store_x), + .load_store_address_x (adder_result_x), + .csr_write_enable_x (csr_write_enable_q_x), + .csr_write_data (operand_1_x), + .csr_x (csr_x), + + .jtag_csr_write_enable (jtag_csr_write_enable), + .jtag_csr_write_data (jtag_csr_write_data), + .jtag_csr (jtag_csr), - - - - - - - + + + .eret_q_x (eret_q_x), + .bret_q_x (bret_q_x), + .stall_x (stall_x), + .exception_x (exception_x), + .q_x (q_x), + + + .dcache_refill_request (dcache_refill_request), + - - - - - + + .dc_ss (dc_ss), + + + .dc_re (dc_re), + .bp_match (bp_match), + .wp_match (wp_match) + ); + @@ -3780,21 +3856,25 @@ assign kill_w = 1'b0 - - - - - - - - +assign breakpoint_exception = ( ( (break_x == 1'b1) + || (bp_match == 1'b1) + ) + && (valid_x == 1'b1) + ) + + || (jtag_break == 1'b1) + + + ; + - +assign watchpoint_exception = wp_match == 1'b1; + @@ -3821,38 +3901,17 @@ assign system_call_exception = ( (scall_x == 1'b1) ); - - - - - - - - - - +assign debug_exception_x = (breakpoint_exception == 1'b1) + || (watchpoint_exception == 1'b1) + ; - - +assign non_debug_exception_x = (system_call_exception == 1'b1) + + || (reset_exception == 1'b1) - - - - - - - - - - - - - - -assign exception_x = (system_call_exception == 1'b1) || (instruction_bus_error_exception == 1'b1) @@ -3868,8 +3927,9 @@ assign exception_x = (system_call_exception == 1'b1) || ( (interrupt_exception == 1'b1) - + && (dc_ss == 1'b0) + @@ -3881,27 +3941,55 @@ assign exception_x = (system_call_exception == 1'b1) ; + +assign exception_x = (debug_exception_x == 1'b1) || (non_debug_exception_x == 1'b1); + + + + + + + + + + + + + + + + + + + + + always @(*) begin + + + + if (reset_exception == 1'b1) + eid_x = 3'h0; + else - - - - - - - + - - - + if (data_bus_error_exception == 1'b1) + eid_x = 3'h4; + else + + if (breakpoint_exception == 1'b1) + eid_x = 3'd1; + else + @@ -3914,10 +4002,11 @@ begin - - - + if (watchpoint_exception == 1'b1) + eid_x = 3'd3; + else + @@ -3930,8 +4019,9 @@ begin if ( (interrupt_exception == 1'b1) - + && (dc_ss == 1'b0) + ) eid_x = 3'h6; @@ -3968,18 +4058,19 @@ assign stall_d = (stall_x == 1'b1) && (kill_d == 1'b0) ) - - - - - - - - - - - + || ( ( (break_d == 1'b1) + || (bret_d == 1'b1) + ) + && ( (load_q_x == 1'b1) + || (store_q_x == 1'b1) + || (load_q_m == 1'b1) + || (store_q_m == 1'b1) + || (D_CYC_O == 1'b1) + ) + && (kill_d == 1'b0) + ) + || ( (csr_write_enable_d == 1'b1) && (load_q_x == 1'b1) @@ -4085,21 +4176,24 @@ assign q_x = (valid_x == 1'b1) && (kill_x == 1'b0); assign csr_write_enable_q_x = (csr_write_enable_x == 1'b1) && (q_x == 1'b1); assign eret_q_x = (eret_x == 1'b1) && (q_x == 1'b1); - +assign bret_q_x = (bret_x == 1'b1) && (q_x == 1'b1); + assign load_q_x = (load_x == 1'b1) && (q_x == 1'b1) - + && (bp_match == 1'b0) + ; assign store_q_x = (store_x == 1'b1) && (q_x == 1'b1) - + && (bp_match == 1'b0) + ; @@ -4110,12 +4204,12 @@ assign q_m = (valid_m == 1'b1) && (kill_m == 1'b0) && (exception_m == 1'b0); assign load_q_m = (load_m == 1'b1) && (q_m == 1'b1); assign store_q_m = (store_m == 1'b1) && (q_m == 1'b1); - - - -assign exception_q_w = ((exception_w == 1'b1) && (valid_w == 1'b1)); +assign debug_exception_q_w = ((debug_exception_w == 1'b1) && (valid_w == 1'b1)); +assign non_debug_exception_q_w = ((non_debug_exception_w == 1'b1) && (valid_w == 1'b1)); + + assign write_enable_q_x = (write_enable_x == 1'b1) && (valid_x == 1'b1) && (branch_flushX_m == 1'b0); @@ -4131,19 +4225,12 @@ assign cfg = { breakpoints[3:0], interrupts[5:0], - - - 1'b0, + 1'b1, - - - 1'b0, - - @@ -4152,11 +4239,18 @@ assign cfg = { + + 1'b1, + - 1'b0, + + + 1'b1, + + @@ -4238,16 +4332,17 @@ assign cfg2 = { assign iflush = ( (csr_write_enable_d == 1'b1) - && (csr_d == 3'h3) + && (csr_d == 5'h3) && (stall_d == 1'b0) && (kill_d == 1'b0) && (valid_d == 1'b1)) - - - + || + ( (jtag_csr_write_enable == 1'b1) + && (jtag_csr == 5'h3)) + ; @@ -4255,20 +4350,21 @@ assign iflush = ( (csr_write_enable_d == 1'b1) assign dflush_x = ( (csr_write_enable_q_x == 1'b1) - && (csr_x == 3'h4)) + && (csr_x == 5'h4)) - - - + || + ( (jtag_csr_write_enable == 1'b1) + && (jtag_csr == 5'h4)) + ; -assign csr_d = read_idx_0_d[ (3-1):0]; +assign csr_d = read_idx_0_d[ (5-1):0]; always @(*) @@ -4276,27 +4372,29 @@ begin case (csr_x) - 3'h0, - 3'h1, - 3'h2: csr_read_data_x = interrupt_csr_read_data_x; + 5'h0, + 5'h1, + 5'h2: csr_read_data_x = interrupt_csr_read_data_x; - 3'h6: csr_read_data_x = cfg; - 3'h7: csr_read_data_x = {eba, 8'h00}; + 5'h6: csr_read_data_x = cfg; + 5'h7: csr_read_data_x = {eba, 8'h00}; - + 5'h9: csr_read_data_x = {deba, 8'h00}; + - - + 5'he: csr_read_data_x = jtx_csr_read_data; + 5'hf: csr_read_data_x = jrx_csr_read_data; + - 3'ha: csr_read_data_x = cfg2; + 5'ha: csr_read_data_x = cfg2; default: csr_read_data_x = { 32{1'bx}}; endcase @@ -4313,33 +4411,37 @@ begin eba <= eba_reset[ (clogb2(32'h7fffffff-32'h0)-2)+2-1:8]; else begin - if ((csr_write_enable_q_x == 1'b1) && (csr_x == 3'h7) && (stall_x == 1'b0)) + if ((csr_write_enable_q_x == 1'b1) && (csr_x == 5'h7) && (stall_x == 1'b0)) eba <= operand_1_x[ (clogb2(32'h7fffffff-32'h0)-2)+2-1:8]; - - + if ((jtag_csr_write_enable == 1'b1) && (jtag_csr == 5'h7)) + eba <= jtag_csr_write_data[ (clogb2(32'h7fffffff-32'h0)-2)+2-1:8]; + end end - - - - - - - - - - - - +always @(posedge clk_i ) +begin + if (rst_i == 1'b1) + deba <= deba_reset[ (clogb2(32'h7fffffff-32'h0)-2)+2-1:8]; + else + begin + if ((csr_write_enable_q_x == 1'b1) && (csr_x == 5'h9) && (stall_x == 1'b0)) + deba <= operand_1_x[ (clogb2(32'h7fffffff-32'h0)-2)+2-1:8]; + + if ((jtag_csr_write_enable == 1'b1) && (jtag_csr == 5'h9)) + deba <= jtag_csr_write_data[ (clogb2(32'h7fffffff-32'h0)-2)+2-1:8]; + + end +end + @@ -4521,7 +4623,7 @@ begin m_bypass_enable_x <= 1'b0; write_enable_x <= 1'b0; write_idx_x <= { 5{1'b0}}; - csr_x <= { 3{1'b0}}; + csr_x <= { 5{1'b0}}; load_x <= 1'b0; store_x <= 1'b0; size_x <= { 2{1'b0}}; @@ -4544,14 +4646,16 @@ begin branch_predict_taken_x <= 1'b0; condition_x <= 3'b000; - + break_x <= 1'b0; + scall_x <= 1'b0; eret_x <= 1'b0; - + bret_x <= 1'b0; + @@ -4595,9 +4699,10 @@ begin - - + debug_exception_m <= 1'b0; + non_debug_exception_m <= 1'b0; + operand_w <= { 32{1'b0}}; w_result_sel_load_w <= 1'b0; @@ -4609,12 +4714,12 @@ begin write_idx_w <= { 5{1'b0}}; write_enable_w <= 1'b0; - - - - exception_w <= 1'b0; + debug_exception_w <= 1'b0; + non_debug_exception_w <= 1'b0; + + @@ -4695,8 +4800,9 @@ begin condition_x <= condition_d; csr_write_enable_x <= csr_write_enable_d; - + break_x <= break_d; + scall_x <= scall_d; @@ -4706,8 +4812,9 @@ begin eret_x <= eret_d; - + bret_x <= bret_d; + write_enable_x <= write_enable_d; end @@ -4759,40 +4866,40 @@ begin + - - - - - - - - - if (exception_x == 1'b1) + if (non_debug_exception_x == 1'b1) write_idx_m <= 5'd30; + else if (debug_exception_x == 1'b1) + write_idx_m <= 5'd31; else write_idx_m <= write_idx_x; + + + + + condition_met_m <= condition_met_x; - - - - - - - - - - - branch_target_m <= exception_x == 1'b1 ? {eba, eid_x, {3{1'b0}}} : branch_target_x; + if (exception_x == 1'b1) + if ((dc_re == 1'b1) + || ((debug_exception_x == 1'b1) + && (non_debug_exception_x == 1'b0))) + branch_target_m <= {deba, eid_x, {3{1'b0}}}; + else + branch_target_m <= {eba, eid_x, {3{1'b0}}}; + else + branch_target_m <= branch_target_x; + + @@ -4805,14 +4912,16 @@ begin eret_m <= eret_q_x; - + bret_m <= bret_q_x; + write_enable_m <= exception_x == 1'b1 ? 1'b1 : write_enable_x; - - + debug_exception_m <= debug_exception_x; + non_debug_exception_m <= non_debug_exception_x; + end @@ -4827,8 +4936,9 @@ begin data_bus_error_exception_m <= (data_bus_error_exception == 1'b1) - + && (reset_exception == 1'b0) + ; @@ -4860,12 +4970,12 @@ begin write_enable_w <= write_enable_m; - - - - exception_w <= exception_m; + debug_exception_w <= debug_exception_m; + non_debug_exception_w <= non_debug_exception_m; + + @@ -5411,7 +5521,7 @@ endmodule -module lm32_load_store_unit_full ( +module lm32_load_store_unit_full_debug ( clk_i, rst_i, @@ -5789,7 +5899,7 @@ endfunction -lm32_dcache_full #( +lm32_dcache_full_debug #( .associativity (associativity), .sets (sets), .bytes_per_line (bytes_per_line), @@ -6741,7 +6851,7 @@ endmodule -module lm32_decoder_full ( +module lm32_decoder_full_debug ( instruction, @@ -6822,14 +6932,16 @@ module lm32_decoder_full ( bi_conditional, bi_unconditional, - + break_opcode, + scall, eret, - + bret, + @@ -6965,18 +7077,20 @@ wire bi_conditional; output bi_unconditional; wire bi_unconditional; - - +output break_opcode; +wire break_opcode; + output scall; wire scall; output eret; wire eret; - - +output bret; +wire bret; + @@ -7340,14 +7454,16 @@ assign branch = bra | call; assign branch_reg = op_call | op_b; assign condition = instruction[28:26]; - +assign break_opcode = op_raise & ~instruction[2]; + assign scall = op_raise & instruction[2]; assign eret = op_b & (instruction[25:21] == 5'd30); - +assign bret = op_b & (instruction[25:21] == 5'd31); + @@ -7779,7 +7895,7 @@ endmodule -module lm32_icache_full ( +module lm32_icache_full_debug ( clk_i, rst_i, @@ -8625,7 +8741,7 @@ endmodule -module lm32_dcache_full ( +module lm32_dcache_full_debug ( clk_i, rst_i, @@ -9481,135 +9597,162 @@ endmodule - - - - - - + + + + + + + + + + + + +module lm32_debug_full_debug ( - - - - - - - - - - - - - + clk_i, + rst_i, + pc_x, + load_x, + store_x, + load_store_address_x, + csr_write_enable_x, + csr_write_data, + csr_x, + + jtag_csr_write_enable, + jtag_csr_write_data, + jtag_csr, - - - - - + + + + eret_q_x, + bret_q_x, + stall_x, + exception_x, + q_x, + + + dcache_refill_request, - + + + + dc_ss, - - - - - + dc_re, + bp_match, + wp_match + ); - - +parameter breakpoints = 0; +parameter watchpoints = 0; - - +input clk_i; +input rst_i; - - - - - - - +input [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] pc_x; +input load_x; +input store_x; +input [ (32-1):0] load_store_address_x; +input csr_write_enable_x; +input [ (32-1):0] csr_write_data; +input [ (5-1):0] csr_x; + + +input jtag_csr_write_enable; +input [ (32-1):0] jtag_csr_write_data; +input [ (5-1):0] jtag_csr; - - - + + +input eret_q_x; +input bret_q_x; +input stall_x; +input exception_x; +input q_x; + + +input dcache_refill_request; - - - - - + - + +output dc_ss; +reg dc_ss; - - - - - - - - +output dc_re; +reg dc_re; +output bp_match; +wire bp_match; +output wp_match; +wire wp_match; - +genvar i; - - - +reg [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] bp_a[0:breakpoints-1]; +reg bp_e[0:breakpoints-1]; +wire [0:breakpoints-1]bp_match_n; - - - +reg [ 1:0] wpc_c[0:watchpoints-1]; +reg [ (32-1):0] wp[0:watchpoints-1]; +wire [0:watchpoints]wp_match_n; + +wire debug_csr_write_enable; +wire [ (32-1):0] debug_csr_write_data; +wire [ (5-1):0] debug_csr; + + - - - + +reg [ 2:0] state; - + - @@ -9617,48 +9760,15 @@ endmodule - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -9667,132 +9777,225 @@ endmodule - - - - - - - - - - - - - - - - - - + +function integer clogb2; +input [31:0] value; +begin + for (clogb2 = 0; value > 0; clogb2 = clogb2 + 1) + value = value >> 1; +end +endfunction +function integer clogb2_v1; +input [31:0] value; +reg [31:0] i; +reg [31:0] temp; +begin + temp = 0; + i = 0; + for (i = 0; temp < value; i = i + 1) + temp = 1<<i; + clogb2_v1 = i-1; +end +endfunction - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +generate + for (i = 0; i < breakpoints; i = i + 1) + begin : bp_comb +assign bp_match_n[i] = ((bp_a[i] == pc_x) && (bp_e[i] == 1'b1)); + end +endgenerate +generate + + if (breakpoints > 0) +assign bp_match = (|bp_match_n) || (state == 3'b011); + else +assign bp_match = state == 3'b011; + + - - - - - - - + + + +endgenerate - - + +generate + for (i = 0; i < watchpoints; i = i + 1) + begin : wp_comb +assign wp_match_n[i] = (wp[i] == load_store_address_x) && ((load_x & wpc_c[i][0]) | (store_x & wpc_c[i][1])); + end +endgenerate +generate + if (watchpoints > 0) +assign wp_match = |wp_match_n; + else +assign wp_match = 1'b0; +endgenerate - - - - - - - - - - - - - - - - - - - - - - - - + + + +assign debug_csr_write_enable = (csr_write_enable_x == 1'b1) || (jtag_csr_write_enable == 1'b1); +assign debug_csr_write_data = jtag_csr_write_enable == 1'b1 ? jtag_csr_write_data : csr_write_data; +assign debug_csr = jtag_csr_write_enable == 1'b1 ? jtag_csr : csr_x; - - - + + + - + + + + + + + +generate + for (i = 0; i < breakpoints; i = i + 1) + begin : bp_seq +always @(posedge clk_i ) +begin + if (rst_i == 1'b1) + begin + bp_a[i] <= { (clogb2(32'h7fffffff-32'h0)-2){1'bx}}; + bp_e[i] <= 1'b0; + end + else + begin + if ((debug_csr_write_enable == 1'b1) && (debug_csr == 5'h10 + i)) + begin + bp_a[i] <= debug_csr_write_data[ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2]; + bp_e[i] <= debug_csr_write_data[0]; + end + end +end + end +endgenerate + + +generate + for (i = 0; i < watchpoints; i = i + 1) + begin : wp_seq +always @(posedge clk_i ) +begin + if (rst_i == 1'b1) + begin + wp[i] <= { 32{1'bx}}; + wpc_c[i] <= 2'b00; + end + else + begin + if (debug_csr_write_enable == 1'b1) + begin + if (debug_csr == 5'h8) + wpc_c[i] <= debug_csr_write_data[3+i*2:2+i*2]; + if (debug_csr == 5'h18 + i) + wp[i] <= debug_csr_write_data; + end + end +end + end +endgenerate + + +always @(posedge clk_i ) +begin + if (rst_i == 1'b1) + dc_re <= 1'b0; + else + begin + if ((debug_csr_write_enable == 1'b1) && (debug_csr == 5'h8)) + dc_re <= debug_csr_write_data[1]; + end +end + + + + +always @(posedge clk_i ) +begin + if (rst_i == 1'b1) + begin + state <= 3'b000; + dc_ss <= 1'b0; + end + else + begin + if ((debug_csr_write_enable == 1'b1) && (debug_csr == 5'h8)) + begin + dc_ss <= debug_csr_write_data[0]; + if (debug_csr_write_data[0] == 1'b0) + state <= 3'b000; + else + state <= 3'b001; + end + case (state) + 3'b001: + begin - - + if ( ( (eret_q_x == 1'b1) + || (bret_q_x == 1'b1) + ) + && (stall_x == 1'b0) + ) + state <= 3'b010; + end + 3'b010: + begin - - - + if ((q_x == 1'b1) && (stall_x == 1'b0)) + state <= 3'b011; + end + 3'b011: + begin - - - - + - - - - + if (dcache_refill_request == 1'b1) + state <= 3'b010; + else + + if ((exception_x == 1'b1) && (q_x == 1'b1) && (stall_x == 1'b0)) + begin + dc_ss <= 1'b0; + state <= 3'b100; + end + end + 3'b100: + begin + + + if (dcache_refill_request == 1'b1) + state <= 3'b010; + else + + state <= 3'b000; + end + endcase + end +end + +endmodule + @@ -10165,7 +10368,7 @@ endmodule -module lm32_instruction_unit_full ( +module lm32_instruction_unit_full_debug ( clk_i, rst_i, @@ -10218,11 +10421,12 @@ module lm32_instruction_unit_full ( - - - - + jtag_read_enable, + jtag_write_enable, + jtag_write_data, + jtag_address, + @@ -10258,9 +10462,10 @@ module lm32_instruction_unit_full ( - - + jtag_read_data, + jtag_access_complete, + @@ -10350,11 +10555,12 @@ input i_rty_i; - - - - +input jtag_read_enable; +input jtag_write_enable; +input [ 7:0] jtag_write_data; +input [ (32-1):0] jtag_address; + @@ -10395,11 +10601,11 @@ wire icache_refilling; output [ (32-1):0] i_dat_o; - - -wire [ (32-1):0] i_dat_o; +reg [ (32-1):0] i_dat_o; + + output [ (32-1):0] i_adr_o; reg [ (32-1):0] i_adr_o; @@ -10407,21 +10613,21 @@ output i_cyc_o; reg i_cyc_o; output [ (4-1):0] i_sel_o; - - -wire [ (4-1):0] i_sel_o; +reg [ (4-1):0] i_sel_o; + + output i_stb_o; reg i_stb_o; output i_we_o; - - -wire i_we_o; +reg i_we_o; + + output [ (3-1):0] i_cti_o; reg [ (3-1):0] i_cti_o; @@ -10433,11 +10639,12 @@ wire [ (2-1):0] i_bte_o; - - - - +output [ 7:0] jtag_read_data; +reg [ 7:0] jtag_read_data; +output jtag_access_complete; +wire jtag_access_complete; + @@ -10503,8 +10710,9 @@ reg bus_error_f; - +reg jtag_access; + @@ -10622,7 +10830,7 @@ endfunction -lm32_icache_full #( +lm32_icache_full_debug #( .associativity (associativity), .sets (sets), .bytes_per_line (bytes_per_line), @@ -10745,11 +10953,11 @@ assign instruction_f = icache_data_f; - -assign i_dat_o = 32'd0; -assign i_we_o = 1'b0; -assign i_sel_o = 4'b1111; + + + + assign i_bte_o = 2'b00; @@ -10866,17 +11074,18 @@ end - - - - - - - - - - +assign jtag_access_complete = (i_cyc_o == 1'b1) && ((i_ack_i == 1'b1) || (i_err_i == 1'b1)) && (jtag_access == 1'b1); +always @(*) +begin + case (jtag_address[1:0]) + 2'b00: jtag_read_data = i_dat_i[ 31:24]; + 2'b01: jtag_read_data = i_dat_i[ 23:16]; + 2'b10: jtag_read_data = i_dat_i[ 15:8]; + 2'b11: jtag_read_data = i_dat_i[ 7:0]; + endcase +end + @@ -10901,10 +11110,11 @@ begin - - - + i_we_o <= 1'b0; + i_sel_o <= 4'b1111; + jtag_access <= 1'b0; + end else @@ -10917,15 +11127,16 @@ begin if ((i_ack_i == 1'b1) || (i_err_i == 1'b1)) begin - - - - - - - - + if (jtag_access == 1'b1) + begin + i_cyc_o <= 1'b0; + i_stb_o <= 1'b0; + i_we_o <= 1'b0; + jtag_access <= 1'b0; + end + else + begin if (last_word == 1'b1) @@ -10958,9 +11169,10 @@ begin if ((icache_refill_request == 1'b1) && (icache_refill_ready == 1'b0)) begin - - - + + + i_sel_o <= 4'b1111; + i_adr_o <= {first_address, 2'b00}; i_cyc_o <= 1'b1; @@ -10974,26 +11186,27 @@ begin end - - - - - - - - - - - - - - - - - - - + else + begin + if ((jtag_read_enable == 1'b1) || (jtag_write_enable == 1'b1)) + begin + case (jtag_address[1:0]) + 2'b00: i_sel_o <= 4'b1000; + 2'b01: i_sel_o <= 4'b0100; + 2'b10: i_sel_o <= 4'b0010; + 2'b11: i_sel_o <= 4'b0001; + endcase + i_adr_o <= jtag_address; + i_dat_o <= {4{jtag_write_data}}; + i_cyc_o <= 1'b1; + i_stb_o <= 1'b1; + i_we_o <= jtag_write_enable; + i_cti_o <= 3'b111; + jtag_access <= 1'b1; + end + end + @@ -11468,443 +11681,523 @@ endmodule - - - + - - - - - - - - + + - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +module lm32_jtag_full_debug ( - - - - - - + clk_i, + rst_i, + jtag_clk, + jtag_update, + jtag_reg_q, + jtag_reg_addr_q, + + + csr, + csr_write_enable, + csr_write_data, + stall_x, - - - - + + + jtag_read_data, + jtag_access_complete, - - + + + exception_q_w, - + + + jtx_csr_read_data, + jrx_csr_read_data, - - + + + jtag_csr_write_enable, + jtag_csr_write_data, + jtag_csr, + jtag_read_enable, + jtag_write_enable, + jtag_write_data, + jtag_address, - - - - - - - + + + jtag_break, + jtag_reset, - - - - - + jtag_reg_d, + jtag_reg_addr_d + ); - - +input clk_i; +input rst_i; - - - - +input jtag_clk; +input jtag_update; +input [ 7:0] jtag_reg_q; +input [2:0] jtag_reg_addr_q; + + +input [ (5-1):0] csr; +input csr_write_enable; +input [ (32-1):0] csr_write_data; +input stall_x; - - - - + + +input [ 7:0] jtag_read_data; +input jtag_access_complete; - - + + +input exception_q_w; - - - - - - + +output [ (32-1):0] jtx_csr_read_data; +wire [ (32-1):0] jtx_csr_read_data; +output [ (32-1):0] jrx_csr_read_data; +wire [ (32-1):0] jrx_csr_read_data; - - - - - - - - - - - - - - + + +output jtag_csr_write_enable; +reg jtag_csr_write_enable; +output [ (32-1):0] jtag_csr_write_data; +wire [ (32-1):0] jtag_csr_write_data; +output [ (5-1):0] jtag_csr; +wire [ (5-1):0] jtag_csr; +output jtag_read_enable; +reg jtag_read_enable; +output jtag_write_enable; +reg jtag_write_enable; +output [ 7:0] jtag_write_data; +wire [ 7:0] jtag_write_data; +output [ (32-1):0] jtag_address; +wire [ (32-1):0] jtag_address; - - - - - - - + +output jtag_break; +reg jtag_break; +output jtag_reset; +reg jtag_reset; + + +output [ 7:0] jtag_reg_d; +reg [ 7:0] jtag_reg_d; +output [2:0] jtag_reg_addr_d; +wire [2:0] jtag_reg_addr_d; - - - - +reg rx_update; +reg rx_update_r; +reg rx_update_r_r; +reg rx_update_r_r_r; - +wire [ 7:0] rx_byte; +wire [2:0] rx_addr; + + +reg [ 7:0] uart_tx_byte; +reg uart_tx_valid; +reg [ 7:0] uart_rx_byte; +reg uart_rx_valid; + - - - - - +reg [ 3:0] command; + - +reg [ 7:0] jtag_byte_0; +reg [ 7:0] jtag_byte_1; +reg [ 7:0] jtag_byte_2; +reg [ 7:0] jtag_byte_3; +reg [ 7:0] jtag_byte_4; +reg processing; - - - - - - - +reg [ 3:0] state; + + +assign jtag_csr_write_data = {jtag_byte_0, jtag_byte_1, jtag_byte_2, jtag_byte_3}; +assign jtag_csr = jtag_byte_4[ (5-1):0]; +assign jtag_address = {jtag_byte_0, jtag_byte_1, jtag_byte_2, jtag_byte_3}; +assign jtag_write_data = jtag_byte_4; - - - - - - - + + +assign jtag_reg_addr_d[1:0] = {uart_rx_valid, uart_tx_valid}; + + + + +assign jtag_reg_addr_d[2] = processing; - - - - + + +assign jtx_csr_read_data = {{ 32-9{1'b0}}, uart_tx_valid, 8'h00}; +assign jrx_csr_read_data = {{ 32-9{1'b0}}, uart_rx_valid, uart_rx_byte}; + - - +assign rx_byte = jtag_reg_q; +assign rx_addr = jtag_reg_addr_q; - +always @(posedge clk_i ) +begin + if (rst_i == 1'b1) + begin + rx_update <= 1'b0; + rx_update_r <= 1'b0; + rx_update_r_r <= 1'b0; + rx_update_r_r_r <= 1'b0; + end + else + begin + rx_update <= jtag_update; + rx_update_r <= rx_update; + rx_update_r_r <= rx_update_r; + rx_update_r_r_r <= rx_update_r_r; + end +end - - - - - - - - - - - - - - +always @(posedge clk_i ) +begin + if (rst_i == 1'b1) + begin + state <= 4'h0; + command <= 4'b0000; + jtag_reg_d <= 8'h00; + + processing <= 1'b0; + jtag_csr_write_enable <= 1'b0; + jtag_read_enable <= 1'b0; + jtag_write_enable <= 1'b0; + - + - - - - - + jtag_break <= 1'b0; + jtag_reset <= 1'b0; - - - - + + + uart_tx_byte <= 8'h00; + uart_tx_valid <= 1'b0; + uart_rx_byte <= 8'h00; + uart_rx_valid <= 1'b0; - - - - - - - - - - - - - - - - - + end + else + begin + + + if ((csr_write_enable == 1'b1) && (stall_x == 1'b0)) + begin + case (csr) + 5'he: + begin - - - - - + uart_tx_byte <= csr_write_data[ 7:0]; + uart_tx_valid <= 1'b1; + end + 5'hf: + begin - - - - - + uart_rx_valid <= 1'b0; + end + endcase + end + + + - - - - - + if (exception_q_w == 1'b1) + begin + jtag_break <= 1'b0; + jtag_reset <= 1'b0; + end + - - - - - + case (state) + 4'h0: + begin - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + if ((~rx_update_r_r_r & rx_update_r_r) == 1'b1) + begin + command <= rx_byte[7:4]; + case (rx_addr) + - - - - - - - + 3'b000: + begin + case (rx_byte[7:4]) + - + 4'b0001: + state <= 4'h1; + 4'b0011: + begin + {jtag_byte_2, jtag_byte_3} <= {jtag_byte_2, jtag_byte_3} + 1'b1; + state <= 4'h6; + end + 4'b0010: + state <= 4'h1; + 4'b0100: + begin + {jtag_byte_2, jtag_byte_3} <= {jtag_byte_2, jtag_byte_3} + 1'b1; + state <= 5; + end + 4'b0101: + state <= 4'h1; + - - + 4'b0110: + begin + + + uart_rx_valid <= 1'b0; + uart_tx_valid <= 1'b0; + - - - - - - - - - - - + jtag_break <= 1'b1; + end + 4'b0111: + begin + + + uart_rx_valid <= 1'b0; + uart_tx_valid <= 1'b0; + - - - - - + jtag_reset <= 1'b1; + end + endcase + end - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + 3'b001: + begin + uart_rx_byte <= rx_byte; + uart_rx_valid <= 1'b1; + end + 3'b010: + begin + jtag_reg_d <= uart_tx_byte; + uart_tx_valid <= 1'b0; + end + + default: + ; + endcase + end + end + 4'h1: + begin + if ((~rx_update_r_r_r & rx_update_r_r) == 1'b1) + begin + jtag_byte_0 <= rx_byte; + state <= 4'h2; + end + end + 4'h2: + begin + if ((~rx_update_r_r_r & rx_update_r_r) == 1'b1) + begin + jtag_byte_1 <= rx_byte; + state <= 4'h3; + end + end + 4'h3: + begin + if ((~rx_update_r_r_r & rx_update_r_r) == 1'b1) + begin + jtag_byte_2 <= rx_byte; + state <= 4'h4; + end + end + 4'h4: + begin + if ((~rx_update_r_r_r & rx_update_r_r) == 1'b1) + begin + jtag_byte_3 <= rx_byte; + if (command == 4'b0001) + state <= 4'h6; + else + state <= 4'h5; + end + end + 4'h5: + begin + if ((~rx_update_r_r_r & rx_update_r_r) == 1'b1) + begin + jtag_byte_4 <= rx_byte; + state <= 4'h6; + end + end + 4'h6: + begin + case (command) + 4'b0001, + 4'b0011: + begin + jtag_read_enable <= 1'b1; + processing <= 1'b1; + state <= 4'h7; + end + 4'b0010, + 4'b0100: + begin + jtag_write_enable <= 1'b1; + processing <= 1'b1; + state <= 4'h7; + end + 4'b0101: + begin + jtag_csr_write_enable <= 1'b1; + processing <= 1'b1; + state <= 4'h8; + end + endcase + end + 4'h7: + begin + if (jtag_access_complete == 1'b1) + begin + jtag_read_enable <= 1'b0; + jtag_reg_d <= jtag_read_data; + jtag_write_enable <= 1'b0; + processing <= 1'b0; + state <= 4'h0; + end + end + 4'h8: + begin + jtag_csr_write_enable <= 1'b0; + processing <= 1'b0; + state <= 4'h0; + end + + endcase + end +end + +endmodule + @@ -12259,7 +12552,7 @@ endmodule -module lm32_interrupt_full ( +module lm32_interrupt_full_debug ( clk_i, rst_i, @@ -12268,17 +12561,18 @@ module lm32_interrupt_full ( stall_x, - - - - exception, + non_debug_exception, + debug_exception, + + eret_q_x, - + bret_q_x, + csr, csr_write_data, @@ -12307,20 +12601,21 @@ input [interrupts-1:0] interrupt; input stall_x; - - - -input exception; +input non_debug_exception; +input debug_exception; + + input eret_q_x; - +input bret_q_x; + -input [ (3-1):0] csr; +input [ (5-1):0] csr; input [ (32-1):0] csr_write_data; input csr_write_enable; @@ -12347,8 +12642,9 @@ wire [interrupts-1:0] interrupt_n_exception; reg ie; reg eie; - +reg bie; + reg [interrupts-1:0] ip; reg [interrupts-1:0] im; @@ -12368,11 +12664,11 @@ assign asserted = ip | interrupt; assign ie_csr_read_data = {{ 32-3{1'b0}}, - - - 1'b0, + bie, + + eie, ie @@ -12386,19 +12682,19 @@ generate always @(*) begin case (csr) - 3'h0: csr_read_data = {{ 32-3{1'b0}}, + 5'h0: csr_read_data = {{ 32-3{1'b0}}, - - - 1'b0, + bie, + + eie, ie }; - 3'h2: csr_read_data = ip; - 3'h1: csr_read_data = im; + 5'h2: csr_read_data = ip; + 5'h1: csr_read_data = im; default: csr_read_data = { 32{1'bx}}; endcase end @@ -12409,18 +12705,18 @@ end always @(*) begin case (csr) - 3'h0: csr_read_data = {{ 32-3{1'b0}}, + 5'h0: csr_read_data = {{ 32-3{1'b0}}, - - - 1'b0, + bie, + + eie, ie }; - 3'h2: csr_read_data = ip; + 5'h2: csr_read_data = ip; default: csr_read_data = { 32{1'bx}}; endcase end @@ -12449,8 +12745,9 @@ always @(posedge clk_i ) ie <= 1'b0; eie <= 1'b0; - + bie <= 1'b0; + im <= {interrupts{1'b0}}; ip <= {interrupts{1'b0}}; @@ -12462,13 +12759,21 @@ always @(posedge clk_i ) ip <= asserted; - - + + if (non_debug_exception == 1'b1) + begin - - - + eie <= ie; + ie <= 1'b0; + end + else if (debug_exception == 1'b1) + begin + bie <= ie; + ie <= 1'b0; + end + + @@ -12476,14 +12781,6 @@ always @(posedge clk_i ) - if (exception == 1'b1) - begin - - eie <= ie; - ie <= 1'b0; - end - - else if (stall_x == 1'b0) begin @@ -12501,26 +12798,28 @@ always @(posedge clk_i ) - - - + else if (bret_q_x == 1'b1) + + ie <= bie; + else if (csr_write_enable == 1'b1) begin - if (csr == 3'h0) + if (csr == 5'h0) begin ie <= csr_write_data[0]; eie <= csr_write_data[1]; - + bie <= csr_write_data[2]; + end - if (csr == 3'h1) + if (csr == 5'h1) im <= csr_write_data[interrupts-1:0]; - if (csr == 3'h2) + if (csr == 5'h2) ip <= asserted & ~csr_write_data[interrupts-1:0]; end end @@ -12537,8 +12836,9 @@ always @(posedge clk_i ) ie <= 1'b0; eie <= 1'b0; - + bie <= 1'b0; + ip <= {interrupts{1'b0}}; eie_delay <= 0; @@ -12548,13 +12848,21 @@ always @(posedge clk_i ) ip <= asserted; - - + + if (non_debug_exception == 1'b1) + begin - - - + eie <= ie; + ie <= 1'b0; + end + else if (debug_exception == 1'b1) + begin + bie <= ie; + ie <= 1'b0; + end + + @@ -12562,14 +12870,6 @@ always @(posedge clk_i ) - if (exception == 1'b1) - begin - - eie <= ie; - ie <= 1'b0; - end - - else if (stall_x == 1'b0) begin @@ -12585,24 +12885,26 @@ always @(posedge clk_i ) end - - - + else if (bret_q_x == 1'b1) + + ie <= bie; + else if (csr_write_enable == 1'b1) begin - if (csr == 3'h0) + if (csr == 5'h0) begin ie <= csr_write_data[0]; eie <= csr_write_data[1]; - + bie <= csr_write_data[2]; + end - if (csr == 3'h2) + if (csr == 5'h2) ip <= asserted & ~csr_write_data[interrupts-1:0]; end end @@ -12669,16 +12971,6 @@ endmodule - - - - - - - - - - @@ -12704,12 +12996,13 @@ endmodule - + + + + - - - + @@ -12847,25 +13140,24 @@ endmodule - - - + + - - - + + + @@ -12968,47 +13260,27 @@ endmodule - - - - - - - - - - - - - - - - - + + - - + - + - - - - @@ -13017,8 +13289,6 @@ endmodule - - @@ -13026,19 +13296,28 @@ endmodule + + - + + - + + + + + + + + - @@ -13196,7 +13475,7 @@ endmodule -module lm32_top_full_debug ( +module lm32_top_full ( clk_i, rst_i, @@ -13353,18 +13632,17 @@ wire [ (2-1):0] D_BTE_O; - -wire [ 7:0] jtag_reg_d; -wire [ 7:0] jtag_reg_q; -wire jtag_update; -wire [2:0] jtag_reg_addr_d; -wire [2:0] jtag_reg_addr_q; -wire jtck; -wire jrstn; + + + + + + + @@ -13440,7 +13718,7 @@ endfunction -lm32_cpu_full_debug cpu ( +lm32_cpu_full cpu ( .clk_i (clk_i), @@ -13461,13 +13739,12 @@ lm32_cpu_full_debug cpu ( - - .jtag_clk (jtck), - .jtag_update (jtag_update), - .jtag_reg_q (jtag_reg_q), - .jtag_reg_addr_q (jtag_reg_addr_q), - + + + + + @@ -13496,10 +13773,9 @@ lm32_cpu_full_debug cpu ( + + - .jtag_reg_d (jtag_reg_d), - .jtag_reg_addr_d (jtag_reg_addr_d), - @@ -13534,21 +13810,20 @@ lm32_cpu_full_debug cpu ( .D_BTE_O (D_BTE_O) ); - - + -jtag_cores jtag_cores ( + - .reg_d (jtag_reg_d), - .reg_addr_d (jtag_reg_addr_d), + + - .reg_update (jtag_update), - .reg_q (jtag_reg_q), - .reg_addr_q (jtag_reg_addr_q), - .jtck (jtck), - .jrstn (jrstn) - ); - + + + + + + + endmodule @@ -13920,7 +14195,7 @@ endmodule -module lm32_mc_arithmetic_full_debug ( +module lm32_mc_arithmetic_full ( clk_i, rst_i, @@ -14586,7 +14861,7 @@ endmodule -module lm32_cpu_full_debug ( +module lm32_cpu_full ( clk_i, @@ -14607,13 +14882,12 @@ module lm32_cpu_full_debug ( - - jtag_clk, - jtag_update, - jtag_reg_q, - jtag_reg_addr_q, - + + + + + @@ -14642,10 +14916,9 @@ module lm32_cpu_full_debug ( + + - jtag_reg_d, - jtag_reg_addr_d, - @@ -14686,9 +14959,8 @@ module lm32_cpu_full_debug ( parameter eba_reset = 32'h00000000; + -parameter deba_reset = 32'h10000000; - @@ -14724,11 +14996,11 @@ parameter dcache_limit = 32'h7fffffff; + -parameter watchpoints = 32'h4; - - +parameter watchpoints = 0; + @@ -14770,12 +15042,11 @@ input [ (32-1):0] interrupt; + + + + -input jtag_clk; -input jtag_update; -input [ 7:0] jtag_reg_q; -input [2:0] jtag_reg_addr_q; - @@ -14815,12 +15086,11 @@ input D_RTY_I; + + + + -output [ 7:0] jtag_reg_d; -wire [ 7:0] jtag_reg_d; -output [2:0] jtag_reg_addr_d; -wire [2:0] jtag_reg_addr_d; - @@ -15000,15 +15270,14 @@ wire [ (5-1):0] write_idx_d; reg [ (5-1):0] write_idx_x; reg [ (5-1):0] write_idx_m; reg [ (5-1):0] write_idx_w; -wire [ (5-1):0] csr_d; -reg [ (5-1):0] csr_x; +wire [ (3-1):0] csr_d; +reg [ (3-1):0] csr_x; wire [ (3-1):0] condition_d; reg [ (3-1):0] condition_x; + + -wire break_d; -reg break_x; - wire scall_d; reg scall_x; @@ -15021,16 +15290,14 @@ reg eret_m; - -wire bret_d; -reg bret_x; -wire bret_q_x; -reg bret_m; - + + + + + - wire csr_write_enable_d; reg csr_write_enable_x; @@ -15236,32 +15503,25 @@ wire stall_wb_load; - - - -wire [ (32-1):0] jtx_csr_read_data; -wire [ (32-1):0] jrx_csr_read_data; + + + + + + + - -wire jtag_csr_write_enable; -wire [ (32-1):0] jtag_csr_write_data; -wire [ (5-1):0] jtag_csr; -wire jtag_read_enable; -wire [ 7:0] jtag_read_data; -wire jtag_write_enable; -wire [ 7:0] jtag_write_data; -wire [ (32-1):0] jtag_address; -wire jtag_access_complete; - - -wire jtag_break; + + + + @@ -15294,9 +15554,8 @@ wire kill_w; reg [ (clogb2(32'h7fffffff-32'h0)-2)+2-1:8] eba; + -reg [ (clogb2(32'h7fffffff-32'h0)-2)+2-1:8] deba; - reg [ (3-1):0] eid_x; @@ -15306,39 +15565,34 @@ reg [ (3-1):0] eid_x; - - - -wire dc_ss; + -wire dc_re; -wire exception_x; -reg exception_m; -wire debug_exception_x; -reg debug_exception_m; -reg debug_exception_w; -wire debug_exception_q_w; -wire non_debug_exception_x; -reg non_debug_exception_m; -reg non_debug_exception_w; -wire non_debug_exception_q_w; - + + + + + + + +wire exception_x; +reg exception_m; +reg exception_w; +wire exception_q_w; + - - -wire reset_exception; + + - @@ -15346,10 +15600,9 @@ wire interrupt_exception; + + -wire breakpoint_exception; -wire watchpoint_exception; - @@ -15433,7 +15686,7 @@ endfunction -lm32_instruction_unit_full_debug #( +lm32_instruction_unit_full #( .associativity (icache_associativity), .sets (icache_sets), .bytes_per_line (icache_bytes_per_line), @@ -15492,12 +15745,11 @@ lm32_instruction_unit_full_debug #( + + + + - .jtag_read_enable (jtag_read_enable), - .jtag_write_enable (jtag_write_enable), - .jtag_write_data (jtag_write_data), - .jtag_address (jtag_address), - @@ -15533,10 +15785,9 @@ lm32_instruction_unit_full_debug #( + + - .jtag_read_data (jtag_read_data), - .jtag_access_complete (jtag_access_complete), - @@ -15552,7 +15803,7 @@ lm32_instruction_unit_full_debug #( ); -lm32_decoder_full_debug decoder ( +lm32_decoder_full decoder ( .instruction (instruction_d), @@ -15633,16 +15884,14 @@ lm32_decoder_full_debug decoder ( .branch_reg (branch_reg_d), .condition (condition_d), + - .break_opcode (break_d), - .scall (scall_d), .eret (eret_d), + - .bret (bret_d), - @@ -15652,7 +15901,7 @@ lm32_decoder_full_debug decoder ( ); -lm32_load_store_unit_full_debug #( +lm32_load_store_unit_full #( .associativity (dcache_associativity), .sets (dcache_sets), .bytes_per_line (dcache_bytes_per_line), @@ -15788,7 +16037,7 @@ lm32_multiplier multiplier ( -lm32_mc_arithmetic_full_debug mc_arithmetic ( +lm32_mc_arithmetic_full mc_arithmetic ( .clk_i (clk_i), .rst_i (rst_i), @@ -15827,7 +16076,7 @@ lm32_mc_arithmetic_full_debug mc_arithmetic ( -lm32_interrupt_full_debug interrupt_unit ( +lm32_interrupt_full interrupt_unit ( .clk_i (clk_i), .rst_i (rst_i), @@ -15836,18 +16085,17 @@ lm32_interrupt_full_debug interrupt_unit ( .stall_x (stall_x), + + - .non_debug_exception (non_debug_exception_q_w), - .debug_exception (debug_exception_q_w), - - + .exception (exception_q_w), + .eret_q_x (eret_q_x), + - .bret_q_x (bret_q_x), - .csr (csr_x), .csr_write_data (operand_1_x), @@ -15862,117 +16110,95 @@ lm32_interrupt_full_debug interrupt_unit ( - -lm32_jtag_full_debug jtag ( + - .clk_i (clk_i), - .rst_i (rst_i), + + - .jtag_clk (jtag_clk), - .jtag_update (jtag_update), - .jtag_reg_q (jtag_reg_q), - .jtag_reg_addr_q (jtag_reg_addr_q), + + + + - - - .csr (csr_x), - .csr_write_data (operand_1_x), - .csr_write_enable (csr_write_enable_q_x), - .stall_x (stall_x), + + + + - - - .jtag_read_data (jtag_read_data), - .jtag_access_complete (jtag_access_complete), + + - - - .exception_q_w (debug_exception_q_w || non_debug_exception_q_w), + - - - .jtx_csr_read_data (jtx_csr_read_data), - .jrx_csr_read_data (jrx_csr_read_data), + + - - - .jtag_csr_write_enable (jtag_csr_write_enable), - .jtag_csr_write_data (jtag_csr_write_data), - .jtag_csr (jtag_csr), - .jtag_read_enable (jtag_read_enable), - .jtag_write_enable (jtag_write_enable), - .jtag_write_data (jtag_write_data), - .jtag_address (jtag_address), + + + + + + + - - - .jtag_break (jtag_break), - .jtag_reset (reset_exception), + + - .jtag_reg_d (jtag_reg_d), - .jtag_reg_addr_d (jtag_reg_addr_d) - ); - - - - - - -lm32_debug_full_debug #( - .breakpoints (breakpoints), - .watchpoints (watchpoints) - ) hw_debug ( + + - .clk_i (clk_i), - .rst_i (rst_i), - .pc_x (pc_x), - .load_x (load_x), - .store_x (store_x), - .load_store_address_x (adder_result_x), - .csr_write_enable_x (csr_write_enable_q_x), - .csr_write_data (operand_1_x), - .csr_x (csr_x), - - .jtag_csr_write_enable (jtag_csr_write_enable), - .jtag_csr_write_data (jtag_csr_write_data), - .jtag_csr (jtag_csr), - - - .eret_q_x (eret_q_x), - .bret_q_x (bret_q_x), - .stall_x (stall_x), - .exception_x (exception_x), - .q_x (q_x), - .dcache_refill_request (dcache_refill_request), + + + + + + + + + + + + + + + + + + + + + + + + - - - .dc_ss (dc_ss), + + + + + + + - .dc_re (dc_re), - .bp_match (bp_match), - .wp_match (wp_match) - ); - @@ -16472,25 +16698,21 @@ assign kill_w = 1'b0 - -assign breakpoint_exception = ( ( (break_x == 1'b1) - || (bp_match == 1'b1) - ) - && (valid_x == 1'b1) - ) - - - || (jtag_break == 1'b1) + + + + + + + + - ; - + -assign watchpoint_exception = wp_match == 1'b1; - @@ -16517,17 +16739,38 @@ assign system_call_exception = ( (scall_x == 1'b1) ); + + + -assign debug_exception_x = (breakpoint_exception == 1'b1) - || (watchpoint_exception == 1'b1) - ; + + + -assign non_debug_exception_x = (system_call_exception == 1'b1) - + + + - || (reset_exception == 1'b1) + + + + + + + + + + + + + + + + + +assign exception_x = (system_call_exception == 1'b1) || (instruction_bus_error_exception == 1'b1) @@ -16543,9 +16786,8 @@ assign non_debug_exception_x = (system_call_exception == 1'b1) || ( (interrupt_exception == 1'b1) + - && (dc_ss == 1'b0) - @@ -16557,55 +16799,27 @@ assign non_debug_exception_x = (system_call_exception == 1'b1) ; - -assign exception_x = (debug_exception_x == 1'b1) || (non_debug_exception_x == 1'b1); - - - - - - - - - - - - - - - - - - - - - always @(*) begin - - - - if (reset_exception == 1'b1) - eid_x = 3'h0; - else + + + - - - if (data_bus_error_exception == 1'b1) - eid_x = 3'h4; - else + + + + + + + - if (breakpoint_exception == 1'b1) - eid_x = 3'd1; - else - @@ -16618,11 +16832,10 @@ begin + + + - if (watchpoint_exception == 1'b1) - eid_x = 3'd3; - else - @@ -16635,9 +16848,8 @@ begin if ( (interrupt_exception == 1'b1) + - && (dc_ss == 1'b0) - ) eid_x = 3'h6; @@ -16674,19 +16886,18 @@ assign stall_d = (stall_x == 1'b1) && (kill_d == 1'b0) ) + + + + + + + + + + + - || ( ( (break_d == 1'b1) - || (bret_d == 1'b1) - ) - && ( (load_q_x == 1'b1) - || (store_q_x == 1'b1) - || (load_q_m == 1'b1) - || (store_q_m == 1'b1) - || (D_CYC_O == 1'b1) - ) - && (kill_d == 1'b0) - ) - || ( (csr_write_enable_d == 1'b1) && (load_q_x == 1'b1) @@ -16792,24 +17003,21 @@ assign q_x = (valid_x == 1'b1) && (kill_x == 1'b0); assign csr_write_enable_q_x = (csr_write_enable_x == 1'b1) && (q_x == 1'b1); assign eret_q_x = (eret_x == 1'b1) && (q_x == 1'b1); + -assign bret_q_x = (bret_x == 1'b1) && (q_x == 1'b1); - assign load_q_x = (load_x == 1'b1) && (q_x == 1'b1) + - && (bp_match == 1'b0) - ; assign store_q_x = (store_x == 1'b1) && (q_x == 1'b1) + - && (bp_match == 1'b0) - ; @@ -16820,13 +17028,13 @@ assign q_m = (valid_m == 1'b1) && (kill_m == 1'b0) && (exception_m == 1'b0); assign load_q_m = (load_m == 1'b1) && (q_m == 1'b1); assign store_q_m = (store_m == 1'b1) && (q_m == 1'b1); - -assign debug_exception_q_w = ((debug_exception_w == 1'b1) && (valid_w == 1'b1)); -assign non_debug_exception_q_w = ((non_debug_exception_w == 1'b1) && (valid_w == 1'b1)); - + +assign exception_q_w = ((exception_w == 1'b1) && (valid_w == 1'b1)); + + assign write_enable_q_x = (write_enable_x == 1'b1) && (valid_x == 1'b1) && (branch_flushX_m == 1'b0); assign write_enable_q_m = (write_enable_m == 1'b1) && (valid_m == 1'b1); @@ -16841,12 +17049,12 @@ assign cfg = { breakpoints[3:0], interrupts[5:0], - - 1'b1, - + 1'b0, + + @@ -16855,19 +17063,19 @@ assign cfg = { - - 1'b1, - - - - 1'b1, + 1'b0, + + + 1'b0, + + 1'b1, @@ -16948,17 +17156,16 @@ assign cfg2 = { assign iflush = ( (csr_write_enable_d == 1'b1) - && (csr_d == 5'h3) + && (csr_d == 3'h3) && (stall_d == 1'b0) && (kill_d == 1'b0) && (valid_d == 1'b1)) + + + - || - ( (jtag_csr_write_enable == 1'b1) - && (jtag_csr == 5'h3)) - ; @@ -16966,21 +17173,20 @@ assign iflush = ( (csr_write_enable_d == 1'b1) assign dflush_x = ( (csr_write_enable_q_x == 1'b1) - && (csr_x == 5'h4)) + && (csr_x == 3'h4)) + + + - || - ( (jtag_csr_write_enable == 1'b1) - && (jtag_csr == 5'h4)) - ; -assign csr_d = read_idx_0_d[ (5-1):0]; +assign csr_d = read_idx_0_d[ (3-1):0]; always @(*) @@ -16988,29 +17194,27 @@ begin case (csr_x) - 5'h0, - 5'h1, - 5'h2: csr_read_data_x = interrupt_csr_read_data_x; + 3'h0, + 3'h1, + 3'h2: csr_read_data_x = interrupt_csr_read_data_x; - 5'h6: csr_read_data_x = cfg; - 5'h7: csr_read_data_x = {eba, 8'h00}; + 3'h6: csr_read_data_x = cfg; + 3'h7: csr_read_data_x = {eba, 8'h00}; + - 5'h9: csr_read_data_x = {deba, 8'h00}; - + + - 5'he: csr_read_data_x = jtx_csr_read_data; - 5'hf: csr_read_data_x = jrx_csr_read_data; - - 5'ha: csr_read_data_x = cfg2; + 3'ha: csr_read_data_x = cfg2; default: csr_read_data_x = { 32{1'bx}}; endcase @@ -17027,37 +17231,33 @@ begin eba <= eba_reset[ (clogb2(32'h7fffffff-32'h0)-2)+2-1:8]; else begin - if ((csr_write_enable_q_x == 1'b1) && (csr_x == 5'h7) && (stall_x == 1'b0)) + if ((csr_write_enable_q_x == 1'b1) && (csr_x == 3'h7) && (stall_x == 1'b0)) eba <= operand_1_x[ (clogb2(32'h7fffffff-32'h0)-2)+2-1:8]; + + - if ((jtag_csr_write_enable == 1'b1) && (jtag_csr == 5'h7)) - eba <= jtag_csr_write_data[ (clogb2(32'h7fffffff-32'h0)-2)+2-1:8]; - end end + -always @(posedge clk_i ) -begin - if (rst_i == 1'b1) - deba <= deba_reset[ (clogb2(32'h7fffffff-32'h0)-2)+2-1:8]; - else - begin - if ((csr_write_enable_q_x == 1'b1) && (csr_x == 5'h9) && (stall_x == 1'b0)) - deba <= operand_1_x[ (clogb2(32'h7fffffff-32'h0)-2)+2-1:8]; - - - if ((jtag_csr_write_enable == 1'b1) && (jtag_csr == 5'h9)) - deba <= jtag_csr_write_data[ (clogb2(32'h7fffffff-32'h0)-2)+2-1:8]; + + + + + + + + + + + - end -end - @@ -17239,7 +17439,7 @@ begin m_bypass_enable_x <= 1'b0; write_enable_x <= 1'b0; write_idx_x <= { 5{1'b0}}; - csr_x <= { 5{1'b0}}; + csr_x <= { 3{1'b0}}; load_x <= 1'b0; store_x <= 1'b0; size_x <= { 2{1'b0}}; @@ -17262,16 +17462,14 @@ begin branch_predict_taken_x <= 1'b0; condition_x <= 3'b000; + - break_x <= 1'b0; - scall_x <= 1'b0; eret_x <= 1'b0; + - bret_x <= 1'b0; - @@ -17315,10 +17513,9 @@ begin + + - debug_exception_m <= 1'b0; - non_debug_exception_m <= 1'b0; - operand_w <= { 32{1'b0}}; w_result_sel_load_w <= 1'b0; @@ -17330,13 +17527,13 @@ begin write_idx_w <= { 5{1'b0}}; write_enable_w <= 1'b0; - - debug_exception_w <= 1'b0; - non_debug_exception_w <= 1'b0; - + + exception_w <= 1'b0; + + memop_pc_w <= { (clogb2(32'h7fffffff-32'h0)-2){1'b0}}; @@ -17416,9 +17613,8 @@ begin condition_x <= condition_d; csr_write_enable_x <= csr_write_enable_d; + - break_x <= break_d; - scall_x <= scall_d; @@ -17428,9 +17624,8 @@ begin eret_x <= eret_d; + - bret_x <= bret_d; - write_enable_x <= write_enable_d; end @@ -17482,40 +17677,40 @@ begin - - if (non_debug_exception_x == 1'b1) - write_idx_m <= 5'd30; - else if (debug_exception_x == 1'b1) - write_idx_m <= 5'd31; - else - write_idx_m <= write_idx_x; - - + + + + if (exception_x == 1'b1) + write_idx_m <= 5'd30; + else + write_idx_m <= write_idx_x; + + condition_met_m <= condition_met_x; + + + + + + + + + - if (exception_x == 1'b1) - if ((dc_re == 1'b1) - || ((debug_exception_x == 1'b1) - && (non_debug_exception_x == 1'b0))) - branch_target_m <= {deba, eid_x, {3{1'b0}}}; - else - branch_target_m <= {eba, eid_x, {3{1'b0}}}; - else - branch_target_m <= branch_target_x; - - + branch_target_m <= exception_x == 1'b1 ? {eba, eid_x, {3{1'b0}}} : branch_target_x; + @@ -17528,16 +17723,14 @@ begin eret_m <= eret_q_x; + - bret_m <= bret_q_x; - write_enable_m <= exception_x == 1'b1 ? 1'b1 : write_enable_x; + + - debug_exception_m <= debug_exception_x; - non_debug_exception_m <= non_debug_exception_x; - end @@ -17552,9 +17745,8 @@ begin data_bus_error_exception_m <= (data_bus_error_exception == 1'b1) + - && (reset_exception == 1'b0) - ; @@ -17586,12 +17778,12 @@ begin write_enable_w <= write_enable_m; - - debug_exception_w <= debug_exception_m; - non_debug_exception_w <= non_debug_exception_m; - + + + exception_w <= exception_m; + @@ -18137,7 +18329,7 @@ endmodule -module lm32_load_store_unit_full_debug ( +module lm32_load_store_unit_full ( clk_i, rst_i, @@ -18515,7 +18707,7 @@ endfunction -lm32_dcache_full_debug #( +lm32_dcache_full #( .associativity (associativity), .sets (sets), .bytes_per_line (bytes_per_line), @@ -19467,7 +19659,7 @@ endmodule -module lm32_decoder_full_debug ( +module lm32_decoder_full ( instruction, @@ -19548,16 +19740,14 @@ module lm32_decoder_full_debug ( bi_conditional, bi_unconditional, + - break_opcode, - scall, eret, + - bret, - @@ -19693,20 +19883,18 @@ wire bi_conditional; output bi_unconditional; wire bi_unconditional; - -output break_opcode; -wire break_opcode; + + output scall; wire scall; output eret; wire eret; - -output bret; -wire bret; + + @@ -20070,16 +20258,14 @@ assign branch = bra | call; assign branch_reg = op_call | op_b; assign condition = instruction[28:26]; + -assign break_opcode = op_raise & ~instruction[2]; - assign scall = op_raise & instruction[2]; assign eret = op_b & (instruction[25:21] == 5'd30); + -assign bret = op_b & (instruction[25:21] == 5'd31); - @@ -20511,7 +20697,7 @@ endmodule -module lm32_icache_full_debug ( +module lm32_icache_full ( clk_i, rst_i, @@ -21357,7 +21543,7 @@ endmodule -module lm32_dcache_full_debug ( +module lm32_dcache_full ( clk_i, rst_i, @@ -22213,163 +22399,135 @@ endmodule + + + + + + - - - - - - - - - - - - -module lm32_debug_full_debug ( - clk_i, - rst_i, - pc_x, - load_x, - store_x, - load_store_address_x, - csr_write_enable_x, - csr_write_data, - csr_x, - - - jtag_csr_write_enable, - jtag_csr_write_data, - jtag_csr, + + + + + + + + + + + + - - - eret_q_x, - bret_q_x, - stall_x, - exception_x, - q_x, - - - dcache_refill_request, - + + + + + - - - dc_ss, - - dc_re, - bp_match, - wp_match - ); + + + + + + + -parameter breakpoints = 0; -parameter watchpoints = 0; + + -input clk_i; -input rst_i; -input [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] pc_x; -input load_x; -input store_x; -input [ (32-1):0] load_store_address_x; -input csr_write_enable_x; -input [ (32-1):0] csr_write_data; -input [ (5-1):0] csr_x; - + + -input jtag_csr_write_enable; -input [ (32-1):0] jtag_csr_write_data; -input [ (5-1):0] jtag_csr; + + + + + + + + + + - - -input eret_q_x; -input bret_q_x; -input stall_x; -input exception_x; -input q_x; - - -input dcache_refill_request; - + + + + + + - -output dc_ss; -reg dc_ss; + + -output dc_re; -reg dc_re; -output bp_match; -wire bp_match; -output wp_match; -wire wp_match; - - - + + + + + + -genvar i; -reg [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] bp_a[0:breakpoints-1]; -reg bp_e[0:breakpoints-1]; -wire [0:breakpoints-1]bp_match_n; + -reg [ 1:0] wpc_c[0:watchpoints-1]; -reg [ (32-1):0] wp[0:watchpoints-1]; -wire [0:watchpoints]wp_match_n; -wire debug_csr_write_enable; -wire [ (32-1):0] debug_csr_write_data; -wire [ (5-1):0] debug_csr; - + + + + + + -reg [ 2:0] state; + + + + - - + @@ -22377,15 +22535,48 @@ reg [ 2:0] state; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -22394,224 +22585,132 @@ reg [ 2:0] state; + + + - -function integer clogb2; -input [31:0] value; -begin - for (clogb2 = 0; value > 0; clogb2 = clogb2 + 1) - value = value >> 1; -end -endfunction + + + + + + + + + + + + + + + -function integer clogb2_v1; -input [31:0] value; -reg [31:0] i; -reg [31:0] temp; -begin - temp = 0; - i = 0; - for (i = 0; temp < value; i = i + 1) - temp = 1<<i; - clogb2_v1 = i-1; -end -endfunction + + + + + + + + + + + + + + + + + + + + -generate - for (i = 0; i < breakpoints; i = i + 1) - begin : bp_comb -assign bp_match_n[i] = ((bp_a[i] == pc_x) && (bp_e[i] == 1'b1)); - end -endgenerate -generate - + + + + + + + + - if (breakpoints > 0) -assign bp_match = (|bp_match_n) || (state == 3'b011); - else -assign bp_match = state == 3'b011; - - - - + -endgenerate + + + + + + + - -generate - for (i = 0; i < watchpoints; i = i + 1) - begin : wp_comb -assign wp_match_n[i] = (wp[i] == load_store_address_x) && ((load_x & wpc_c[i][0]) | (store_x & wpc_c[i][1])); - end -endgenerate -generate - if (watchpoints > 0) -assign wp_match = |wp_match_n; - else -assign wp_match = 1'b0; -endgenerate - - + + - -assign debug_csr_write_enable = (csr_write_enable_x == 1'b1) || (jtag_csr_write_enable == 1'b1); -assign debug_csr_write_data = jtag_csr_write_enable == 1'b1 ? jtag_csr_write_data : csr_write_data; -assign debug_csr = jtag_csr_write_enable == 1'b1 ? jtag_csr : csr_x; + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - -generate - for (i = 0; i < breakpoints; i = i + 1) - begin : bp_seq -always @(posedge clk_i ) -begin - if (rst_i == 1'b1) - begin - bp_a[i] <= { (clogb2(32'h7fffffff-32'h0)-2){1'bx}}; - bp_e[i] <= 1'b0; - end - else - begin - if ((debug_csr_write_enable == 1'b1) && (debug_csr == 5'h10 + i)) - begin - bp_a[i] <= debug_csr_write_data[ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2]; - bp_e[i] <= debug_csr_write_data[0]; - end - end -end - end -endgenerate - - -generate - for (i = 0; i < watchpoints; i = i + 1) - begin : wp_seq -always @(posedge clk_i ) -begin - if (rst_i == 1'b1) - begin - wp[i] <= { 32{1'bx}}; - wpc_c[i] <= 2'b00; - end - else - begin - if (debug_csr_write_enable == 1'b1) - begin - if (debug_csr == 5'h8) - wpc_c[i] <= debug_csr_write_data[3+i*2:2+i*2]; - if (debug_csr == 5'h18 + i) - wp[i] <= debug_csr_write_data; - end - end -end - end -endgenerate - - -always @(posedge clk_i ) -begin - if (rst_i == 1'b1) - dc_re <= 1'b0; - else - begin - if ((debug_csr_write_enable == 1'b1) && (debug_csr == 5'h8)) - dc_re <= debug_csr_write_data[1]; - end -end - - - + + + -always @(posedge clk_i ) -begin - if (rst_i == 1'b1) - begin - state <= 3'b000; - dc_ss <= 1'b0; - end - else - begin - if ((debug_csr_write_enable == 1'b1) && (debug_csr == 5'h8)) - begin - dc_ss <= debug_csr_write_data[0]; - if (debug_csr_write_data[0] == 1'b0) - state <= 3'b000; - else - state <= 3'b001; - end - case (state) - 3'b001: - begin + - if ( ( (eret_q_x == 1'b1) - || (bret_q_x == 1'b1) - ) - && (stall_x == 1'b0) - ) - state <= 3'b010; - end - 3'b010: - begin + + - if ((q_x == 1'b1) && (stall_x == 1'b0)) - state <= 3'b011; - end - 3'b011: - begin + + + - - - if (dcache_refill_request == 1'b1) - state <= 3'b010; - else + + + + + + + + - if ((exception_x == 1'b1) && (q_x == 1'b1) && (stall_x == 1'b0)) - begin - dc_ss <= 1'b0; - state <= 3'b100; - end - end - 3'b100: - begin - - - if (dcache_refill_request == 1'b1) - state <= 3'b010; - else - - state <= 3'b000; - end - endcase - end -end - -endmodule - @@ -22984,7 +23083,7 @@ endmodule -module lm32_instruction_unit_full_debug ( +module lm32_instruction_unit_full ( clk_i, rst_i, @@ -23037,12 +23136,11 @@ module lm32_instruction_unit_full_debug ( + + + + - jtag_read_enable, - jtag_write_enable, - jtag_write_data, - jtag_address, - @@ -23078,10 +23176,9 @@ module lm32_instruction_unit_full_debug ( + + - jtag_read_data, - jtag_access_complete, - @@ -23171,12 +23268,11 @@ input i_rty_i; + + + + -input jtag_read_enable; -input jtag_write_enable; -input [ 7:0] jtag_write_data; -input [ (32-1):0] jtag_address; - @@ -23217,11 +23313,11 @@ wire icache_refilling; output [ (32-1):0] i_dat_o; + -reg [ (32-1):0] i_dat_o; - - +wire [ (32-1):0] i_dat_o; + output [ (32-1):0] i_adr_o; reg [ (32-1):0] i_adr_o; @@ -23229,21 +23325,21 @@ output i_cyc_o; reg i_cyc_o; output [ (4-1):0] i_sel_o; + -reg [ (4-1):0] i_sel_o; - - +wire [ (4-1):0] i_sel_o; + output i_stb_o; reg i_stb_o; output i_we_o; + -reg i_we_o; - - +wire i_we_o; + output [ (3-1):0] i_cti_o; reg [ (3-1):0] i_cti_o; @@ -23255,12 +23351,11 @@ wire [ (2-1):0] i_bte_o; + + + + -output [ 7:0] jtag_read_data; -reg [ 7:0] jtag_read_data; -output jtag_access_complete; -wire jtag_access_complete; - @@ -23326,9 +23421,8 @@ reg bus_error_f; + -reg jtag_access; - @@ -23446,7 +23540,7 @@ endfunction -lm32_icache_full_debug #( +lm32_icache_full #( .associativity (associativity), .sets (sets), .bytes_per_line (bytes_per_line), @@ -23569,11 +23663,11 @@ assign instruction_f = icache_data_f; - - - - +assign i_dat_o = 32'd0; +assign i_we_o = 1'b0; +assign i_sel_o = 4'b1111; + assign i_bte_o = 2'b00; @@ -23690,18 +23784,17 @@ end - -assign jtag_access_complete = (i_cyc_o == 1'b1) && ((i_ack_i == 1'b1) || (i_err_i == 1'b1)) && (jtag_access == 1'b1); -always @(*) -begin - case (jtag_address[1:0]) - 2'b00: jtag_read_data = i_dat_i[ 31:24]; - 2'b01: jtag_read_data = i_dat_i[ 23:16]; - 2'b10: jtag_read_data = i_dat_i[ 15:8]; - 2'b11: jtag_read_data = i_dat_i[ 7:0]; - endcase -end + + + + + + + + + + @@ -23726,11 +23819,10 @@ begin + + + - i_we_o <= 1'b0; - i_sel_o <= 4'b1111; - jtag_access <= 1'b0; - end else @@ -23743,16 +23835,15 @@ begin if ((i_ack_i == 1'b1) || (i_err_i == 1'b1)) begin + + + + + + + + - if (jtag_access == 1'b1) - begin - i_cyc_o <= 1'b0; - i_stb_o <= 1'b0; - i_we_o <= 1'b0; - jtag_access <= 1'b0; - end - else - begin if (last_word == 1'b1) @@ -23785,10 +23876,9 @@ begin if ((icache_refill_request == 1'b1) && (icache_refill_ready == 1'b0)) begin - - - i_sel_o <= 4'b1111; - + + + i_adr_o <= {first_address, 2'b00}; i_cyc_o <= 1'b1; @@ -23802,27 +23892,26 @@ begin end + + + + + + + + + + + + + + + + + + + - else - begin - if ((jtag_read_enable == 1'b1) || (jtag_write_enable == 1'b1)) - begin - case (jtag_address[1:0]) - 2'b00: i_sel_o <= 4'b1000; - 2'b01: i_sel_o <= 4'b0100; - 2'b10: i_sel_o <= 4'b0010; - 2'b11: i_sel_o <= 4'b0001; - endcase - i_adr_o <= jtag_address; - i_dat_o <= {4{jtag_write_data}}; - i_cyc_o <= 1'b1; - i_stb_o <= 1'b1; - i_we_o <= jtag_write_enable; - i_cti_o <= 3'b111; - jtag_access <= 1'b1; - end - end - @@ -24297,523 +24386,443 @@ endmodule + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + - - + + + + + + + + + + - - - - - - - - - - -module lm32_jtag_full_debug ( - clk_i, - rst_i, - jtag_clk, - jtag_update, - jtag_reg_q, - jtag_reg_addr_q, - - - csr, - csr_write_enable, - csr_write_data, - stall_x, + + + + + + + + + + - - - jtag_read_data, - jtag_access_complete, + + - - - exception_q_w, - - - jtx_csr_read_data, - jrx_csr_read_data, + + + - - - jtag_csr_write_enable, - jtag_csr_write_data, - jtag_csr, - jtag_read_enable, - jtag_write_enable, - jtag_write_data, - jtag_address, + + + + + + + - - - jtag_break, - jtag_reset, + + - jtag_reg_d, - jtag_reg_addr_d - ); - + + + -input clk_i; -input rst_i; -input jtag_clk; -input jtag_update; -input [ 7:0] jtag_reg_q; -input [2:0] jtag_reg_addr_q; + + - + + + + -input [ (5-1):0] csr; -input csr_write_enable; -input [ (32-1):0] csr_write_data; -input stall_x; + + + + - - -input [ 7:0] jtag_read_data; -input jtag_access_complete; + + - - -input exception_q_w; + - - -output [ (32-1):0] jtx_csr_read_data; -wire [ (32-1):0] jtx_csr_read_data; -output [ (32-1):0] jrx_csr_read_data; -wire [ (32-1):0] jrx_csr_read_data; + + + + - - -output jtag_csr_write_enable; -reg jtag_csr_write_enable; -output [ (32-1):0] jtag_csr_write_data; -wire [ (32-1):0] jtag_csr_write_data; -output [ (5-1):0] jtag_csr; -wire [ (5-1):0] jtag_csr; -output jtag_read_enable; -reg jtag_read_enable; -output jtag_write_enable; -reg jtag_write_enable; -output [ 7:0] jtag_write_data; -wire [ 7:0] jtag_write_data; -output [ (32-1):0] jtag_address; -wire [ (32-1):0] jtag_address; + + + + + + + + + + + + + + - - -output jtag_break; -reg jtag_break; -output jtag_reset; -reg jtag_reset; + + + + -output [ 7:0] jtag_reg_d; -reg [ 7:0] jtag_reg_d; -output [2:0] jtag_reg_addr_d; -wire [2:0] jtag_reg_addr_d; + + + + -reg rx_update; -reg rx_update_r; -reg rx_update_r_r; -reg rx_update_r_r_r; - + + + + -wire [ 7:0] rx_byte; -wire [2:0] rx_addr; + - -reg [ 7:0] uart_tx_byte; -reg uart_tx_valid; -reg [ 7:0] uart_rx_byte; -reg uart_rx_valid; - + + + + + -reg [ 3:0] command; - -reg [ 7:0] jtag_byte_0; -reg [ 7:0] jtag_byte_1; -reg [ 7:0] jtag_byte_2; -reg [ 7:0] jtag_byte_3; -reg [ 7:0] jtag_byte_4; -reg processing; + + + + + + + -reg [ 3:0] state; - + - -assign jtag_csr_write_data = {jtag_byte_0, jtag_byte_1, jtag_byte_2, jtag_byte_3}; -assign jtag_csr = jtag_byte_4[ (5-1):0]; -assign jtag_address = {jtag_byte_0, jtag_byte_1, jtag_byte_2, jtag_byte_3}; -assign jtag_write_data = jtag_byte_4; + + + + - - -assign jtag_reg_addr_d[1:0] = {uart_rx_valid, uart_tx_valid}; - - - + + - + -assign jtag_reg_addr_d[2] = processing; + - - -assign jtx_csr_read_data = {{ 32-9{1'b0}}, uart_tx_valid, 8'h00}; -assign jrx_csr_read_data = {{ 32-9{1'b0}}, uart_rx_valid, uart_rx_byte}; - + + + -assign rx_byte = jtag_reg_q; -assign rx_addr = jtag_reg_addr_q; + + -always @(posedge clk_i ) -begin - if (rst_i == 1'b1) - begin - rx_update <= 1'b0; - rx_update_r <= 1'b0; - rx_update_r_r <= 1'b0; - rx_update_r_r_r <= 1'b0; - end - else - begin - rx_update <= jtag_update; - rx_update_r <= rx_update; - rx_update_r_r <= rx_update_r; - rx_update_r_r_r <= rx_update_r_r; - end -end + + + + + + + + + + + + + + + -always @(posedge clk_i ) -begin - if (rst_i == 1'b1) - begin - state <= 4'h0; - command <= 4'b0000; - jtag_reg_d <= 8'h00; - - processing <= 1'b0; - jtag_csr_write_enable <= 1'b0; - jtag_read_enable <= 1'b0; - jtag_write_enable <= 1'b0; - - + - jtag_break <= 1'b0; - jtag_reset <= 1'b0; + + + + + + + + + - - - uart_tx_byte <= 8'h00; - uart_tx_valid <= 1'b0; - uart_rx_byte <= 8'h00; - uart_rx_valid <= 1'b0; + + - end - else - begin - - - if ((csr_write_enable == 1'b1) && (stall_x == 1'b0)) - begin - case (csr) - 5'he: - begin + + + + + + + + + + + + + + + - uart_tx_byte <= csr_write_data[ 7:0]; - uart_tx_valid <= 1'b1; - end - 5'hf: - begin + + + + + - uart_rx_valid <= 1'b0; - end - endcase - end - - - + + + + + + + + + + - if (exception_q_w == 1'b1) - begin - jtag_break <= 1'b0; - jtag_reset <= 1'b0; - end - - case (state) - 4'h0: - begin + + + - if ((~rx_update_r_r_r & rx_update_r_r) == 1'b1) - begin - command <= rx_byte[7:4]; - case (rx_addr) - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - 3'b000: - begin - case (rx_byte[7:4]) - + + + + + + + - 4'b0001: - state <= 4'h1; - 4'b0011: - begin - {jtag_byte_2, jtag_byte_3} <= {jtag_byte_2, jtag_byte_3} + 1'b1; - state <= 4'h6; - end - 4'b0010: - state <= 4'h1; - 4'b0100: - begin - {jtag_byte_2, jtag_byte_3} <= {jtag_byte_2, jtag_byte_3} + 1'b1; - state <= 5; - end - 4'b0101: - state <= 4'h1; - + - 4'b0110: - begin - - - uart_rx_valid <= 1'b0; - uart_tx_valid <= 1'b0; - + + - jtag_break <= 1'b1; - end - 4'b0111: - begin - - - uart_rx_valid <= 1'b0; - uart_tx_valid <= 1'b0; - + + + + + + + + + + + - jtag_reset <= 1'b1; - end - endcase - end + + + + + - - + + - 3'b001: - begin - uart_rx_byte <= rx_byte; - uart_rx_valid <= 1'b1; - end - 3'b010: - begin - jtag_reg_d <= uart_tx_byte; - uart_tx_valid <= 1'b0; - end - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - default: - ; - endcase - end - end - 4'h1: - begin - if ((~rx_update_r_r_r & rx_update_r_r) == 1'b1) - begin - jtag_byte_0 <= rx_byte; - state <= 4'h2; - end - end - 4'h2: - begin - if ((~rx_update_r_r_r & rx_update_r_r) == 1'b1) - begin - jtag_byte_1 <= rx_byte; - state <= 4'h3; - end - end - 4'h3: - begin - if ((~rx_update_r_r_r & rx_update_r_r) == 1'b1) - begin - jtag_byte_2 <= rx_byte; - state <= 4'h4; - end - end - 4'h4: - begin - if ((~rx_update_r_r_r & rx_update_r_r) == 1'b1) - begin - jtag_byte_3 <= rx_byte; - if (command == 4'b0001) - state <= 4'h6; - else - state <= 4'h5; - end - end - 4'h5: - begin - if ((~rx_update_r_r_r & rx_update_r_r) == 1'b1) - begin - jtag_byte_4 <= rx_byte; - state <= 4'h6; - end - end - 4'h6: - begin - case (command) - 4'b0001, - 4'b0011: - begin - jtag_read_enable <= 1'b1; - processing <= 1'b1; - state <= 4'h7; - end - 4'b0010, - 4'b0100: - begin - jtag_write_enable <= 1'b1; - processing <= 1'b1; - state <= 4'h7; - end - 4'b0101: - begin - jtag_csr_write_enable <= 1'b1; - processing <= 1'b1; - state <= 4'h8; - end - endcase - end - 4'h7: - begin - if (jtag_access_complete == 1'b1) - begin - jtag_read_enable <= 1'b0; - jtag_reg_d <= jtag_read_data; - jtag_write_enable <= 1'b0; - processing <= 1'b0; - state <= 4'h0; - end - end - 4'h8: - begin - jtag_csr_write_enable <= 1'b0; - processing <= 1'b0; - state <= 4'h0; - end - - endcase - end -end - -endmodule - @@ -25168,7 +25177,7 @@ endmodule -module lm32_interrupt_full_debug ( +module lm32_interrupt_full ( clk_i, rst_i, @@ -25177,18 +25186,17 @@ module lm32_interrupt_full_debug ( stall_x, - - non_debug_exception, - debug_exception, - + + + exception, + eret_q_x, + - bret_q_x, - csr, csr_write_data, @@ -25217,21 +25225,20 @@ input [interrupts-1:0] interrupt; input stall_x; + + -input non_debug_exception; -input debug_exception; - - +input exception; + input eret_q_x; + -input bret_q_x; - -input [ (5-1):0] csr; +input [ (3-1):0] csr; input [ (32-1):0] csr_write_data; input csr_write_enable; @@ -25258,9 +25265,8 @@ wire [interrupts-1:0] interrupt_n_exception; reg ie; reg eie; + -reg bie; - reg [interrupts-1:0] ip; reg [interrupts-1:0] im; @@ -25280,11 +25286,11 @@ assign asserted = ip | interrupt; assign ie_csr_read_data = {{ 32-3{1'b0}}, - - bie, - + + 1'b0, + eie, ie @@ -25298,19 +25304,19 @@ generate always @(*) begin case (csr) - 5'h0: csr_read_data = {{ 32-3{1'b0}}, + 3'h0: csr_read_data = {{ 32-3{1'b0}}, + - bie, - - + 1'b0, + eie, ie }; - 5'h2: csr_read_data = ip; - 5'h1: csr_read_data = im; + 3'h2: csr_read_data = ip; + 3'h1: csr_read_data = im; default: csr_read_data = { 32{1'bx}}; endcase end @@ -25321,18 +25327,18 @@ end always @(*) begin case (csr) - 5'h0: csr_read_data = {{ 32-3{1'b0}}, + 3'h0: csr_read_data = {{ 32-3{1'b0}}, + - bie, - - + 1'b0, + eie, ie }; - 5'h2: csr_read_data = ip; + 3'h2: csr_read_data = ip; default: csr_read_data = { 32{1'bx}}; endcase end @@ -25361,9 +25367,8 @@ always @(posedge clk_i ) ie <= 1'b0; eie <= 1'b0; + - bie <= 1'b0; - im <= {interrupts{1'b0}}; ip <= {interrupts{1'b0}}; @@ -25375,21 +25380,13 @@ always @(posedge clk_i ) ip <= asserted; - - if (non_debug_exception == 1'b1) - begin + + - eie <= ie; - ie <= 1'b0; - end - else if (debug_exception == 1'b1) - begin + + + - bie <= ie; - ie <= 1'b0; - end - - @@ -25397,6 +25394,14 @@ always @(posedge clk_i ) + if (exception == 1'b1) + begin + + eie <= ie; + ie <= 1'b0; + end + + else if (stall_x == 1'b0) begin @@ -25414,28 +25419,26 @@ always @(posedge clk_i ) - - else if (bret_q_x == 1'b1) - ie <= bie; - + + + else if (csr_write_enable == 1'b1) begin - if (csr == 5'h0) + if (csr == 3'h0) begin ie <= csr_write_data[0]; eie <= csr_write_data[1]; + - bie <= csr_write_data[2]; - end - if (csr == 5'h1) + if (csr == 3'h1) im <= csr_write_data[interrupts-1:0]; - if (csr == 5'h2) + if (csr == 3'h2) ip <= asserted & ~csr_write_data[interrupts-1:0]; end end @@ -25452,9 +25455,8 @@ always @(posedge clk_i ) ie <= 1'b0; eie <= 1'b0; + - bie <= 1'b0; - ip <= {interrupts{1'b0}}; eie_delay <= 0; @@ -25464,21 +25466,13 @@ always @(posedge clk_i ) ip <= asserted; - - if (non_debug_exception == 1'b1) - begin + + - eie <= ie; - ie <= 1'b0; - end - else if (debug_exception == 1'b1) - begin + + + - bie <= ie; - ie <= 1'b0; - end - - @@ -25486,6 +25480,14 @@ always @(posedge clk_i ) + if (exception == 1'b1) + begin + + eie <= ie; + ie <= 1'b0; + end + + else if (stall_x == 1'b0) begin @@ -25501,26 +25503,24 @@ always @(posedge clk_i ) end - - else if (bret_q_x == 1'b1) - ie <= bie; - + + + else if (csr_write_enable == 1'b1) begin - if (csr == 5'h0) + if (csr == 3'h0) begin ie <= csr_write_data[0]; eie <= csr_write_data[1]; + - bie <= csr_write_data[2]; - end - if (csr == 5'h2) + if (csr == 3'h2) ip <= asserted & ~csr_write_data[interrupts-1:0]; end end @@ -25577,6 +25577,10 @@ endmodule + + + + @@ -25602,13 +25606,20 @@ endmodule - - - - + + - + + + + + + + + + + @@ -25708,18 +25719,16 @@ endmodule - - - - + + + - @@ -25748,24 +25757,25 @@ endmodule - + + - - + + + + - - @@ -25866,24 +25876,34 @@ endmodule - - + + + + + + + + + + - + - + + + @@ -25895,6 +25915,8 @@ endmodule + + @@ -25902,27 +25924,28 @@ endmodule - - + - - + - - - - - - - - + + + + + + + + + + + @@ -25984,14 +26007,14 @@ endmodule - - + + + - @@ -26081,7 +26104,7 @@ endmodule -module lm32_top_medium ( +module lm32_top_medium_debug ( clk_i, rst_i, @@ -26238,14 +26261,15 @@ wire [ (2-1):0] D_BTE_O; - - - - - - - +wire [ 7:0] jtag_reg_d; +wire [ 7:0] jtag_reg_q; +wire jtag_update; +wire [2:0] jtag_reg_addr_d; +wire [2:0] jtag_reg_addr_q; +wire jtck; +wire jrstn; + @@ -26324,7 +26348,7 @@ endfunction -lm32_cpu_medium cpu ( +lm32_cpu_medium_debug cpu ( .clk_i (clk_i), @@ -26345,12 +26369,13 @@ lm32_cpu_medium cpu ( - - - - - + + .jtag_clk (jtck), + .jtag_update (jtag_update), + .jtag_reg_q (jtag_reg_q), + .jtag_reg_addr_q (jtag_reg_addr_q), + @@ -26379,9 +26404,10 @@ lm32_cpu_medium cpu ( - - + .jtag_reg_d (jtag_reg_d), + .jtag_reg_addr_d (jtag_reg_addr_d), + @@ -26416,20 +26442,21 @@ lm32_cpu_medium cpu ( .D_BTE_O (D_BTE_O) ); - - + + +jtag_cores jtag_cores ( - - - - - - - - + .reg_d (jtag_reg_d), + .reg_addr_d (jtag_reg_addr_d), - + .reg_update (jtag_update), + .reg_q (jtag_reg_q), + .reg_addr_q (jtag_reg_addr_q), + .jtck (jtck), + .jrstn (jrstn) + ); + endmodule @@ -26801,7 +26828,7 @@ endmodule -module lm32_mc_arithmetic_medium ( +module lm32_mc_arithmetic_medium_debug ( clk_i, rst_i, @@ -27457,7 +27484,7 @@ endmodule -module lm32_cpu_medium ( +module lm32_cpu_medium_debug ( clk_i, @@ -27478,12 +27505,13 @@ module lm32_cpu_medium ( - - - - - + + jtag_clk, + jtag_update, + jtag_reg_q, + jtag_reg_addr_q, + @@ -27512,9 +27540,10 @@ module lm32_cpu_medium ( - - + jtag_reg_d, + jtag_reg_addr_d, + @@ -27555,24 +27584,25 @@ module lm32_cpu_medium ( parameter eba_reset = 32'h00000000; - +parameter deba_reset = 32'h10000000; + - - - - - - -parameter icache_associativity = 1; -parameter icache_sets = 512; -parameter icache_bytes_per_line = 16; -parameter icache_base_address = 0; -parameter icache_limit = 0; +parameter icache_associativity = 1; +parameter icache_sets = 256; +parameter icache_bytes_per_line = 16; +parameter icache_base_address = 32'h0; +parameter icache_limit = 32'h7fffffff; + + + + + + @@ -27592,11 +27622,11 @@ parameter dcache_limit = 0; - - -parameter watchpoints = 0; +parameter watchpoints = 32'h4; + + @@ -27638,11 +27668,12 @@ input [ (32-1):0] interrupt; - - - - +input jtag_clk; +input jtag_update; +input [ 7:0] jtag_reg_q; +input [2:0] jtag_reg_addr_q; + @@ -27682,11 +27713,12 @@ input D_RTY_I; - - - - +output [ 7:0] jtag_reg_d; +wire [ 7:0] jtag_reg_d; +output [2:0] jtag_reg_addr_d; +wire [2:0] jtag_reg_addr_d; + @@ -27750,8 +27782,9 @@ wire [ (2-1):0] D_BTE_O; - +reg valid_a; + reg valid_f; reg valid_d; @@ -27774,8 +27807,8 @@ reg [ 1:0] size_x; wire branch_d; wire branch_predict_d; wire branch_predict_taken_d; -wire [ ((32-2)+2-1):2] branch_predict_address_d; -wire [ ((32-2)+2-1):2] branch_target_d; +wire [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] branch_predict_address_d; +wire [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] branch_target_d; wire bi_unconditional; wire bi_conditional; reg branch_x; @@ -27787,9 +27820,9 @@ reg branch_predict_taken_m; wire branch_mispredict_taken_m; wire branch_flushX_m; wire branch_reg_d; -wire [ ((32-2)+2-1):2] branch_offset_d; -reg [ ((32-2)+2-1):2] branch_target_x; -reg [ ((32-2)+2-1):2] branch_target_m; +wire [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] branch_offset_d; +reg [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] branch_target_x; +reg [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] branch_target_m; wire [ 0:0] d_result_sel_0_d; wire [ 1:0] d_result_sel_1_d; @@ -27864,14 +27897,15 @@ wire [ (5-1):0] write_idx_d; reg [ (5-1):0] write_idx_x; reg [ (5-1):0] write_idx_m; reg [ (5-1):0] write_idx_w; -wire [ (3-1):0] csr_d; -reg [ (3-1):0] csr_x; +wire [ (5-1):0] csr_d; +reg [ (5-1):0] csr_x; wire [ (3-1):0] condition_d; reg [ (3-1):0] condition_x; - - +wire break_d; +reg break_x; + wire scall_d; reg scall_x; @@ -27884,14 +27918,16 @@ reg eret_m; - - - - - + +wire bret_d; +reg bret_x; +wire bret_q_x; +reg bret_m; + + wire csr_write_enable_d; reg csr_write_enable_x; @@ -28043,11 +28079,11 @@ wire [ (32-1):0] cfg2; reg [ (32-1):0] csr_read_data_x; -wire [ ((32-2)+2-1):2] pc_f; -wire [ ((32-2)+2-1):2] pc_d; -wire [ ((32-2)+2-1):2] pc_x; -wire [ ((32-2)+2-1):2] pc_m; -wire [ ((32-2)+2-1):2] pc_w; +wire [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] pc_f; +wire [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] pc_d; +wire [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] pc_x; +wire [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] pc_m; +wire [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] pc_w; @@ -28061,12 +28097,13 @@ wire [ (32-1):0] instruction_f; wire [ (32-1):0] instruction_d; - - - - - +wire iflush; +wire icache_stall_request; +wire icache_restart_request; +wire icache_refill_request; +wire icache_refilling; + @@ -28092,25 +28129,32 @@ wire stall_wb_load; - - - - - - - - + +wire [ (32-1):0] jtx_csr_read_data; +wire [ (32-1):0] jrx_csr_read_data; + - - +wire jtag_csr_write_enable; +wire [ (32-1):0] jtag_csr_write_data; +wire [ (5-1):0] jtag_csr; +wire jtag_read_enable; +wire [ 7:0] jtag_read_data; +wire jtag_write_enable; +wire [ 7:0] jtag_write_data; +wire [ (32-1):0] jtag_address; +wire jtag_access_complete; - + + +wire jtag_break; + + @@ -28140,10 +28184,11 @@ wire kill_x; wire kill_m; wire kill_w; -reg [ (32-2)+2-1:8] eba; +reg [ (clogb2(32'h7fffffff-32'h0)-2)+2-1:8] eba; - +reg [ (clogb2(32'h7fffffff-32'h0)-2)+2-1:8] deba; + reg [ (3-1):0] eid_x; @@ -28153,34 +28198,39 @@ reg [ (3-1):0] eid_x; - - - - - - - + + +wire dc_ss; + +wire dc_re; +wire exception_x; +reg exception_m; +wire debug_exception_x; +reg debug_exception_m; +reg debug_exception_w; +wire debug_exception_q_w; +wire non_debug_exception_x; +reg non_debug_exception_m; +reg non_debug_exception_w; +wire non_debug_exception_q_w; - + -wire exception_x; -reg exception_m; -reg exception_w; -wire exception_q_w; - + - - +wire reset_exception; + + @@ -28188,9 +28238,10 @@ wire interrupt_exception; - - +wire breakpoint_exception; +wire watchpoint_exception; + @@ -28271,7 +28322,7 @@ endfunction -lm32_instruction_unit_medium #( +lm32_instruction_unit_medium_debug #( .associativity (icache_associativity), .sets (icache_sets), .bytes_per_line (icache_bytes_per_line), @@ -28302,8 +28353,9 @@ lm32_instruction_unit_medium #( .branch_mispredict_taken_m (branch_mispredict_taken_m), .branch_target_m (branch_target_m), - + .iflush (iflush), + @@ -28327,11 +28379,12 @@ lm32_instruction_unit_medium #( - - - - + .jtag_read_enable (jtag_read_enable), + .jtag_write_enable (jtag_write_enable), + .jtag_write_data (jtag_write_data), + .jtag_address (jtag_address), + @@ -28341,11 +28394,12 @@ lm32_instruction_unit_medium #( .pc_m (pc_m), .pc_w (pc_w), - - - - + .icache_stall_request (icache_stall_request), + .icache_restart_request (icache_restart_request), + .icache_refill_request (icache_refill_request), + .icache_refilling (icache_refilling), + @@ -28366,9 +28420,10 @@ lm32_instruction_unit_medium #( - - + .jtag_read_data (jtag_read_data), + .jtag_access_complete (jtag_access_complete), + @@ -28383,7 +28438,7 @@ lm32_instruction_unit_medium #( ); -lm32_decoder_medium decoder ( +lm32_decoder_medium_debug decoder ( .instruction (instruction_d), @@ -28462,14 +28517,16 @@ lm32_decoder_medium decoder ( .branch_reg (branch_reg_d), .condition (condition_d), - + .break_opcode (break_d), + .scall (scall_d), .eret (eret_d), - + .bret (bret_d), + @@ -28479,7 +28536,7 @@ lm32_decoder_medium decoder ( ); -lm32_load_store_unit_medium #( +lm32_load_store_unit_medium_debug #( .associativity (dcache_associativity), .sets (dcache_sets), .bytes_per_line (dcache_bytes_per_line), @@ -28645,7 +28702,7 @@ lm32_multiplier multiplier ( -lm32_interrupt_medium interrupt_unit ( +lm32_interrupt_medium_debug interrupt_unit ( .clk_i (clk_i), .rst_i (rst_i), @@ -28654,17 +28711,18 @@ lm32_interrupt_medium interrupt_unit ( .stall_x (stall_x), - - - - .exception (exception_q_w), + .non_debug_exception (non_debug_exception_q_w), + .debug_exception (debug_exception_q_w), + + .eret_q_x (eret_q_x), - + .bret_q_x (bret_q_x), + .csr (csr_x), .csr_write_data (operand_1_x), @@ -28679,95 +28737,116 @@ lm32_interrupt_medium interrupt_unit ( - + +lm32_jtag_medium_debug jtag ( - - + .clk_i (clk_i), + .rst_i (rst_i), - - - - + .jtag_clk (jtag_clk), + .jtag_update (jtag_update), + .jtag_reg_q (jtag_reg_q), + .jtag_reg_addr_q (jtag_reg_addr_q), + + + .csr (csr_x), + .csr_write_data (operand_1_x), + .csr_write_enable (csr_write_enable_q_x), + .stall_x (stall_x), - - - - + + + .jtag_read_data (jtag_read_data), + .jtag_access_complete (jtag_access_complete), - - + + + .exception_q_w (debug_exception_q_w || non_debug_exception_q_w), - + + + .jtx_csr_read_data (jtx_csr_read_data), + .jrx_csr_read_data (jrx_csr_read_data), - - + + + .jtag_csr_write_enable (jtag_csr_write_enable), + .jtag_csr_write_data (jtag_csr_write_data), + .jtag_csr (jtag_csr), + .jtag_read_enable (jtag_read_enable), + .jtag_write_enable (jtag_write_enable), + .jtag_write_data (jtag_write_data), + .jtag_address (jtag_address), - - - - - - - + + + .jtag_break (jtag_break), + .jtag_reset (reset_exception), - - - - - - + .jtag_reg_d (jtag_reg_d), + .jtag_reg_addr_d (jtag_reg_addr_d) + ); + - - - - + +lm32_debug_medium_debug #( + .breakpoints (breakpoints), + .watchpoints (watchpoints) + ) hw_debug ( - - - - - - - - - - - - - + .clk_i (clk_i), + .rst_i (rst_i), + .pc_x (pc_x), + .load_x (load_x), + .store_x (store_x), + .load_store_address_x (adder_result_x), + .csr_write_enable_x (csr_write_enable_q_x), + .csr_write_data (operand_1_x), + .csr_x (csr_x), + + .jtag_csr_write_enable (jtag_csr_write_enable), + .jtag_csr_write_data (jtag_csr_write_data), + .jtag_csr (jtag_csr), - - - - - - + + + + .eret_q_x (eret_q_x), + .bret_q_x (bret_q_x), + .stall_x (stall_x), + .exception_x (exception_x), + .q_x (q_x), + - - - - - + + .dc_ss (dc_ss), + + + .dc_re (dc_re), + .bp_match (bp_match), + .wp_match (wp_match) + ); + @@ -29212,8 +29291,9 @@ assign kill_f = ( (valid_d == 1'b1) - + || (icache_refill_request == 1'b1) + @@ -29226,8 +29306,9 @@ assign kill_d = (branch_taken_m == 1'b1) - + || (icache_refill_request == 1'b1) + @@ -29256,21 +29337,25 @@ assign kill_w = 1'b0 - - - - - - - - +assign breakpoint_exception = ( ( (break_x == 1'b1) + || (bp_match == 1'b1) + ) + && (valid_x == 1'b1) + ) + + || (jtag_break == 1'b1) + + + ; + - +assign watchpoint_exception = wp_match == 1'b1; + @@ -29294,38 +29379,17 @@ assign system_call_exception = ( (scall_x == 1'b1) ); - - - - - - - - - - +assign debug_exception_x = (breakpoint_exception == 1'b1) + || (watchpoint_exception == 1'b1) + ; - - +assign non_debug_exception_x = (system_call_exception == 1'b1) + + || (reset_exception == 1'b1) - - - - - - - - - - - - - - -assign exception_x = (system_call_exception == 1'b1) @@ -29339,8 +29403,9 @@ assign exception_x = (system_call_exception == 1'b1) || ( (interrupt_exception == 1'b1) - + && (dc_ss == 1'b0) + @@ -29351,27 +29416,54 @@ assign exception_x = (system_call_exception == 1'b1) ; + +assign exception_x = (debug_exception_x == 1'b1) || (non_debug_exception_x == 1'b1); + + + + + + + + + + + + + + + + + + + + + always @(*) begin + + + + if (reset_exception == 1'b1) + eid_x = 3'h0; + else - - - - + - - - + if (breakpoint_exception == 1'b1) + eid_x = 3'd1; + else + @@ -29383,10 +29475,11 @@ begin - - - + if (watchpoint_exception == 1'b1) + eid_x = 3'd3; + else + @@ -29398,8 +29491,9 @@ begin if ( (interrupt_exception == 1'b1) - + && (dc_ss == 1'b0) + ) eid_x = 3'h6; @@ -29435,18 +29529,19 @@ assign stall_d = (stall_x == 1'b1) && (kill_d == 1'b0) ) - - - - - - - - - - - + || ( ( (break_d == 1'b1) + || (bret_d == 1'b1) + ) + && ( (load_q_x == 1'b1) + || (store_q_x == 1'b1) + || (load_q_m == 1'b1) + || (store_q_m == 1'b1) + || (D_CYC_O == 1'b1) + ) + && (kill_d == 1'b0) + ) + || ( (csr_write_enable_d == 1'b1) && (load_q_x == 1'b1) @@ -29508,16 +29603,14 @@ assign stall_m = (stall_wb_load == 1'b1) - - - - - - || (I_CYC_O == 1'b1) + || (icache_stall_request == 1'b1) + || ((I_CYC_O == 1'b1) && ((branch_m == 1'b1) || (exception_m == 1'b1))) - + + + @@ -29550,21 +29643,24 @@ assign q_x = (valid_x == 1'b1) && (kill_x == 1'b0); assign csr_write_enable_q_x = (csr_write_enable_x == 1'b1) && (q_x == 1'b1); assign eret_q_x = (eret_x == 1'b1) && (q_x == 1'b1); - +assign bret_q_x = (bret_x == 1'b1) && (q_x == 1'b1); + assign load_q_x = (load_x == 1'b1) && (q_x == 1'b1) - + && (bp_match == 1'b0) + ; assign store_q_x = (store_x == 1'b1) && (q_x == 1'b1) - + && (bp_match == 1'b0) + ; @@ -29575,12 +29671,12 @@ assign q_m = (valid_m == 1'b1) && (kill_m == 1'b0) && (exception_m == 1'b0); assign load_q_m = (load_m == 1'b1) && (q_m == 1'b1); assign store_q_m = (store_m == 1'b1) && (q_m == 1'b1); - - - -assign exception_q_w = ((exception_w == 1'b1) && (valid_w == 1'b1)); +assign debug_exception_q_w = ((debug_exception_w == 1'b1) && (valid_w == 1'b1)); +assign non_debug_exception_q_w = ((non_debug_exception_w == 1'b1) && (valid_w == 1'b1)); + + assign write_enable_q_x = (write_enable_x == 1'b1) && (valid_x == 1'b1) && (branch_flushX_m == 1'b0); @@ -29596,19 +29692,12 @@ assign cfg = { breakpoints[3:0], interrupts[5:0], - - - 1'b0, + 1'b1, - - - 1'b0, - - @@ -29617,18 +29706,25 @@ assign cfg = { - - - 1'b0, + 1'b1, + + + + 1'b1, + - 1'b0, + + + 1'b1, + + @@ -29701,19 +29797,22 @@ assign cfg2 = { - - - - - - - - - +assign iflush = ( (csr_write_enable_d == 1'b1) + && (csr_d == 5'h3) + && (stall_d == 1'b0) + && (kill_d == 1'b0) + && (valid_d == 1'b1)) - + + || + ( (jtag_csr_write_enable == 1'b1) + && (jtag_csr == 5'h3)) + + + ; + @@ -29729,7 +29828,7 @@ assign cfg2 = { -assign csr_d = read_idx_0_d[ (3-1):0]; +assign csr_d = read_idx_0_d[ (5-1):0]; always @(*) @@ -29737,27 +29836,29 @@ begin case (csr_x) - 3'h0, - 3'h1, - 3'h2: csr_read_data_x = interrupt_csr_read_data_x; + 5'h0, + 5'h1, + 5'h2: csr_read_data_x = interrupt_csr_read_data_x; - 3'h6: csr_read_data_x = cfg; - 3'h7: csr_read_data_x = {eba, 8'h00}; + 5'h6: csr_read_data_x = cfg; + 5'h7: csr_read_data_x = {eba, 8'h00}; - + 5'h9: csr_read_data_x = {deba, 8'h00}; + - - + 5'he: csr_read_data_x = jtx_csr_read_data; + 5'hf: csr_read_data_x = jrx_csr_read_data; + - 3'ha: csr_read_data_x = cfg2; + 5'ha: csr_read_data_x = cfg2; default: csr_read_data_x = { 32{1'bx}}; endcase @@ -29771,36 +29872,40 @@ end always @(posedge clk_i ) begin if (rst_i == 1'b1) - eba <= eba_reset[ (32-2)+2-1:8]; + eba <= eba_reset[ (clogb2(32'h7fffffff-32'h0)-2)+2-1:8]; else begin - if ((csr_write_enable_q_x == 1'b1) && (csr_x == 3'h7) && (stall_x == 1'b0)) - eba <= operand_1_x[ (32-2)+2-1:8]; + if ((csr_write_enable_q_x == 1'b1) && (csr_x == 5'h7) && (stall_x == 1'b0)) + eba <= operand_1_x[ (clogb2(32'h7fffffff-32'h0)-2)+2-1:8]; - - + if ((jtag_csr_write_enable == 1'b1) && (jtag_csr == 5'h7)) + eba <= jtag_csr_write_data[ (clogb2(32'h7fffffff-32'h0)-2)+2-1:8]; + end end - - - - - - - - - - - - +always @(posedge clk_i ) +begin + if (rst_i == 1'b1) + deba <= deba_reset[ (clogb2(32'h7fffffff-32'h0)-2)+2-1:8]; + else + begin + if ((csr_write_enable_q_x == 1'b1) && (csr_x == 5'h9) && (stall_x == 1'b0)) + deba <= operand_1_x[ (clogb2(32'h7fffffff-32'h0)-2)+2-1:8]; + + if ((jtag_csr_write_enable == 1'b1) && (jtag_csr == 5'h9)) + deba <= jtag_csr_write_data[ (clogb2(32'h7fffffff-32'h0)-2)+2-1:8]; + + end +end + @@ -29837,7 +29942,8 @@ end - + + @@ -29852,19 +29958,20 @@ end - - - - - - - +always @(*) +begin + if (icache_refill_request == 1'b1) + valid_a = 1'b0; + else if (icache_restart_request == 1'b1) + valid_a = 1'b1; + else + valid_a = !icache_refilling; +end - - - + + @@ -29876,7 +29983,6 @@ end - always @(posedge clk_i ) @@ -29893,11 +29999,11 @@ begin begin if ((kill_f == 1'b1) || (stall_a == 1'b0)) - - - valid_f <= 1'b1; + valid_f <= valid_a; + + else if (stall_f == 1'b0) valid_f <= 1'b0; @@ -29942,7 +30048,7 @@ begin operand_0_x <= { 32{1'b0}}; operand_1_x <= { 32{1'b0}}; store_operand_x <= { 32{1'b0}}; - branch_target_x <= { (32-2){1'b0}}; + branch_target_x <= { (clogb2(32'h7fffffff-32'h0)-2){1'b0}}; x_result_sel_csr_x <= 1'b0; @@ -29979,7 +30085,7 @@ begin m_bypass_enable_x <= 1'b0; write_enable_x <= 1'b0; write_idx_x <= { 5{1'b0}}; - csr_x <= { 3{1'b0}}; + csr_x <= { 5{1'b0}}; load_x <= 1'b0; store_x <= 1'b0; size_x <= { 2{1'b0}}; @@ -30002,14 +30108,16 @@ begin branch_predict_taken_x <= 1'b0; condition_x <= 3'b000; - + break_x <= 1'b0; + scall_x <= 1'b0; eret_x <= 1'b0; - + bret_x <= 1'b0; + @@ -30018,7 +30126,7 @@ begin csr_write_enable_x <= 1'b0; operand_m <= { 32{1'b0}}; - branch_target_m <= { (32-2){1'b0}}; + branch_target_m <= { (clogb2(32'h7fffffff-32'h0)-2){1'b0}}; m_result_sel_compare_m <= 1'b0; @@ -30051,9 +30159,10 @@ begin - - + debug_exception_m <= 1'b0; + non_debug_exception_m <= 1'b0; + operand_w <= { 32{1'b0}}; w_result_sel_load_w <= 1'b0; @@ -30065,12 +30174,12 @@ begin write_idx_w <= { 5{1'b0}}; write_enable_w <= 1'b0; - - - - exception_w <= 1'b0; + debug_exception_w <= 1'b0; + non_debug_exception_w <= 1'b0; + + @@ -30090,7 +30199,7 @@ begin operand_0_x <= d_result_0; operand_1_x <= d_result_1; store_operand_x <= bypass_data_1; - branch_target_x <= branch_reg_d == 1'b1 ? bypass_data_0[ ((32-2)+2-1):2] : branch_target_d; + branch_target_x <= branch_reg_d == 1'b1 ? bypass_data_0[ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] : branch_target_d; x_result_sel_csr_x <= x_result_sel_csr_d; @@ -30149,8 +30258,9 @@ begin condition_x <= condition_d; csr_write_enable_x <= csr_write_enable_d; - + break_x <= break_d; + scall_x <= scall_d; @@ -30159,8 +30269,9 @@ begin eret_x <= eret_d; - + bret_x <= bret_d; + write_enable_x <= write_enable_d; end @@ -30212,40 +30323,40 @@ begin + - - - - - - - - - if (exception_x == 1'b1) + if (non_debug_exception_x == 1'b1) write_idx_m <= 5'd30; + else if (debug_exception_x == 1'b1) + write_idx_m <= 5'd31; else write_idx_m <= write_idx_x; + + + + + condition_met_m <= condition_met_x; - - - - - - - - - - - branch_target_m <= exception_x == 1'b1 ? {eba, eid_x, {3{1'b0}}} : branch_target_x; + if (exception_x == 1'b1) + if ((dc_re == 1'b1) + || ((debug_exception_x == 1'b1) + && (non_debug_exception_x == 1'b0))) + branch_target_m <= {deba, eid_x, {3{1'b0}}}; + else + branch_target_m <= {eba, eid_x, {3{1'b0}}}; + else + branch_target_m <= branch_target_x; + + @@ -30257,14 +30368,16 @@ begin eret_m <= eret_q_x; - + bret_m <= bret_q_x; + write_enable_m <= exception_x == 1'b1 ? 1'b1 : write_enable_x; - - + debug_exception_m <= debug_exception_x; + non_debug_exception_m <= non_debug_exception_x; + end @@ -30310,12 +30423,12 @@ begin write_enable_w <= write_enable_m; - - - - exception_w <= exception_m; + debug_exception_w <= debug_exception_m; + non_debug_exception_w <= non_debug_exception_m; + + @@ -30860,7 +30973,7 @@ endmodule -module lm32_load_store_unit_medium ( +module lm32_load_store_unit_medium_debug ( clk_i, rst_i, @@ -32172,7 +32285,7 @@ endmodule -module lm32_decoder_medium ( +module lm32_decoder_medium_debug ( instruction, @@ -32251,14 +32364,16 @@ module lm32_decoder_medium ( bi_conditional, bi_unconditional, - + break_opcode, + scall, eret, - + bret, + @@ -32342,8 +32457,8 @@ output [ (5-1):0] write_idx; wire [ (5-1):0] write_idx; output [ (32-1):0] immediate; wire [ (32-1):0] immediate; -output [ ((32-2)+2-1):2] branch_offset; -wire [ ((32-2)+2-1):2] branch_offset; +output [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] branch_offset; +wire [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] branch_offset; output load; wire load; output store; @@ -32392,18 +32507,20 @@ wire bi_conditional; output bi_unconditional; wire bi_unconditional; - - +output break_opcode; +wire break_opcode; + output scall; wire scall; output eret; wire eret; - - +output bret; +wire bret; + @@ -32757,14 +32874,16 @@ assign branch = bra | call; assign branch_reg = op_call | op_b; assign condition = instruction[28:26]; - +assign break_opcode = op_raise & ~instruction[2]; + assign scall = op_raise & instruction[2]; assign eret = op_b & (instruction[25:21] == 5'd30); - +assign bret = op_b & (instruction[25:21] == 5'd31); + @@ -33153,426 +33272,499 @@ endmodule - - - - - - - - - - - - - - - - - - - - + + + + - - - - - - - - - - - - - - - - - - - - - - - - + + + + - - - - - + - - - - - - - - - + + + + - - + - - + - - - - - - + - - + - - - - - - - - - - - - - +module lm32_icache_medium_debug ( - + clk_i, + rst_i, + stall_a, + stall_f, + address_a, + address_f, + read_enable_f, + refill_ready, + refill_data, + iflush, + + valid_d, + branch_predict_taken_d, + + stall_request, + restart_request, + refill_request, + refill_address, + refilling, + inst + ); - - - - - - - - - - - - - - - - +parameter associativity = 1; +parameter sets = 512; +parameter bytes_per_line = 16; +parameter base_address = 0; +parameter limit = 0; - - - - +localparam addr_offset_width = clogb2(bytes_per_line)-1-2; +localparam addr_set_width = clogb2(sets)-1; +localparam addr_offset_lsb = 2; +localparam addr_offset_msb = (addr_offset_lsb+addr_offset_width-1); +localparam addr_set_lsb = (addr_offset_msb+1); +localparam addr_set_msb = (addr_set_lsb+addr_set_width-1); +localparam addr_tag_lsb = (addr_set_msb+1); +localparam addr_tag_msb = clogb2( 32'h7fffffff- 32'h0)-1; +localparam addr_tag_width = (addr_tag_msb-addr_tag_lsb+1); - +input clk_i; +input rst_i; - +input stall_a; +input stall_f; +input valid_d; +input branch_predict_taken_d; + +input [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] address_a; +input [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] address_f; +input read_enable_f; +input refill_ready; +input [ (32-1):0] refill_data; +input iflush; + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +output stall_request; +wire stall_request; +output restart_request; +reg restart_request; +output refill_request; +wire refill_request; +output [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] refill_address; +reg [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] refill_address; +output refilling; +reg refilling; +output [ (32-1):0] inst; +wire [ (32-1):0] inst; +wire enable; +wire [0:associativity-1] way_mem_we; +wire [ (32-1):0] way_data[0:associativity-1]; +wire [ ((addr_tag_width+1)-1):1] way_tag[0:associativity-1]; +wire [0:associativity-1] way_valid; +wire [0:associativity-1] way_match; +wire miss; - - - - +wire [ (addr_set_width-1):0] tmem_read_address; +wire [ (addr_set_width-1):0] tmem_write_address; +wire [ ((addr_offset_width+addr_set_width)-1):0] dmem_read_address; +wire [ ((addr_offset_width+addr_set_width)-1):0] dmem_write_address; +wire [ ((addr_tag_width+1)-1):0] tmem_write_data; +reg [ 3:0] state; +wire flushing; +wire check; +wire refill; +reg [associativity-1:0] refill_way_select; +reg [ addr_offset_msb:addr_offset_lsb] refill_offset; +wire last_refill; +reg [ (addr_set_width-1):0] flush_set; +genvar i; - - - - - - - - - - - - - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +function integer clogb2; +input [31:0] value; +begin + for (clogb2 = 0; value > 0; clogb2 = clogb2 + 1) + value = value >> 1; +end +endfunction +function integer clogb2_v1; +input [31:0] value; +reg [31:0] i; +reg [31:0] temp; +begin + temp = 0; + i = 0; + for (i = 0; temp < value; i = i + 1) + temp = 1<<i; + clogb2_v1 = i-1; +end +endfunction - - - - - - - - - - - - - - - - - - - - - - - + + + + + generate + for (i = 0; i < associativity; i = i + 1) + begin : memories + + lm32_ram + #( - + .data_width (32), + .address_width ( (addr_offset_width+addr_set_width)) + +) + way_0_data_ram + ( + .read_clk (clk_i), + .write_clk (clk_i), + .reset (rst_i), + .read_address (dmem_read_address), + .enable_read (enable), + .write_address (dmem_write_address), + .enable_write ( 1'b1), + .write_enable (way_mem_we[i]), + .write_data (refill_data), + + .read_data (way_data[i]) + ); + + lm32_ram + #( + + .data_width ( (addr_tag_width+1)), + .address_width ( addr_set_width) - + ) + way_0_tag_ram + ( + + .read_clk (clk_i), + .write_clk (clk_i), + .reset (rst_i), + .read_address (tmem_read_address), + .enable_read (enable), + .write_address (tmem_write_address), + .enable_write ( 1'b1), + .write_enable (way_mem_we[i] | flushing), + .write_data (tmem_write_data), + + .read_data ({way_tag[i], way_valid[i]}) + ); - - - - - - - - - - - - - - - - - - - + end +endgenerate - - - - - - - - - - - - - - - - - - - - - +generate + for (i = 0; i < associativity; i = i + 1) + begin : match +assign way_match[i] = ({way_tag[i], way_valid[i]} == {address_f[ addr_tag_msb:addr_tag_lsb], 1'b1}); + end +endgenerate + + +generate + if (associativity == 1) + begin : inst_1 +assign inst = way_match[0] ? way_data[0] : 32'b0; + end + else if (associativity == 2) + begin : inst_2 +assign inst = way_match[0] ? way_data[0] : (way_match[1] ? way_data[1] : 32'b0); + end +endgenerate + + +generate + if (bytes_per_line > 4) +assign dmem_write_address = {refill_address[ addr_set_msb:addr_set_lsb], refill_offset}; + else +assign dmem_write_address = refill_address[ addr_set_msb:addr_set_lsb]; +endgenerate - - +assign dmem_read_address = address_a[ addr_set_msb:addr_offset_lsb]; + + +assign tmem_read_address = address_a[ addr_set_msb:addr_set_lsb]; +assign tmem_write_address = flushing + ? flush_set + : refill_address[ addr_set_msb:addr_set_lsb]; + + +generate + if (bytes_per_line > 4) +assign last_refill = refill_offset == {addr_offset_width{1'b1}}; + else +assign last_refill = 1'b1; +endgenerate + + +assign enable = (stall_a == 1'b0); + + +generate + if (associativity == 1) + begin : we_1 +assign way_mem_we[0] = (refill_ready == 1'b1); + end + else + begin : we_2 +assign way_mem_we[0] = (refill_ready == 1'b1) && (refill_way_select[0] == 1'b1); +assign way_mem_we[1] = (refill_ready == 1'b1) && (refill_way_select[1] == 1'b1); + end +endgenerate + + +assign tmem_write_data[ 0] = last_refill & !flushing; +assign tmem_write_data[ ((addr_tag_width+1)-1):1] = refill_address[ addr_tag_msb:addr_tag_lsb]; + + +assign flushing = |state[1:0]; +assign check = state[2]; +assign refill = state[3]; + +assign miss = (~(|way_match)) && (read_enable_f == 1'b1) && (stall_f == 1'b0) && !(valid_d && branch_predict_taken_d); +assign stall_request = (check == 1'b0); +assign refill_request = (refill == 1'b1); + + + + + + +generate + if (associativity >= 2) + begin : way_select +always @(posedge clk_i ) +begin + if (rst_i == 1'b1) + refill_way_select <= {{associativity-1{1'b0}}, 1'b1}; + else + begin + if (miss == 1'b1) + refill_way_select <= {refill_way_select[0], refill_way_select[1]}; + end +end + end +endgenerate + + +always @(posedge clk_i ) +begin + if (rst_i == 1'b1) + refilling <= 1'b0; + else + refilling <= refill; +end + + +always @(posedge clk_i ) +begin + if (rst_i == 1'b1) + begin + state <= 4'b0001; + flush_set <= { addr_set_width{1'b1}}; + refill_address <= { (clogb2(32'h7fffffff-32'h0)-2){1'bx}}; + restart_request <= 1'b0; + end + else + begin + case (state) + + 4'b0001: + begin + if (flush_set == { addr_set_width{1'b0}}) + state <= 4'b0100; + flush_set <= flush_set - 1'b1; + end + - - - - + 4'b0010: + begin + if (flush_set == { addr_set_width{1'b0}}) + + - + + + state <= 4'b0100; + + flush_set <= flush_set - 1'b1; + end - - - + 4'b0100: + begin + if (stall_a == 1'b0) + restart_request <= 1'b0; + if (iflush == 1'b1) + begin + refill_address <= address_f; + state <= 4'b0010; + end + else if (miss == 1'b1) + begin + refill_address <= address_f; + state <= 4'b1000; + end + end + + 4'b1000: + begin + if (refill_ready == 1'b1) + begin + if (last_refill == 1'b1) + begin + restart_request <= 1'b1; + state <= 4'b0100; + end + end + end - - + endcase + end +end - +generate + if (bytes_per_line > 4) + begin - +always @(posedge clk_i ) +begin + if (rst_i == 1'b1) + refill_offset <= {addr_offset_width{1'b0}}; + else + begin + case (state) + + + 4'b0100: + begin + if (iflush == 1'b1) + refill_offset <= {addr_offset_width{1'b0}}; + else if (miss == 1'b1) + refill_offset <= {addr_offset_width{1'b0}}; + end + + 4'b1000: + begin + if (refill_ready == 1'b1) + refill_offset <= refill_offset + 1'b1; + end + endcase + end +end + end +endgenerate + +endmodule + @@ -34756,135 +34948,160 @@ endmodule - - - - - - + + + + - - - - - - - - - - - - - - - - - - - + + + + + + + +module lm32_debug_medium_debug ( + clk_i, + rst_i, + pc_x, + load_x, + store_x, + load_store_address_x, + csr_write_enable_x, + csr_write_data, + csr_x, + + + jtag_csr_write_enable, + jtag_csr_write_data, + jtag_csr, - + + eret_q_x, + bret_q_x, + stall_x, + exception_x, + q_x, + + + - - - - + + + dc_ss, + + + dc_re, + bp_match, + wp_match + ); - - +parameter breakpoints = 0; +parameter watchpoints = 0; - - +input clk_i; +input rst_i; - - - - - - - +input [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] pc_x; +input load_x; +input store_x; +input [ (32-1):0] load_store_address_x; +input csr_write_enable_x; +input [ (32-1):0] csr_write_data; +input [ (5-1):0] csr_x; + + +input jtag_csr_write_enable; +input [ (32-1):0] jtag_csr_write_data; +input [ (5-1):0] jtag_csr; + + + +input eret_q_x; +input bret_q_x; +input stall_x; +input exception_x; +input q_x; + - - + - - - - - - - + +output dc_ss; +reg dc_ss; - - - - - - - - +output dc_re; +reg dc_re; +output bp_match; +wire bp_match; +output wp_match; +wire wp_match; - +genvar i; - - - +reg [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] bp_a[0:breakpoints-1]; +reg bp_e[0:breakpoints-1]; +wire [0:breakpoints-1]bp_match_n; - - - +reg [ 1:0] wpc_c[0:watchpoints-1]; +reg [ (32-1):0] wp[0:watchpoints-1]; +wire [0:watchpoints]wp_match_n; + +wire debug_csr_write_enable; +wire [ (32-1):0] debug_csr_write_data; +wire [ (5-1):0] debug_csr; + + - - - + +reg [ 2:0] state; - + - @@ -34892,48 +35109,15 @@ endmodule - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -34942,132 +35126,223 @@ endmodule - - - - - - - - - - - - - - - - - - + +function integer clogb2; +input [31:0] value; +begin + for (clogb2 = 0; value > 0; clogb2 = clogb2 + 1) + value = value >> 1; +end +endfunction +function integer clogb2_v1; +input [31:0] value; +reg [31:0] i; +reg [31:0] temp; +begin + temp = 0; + i = 0; + for (i = 0; temp < value; i = i + 1) + temp = 1<<i; + clogb2_v1 = i-1; +end +endfunction - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +generate + for (i = 0; i < breakpoints; i = i + 1) + begin : bp_comb +assign bp_match_n[i] = ((bp_a[i] == pc_x) && (bp_e[i] == 1'b1)); + end +endgenerate +generate + + if (breakpoints > 0) +assign bp_match = (|bp_match_n) || (state == 3'b011); + else +assign bp_match = state == 3'b011; + + - - - - - - - + + + +endgenerate - - + +generate + for (i = 0; i < watchpoints; i = i + 1) + begin : wp_comb +assign wp_match_n[i] = (wp[i] == load_store_address_x) && ((load_x & wpc_c[i][0]) | (store_x & wpc_c[i][1])); + end +endgenerate +generate + if (watchpoints > 0) +assign wp_match = |wp_match_n; + else +assign wp_match = 1'b0; +endgenerate - - - - - - - + + + +assign debug_csr_write_enable = (csr_write_enable_x == 1'b1) || (jtag_csr_write_enable == 1'b1); +assign debug_csr_write_data = jtag_csr_write_enable == 1'b1 ? jtag_csr_write_data : csr_write_data; +assign debug_csr = jtag_csr_write_enable == 1'b1 ? jtag_csr : csr_x; + + + + + + + + + + + + +generate + for (i = 0; i < breakpoints; i = i + 1) + begin : bp_seq +always @(posedge clk_i ) +begin + if (rst_i == 1'b1) + begin + bp_a[i] <= { (clogb2(32'h7fffffff-32'h0)-2){1'bx}}; + bp_e[i] <= 1'b0; + end + else + begin + if ((debug_csr_write_enable == 1'b1) && (debug_csr == 5'h10 + i)) + begin + bp_a[i] <= debug_csr_write_data[ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2]; + bp_e[i] <= debug_csr_write_data[0]; + end + end +end + end +endgenerate + + +generate + for (i = 0; i < watchpoints; i = i + 1) + begin : wp_seq +always @(posedge clk_i ) +begin + if (rst_i == 1'b1) + begin + wp[i] <= { 32{1'bx}}; + wpc_c[i] <= 2'b00; + end + else + begin + if (debug_csr_write_enable == 1'b1) + begin + if (debug_csr == 5'h8) + wpc_c[i] <= debug_csr_write_data[3+i*2:2+i*2]; + if (debug_csr == 5'h18 + i) + wp[i] <= debug_csr_write_data; + end + end +end + end +endgenerate + + +always @(posedge clk_i ) +begin + if (rst_i == 1'b1) + dc_re <= 1'b0; + else + begin + if ((debug_csr_write_enable == 1'b1) && (debug_csr == 5'h8)) + dc_re <= debug_csr_write_data[1]; + end +end + + + + +always @(posedge clk_i ) +begin + if (rst_i == 1'b1) + begin + state <= 3'b000; + dc_ss <= 1'b0; + end + else + begin + if ((debug_csr_write_enable == 1'b1) && (debug_csr == 5'h8)) + begin + dc_ss <= debug_csr_write_data[0]; + if (debug_csr_write_data[0] == 1'b0) + state <= 3'b000; + else + state <= 3'b001; + end + case (state) + 3'b001: + begin - - - - - - - - - + if ( ( (eret_q_x == 1'b1) + || (bret_q_x == 1'b1) + ) + && (stall_x == 1'b0) + ) + state <= 3'b010; + end + 3'b010: + begin - - - - - + if ((q_x == 1'b1) && (stall_x == 1'b0)) + state <= 3'b011; + end + 3'b011: + begin - + - - - - - - - - + + if ((exception_x == 1'b1) && (q_x == 1'b1) && (stall_x == 1'b0)) + begin + dc_ss <= 1'b0; + state <= 3'b100; + end + end + 3'b100: + begin - + - - - - - - + state <= 3'b000; + end + endcase + end +end + +endmodule + @@ -35440,7 +35715,7 @@ endmodule -module lm32_instruction_unit_medium ( +module lm32_instruction_unit_medium_debug ( clk_i, rst_i, @@ -35465,8 +35740,9 @@ module lm32_instruction_unit_medium ( branch_mispredict_taken_m, branch_target_m, - + iflush, + @@ -35490,11 +35766,12 @@ module lm32_instruction_unit_medium ( - - - - + jtag_read_enable, + jtag_write_enable, + jtag_write_data, + jtag_address, + @@ -35504,11 +35781,12 @@ module lm32_instruction_unit_medium ( pc_m, pc_w, - - - - + icache_stall_request, + icache_restart_request, + icache_refill_request, + icache_refilling, + @@ -35529,9 +35807,10 @@ module lm32_instruction_unit_medium ( - - + jtag_read_data, + jtag_access_complete, + @@ -35577,7 +35856,7 @@ input valid_d; input kill_f; input branch_predict_taken_d; -input [ ((32-2)+2-1):2] branch_predict_address_d; +input [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] branch_predict_address_d; @@ -35587,11 +35866,12 @@ input [ ((32-2)+2-1):2] branch_predict_address_d; input exception_m; input branch_taken_m; input branch_mispredict_taken_m; -input [ ((32-2)+2-1):2] branch_target_m; +input [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] branch_target_m; - +input iflush; + @@ -35617,38 +35897,40 @@ input i_rty_i; - - - - +input jtag_read_enable; +input jtag_write_enable; +input [ 7:0] jtag_write_data; +input [ (32-1):0] jtag_address; + -output [ ((32-2)+2-1):2] pc_f; -reg [ ((32-2)+2-1):2] pc_f; -output [ ((32-2)+2-1):2] pc_d; -reg [ ((32-2)+2-1):2] pc_d; -output [ ((32-2)+2-1):2] pc_x; -reg [ ((32-2)+2-1):2] pc_x; -output [ ((32-2)+2-1):2] pc_m; -reg [ ((32-2)+2-1):2] pc_m; -output [ ((32-2)+2-1):2] pc_w; -reg [ ((32-2)+2-1):2] pc_w; +output [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] pc_f; +reg [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] pc_f; +output [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] pc_d; +reg [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] pc_d; +output [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] pc_x; +reg [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] pc_x; +output [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] pc_m; +reg [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] pc_m; +output [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] pc_w; +reg [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] pc_w; - - - - - - - - +output icache_stall_request; +wire icache_stall_request; +output icache_restart_request; +wire icache_restart_request; +output icache_refill_request; +wire icache_refill_request; +output icache_refilling; +wire icache_refilling; + @@ -35661,11 +35943,11 @@ reg [ ((32-2)+2-1):2] pc_w; output [ (32-1):0] i_dat_o; - - -wire [ (32-1):0] i_dat_o; +reg [ (32-1):0] i_dat_o; + + output [ (32-1):0] i_adr_o; reg [ (32-1):0] i_adr_o; @@ -35673,21 +35955,21 @@ output i_cyc_o; reg i_cyc_o; output [ (4-1):0] i_sel_o; - - -wire [ (4-1):0] i_sel_o; +reg [ (4-1):0] i_sel_o; + + output i_stb_o; reg i_stb_o; output i_we_o; - - -wire i_we_o; +reg i_we_o; + + output [ (3-1):0] i_cti_o; reg [ (3-1):0] i_cti_o; @@ -35699,11 +35981,12 @@ wire [ (2-1):0] i_bte_o; - - - - +output [ 7:0] jtag_read_data; +reg [ 7:0] jtag_read_data; +output jtag_access_complete; +wire jtag_access_complete; + @@ -35724,31 +36007,30 @@ reg [ (32-1):0] instruction_d; -reg [ ((32-2)+2-1):2] pc_a; +reg [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] pc_a; - - - - - - - - - - - - - +reg [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] restart_address; + -reg [ (32-1):0] wb_data_f; +wire icache_read_enable_f; +wire [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] icache_refill_address; +reg icache_refill_ready; +reg [ (32-1):0] icache_refill_data; +wire [ (32-1):0] icache_data_f; +wire [ (3-1):0] first_cycle_type; +wire [ (3-1):0] next_cycle_type; +wire last_word; +wire [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] first_address; - + + + @@ -35768,8 +36050,9 @@ reg [ (32-1):0] wb_data_f; - +reg jtag_access; + @@ -35886,35 +36169,36 @@ endfunction - - - - - - - - - - - - - - - - - - - - + +lm32_icache_medium_debug #( + .associativity (associativity), + .sets (sets), + .bytes_per_line (bytes_per_line), + .base_address (base_address), + .limit (limit) + ) icache ( - - - - - - + .clk_i (clk_i), + .rst_i (rst_i), + .stall_a (stall_a), + .stall_f (stall_f), + .branch_predict_taken_d (branch_predict_taken_d), + .valid_d (valid_d), + .address_a (pc_a), + .address_f (pc_f), + .read_enable_f (icache_read_enable_f), + .refill_ready (icache_refill_ready), + .refill_data (icache_refill_data), + .iflush (iflush), - + .stall_request (icache_stall_request), + .restart_request (icache_restart_request), + .refill_request (icache_refill_request), + .refill_address (icache_refill_address), + .refilling (icache_refilling), + .inst (icache_data_f) + ); + @@ -35923,16 +36207,19 @@ endfunction - - - + +assign icache_read_enable_f = (valid_f == 1'b1) + && (kill_f == 1'b0) + + - + - - + + ; + @@ -35960,10 +36247,11 @@ begin pc_a = branch_predict_address_d; else - - - + if (icache_restart_request == 1'b1) + pc_a = restart_address; + else + pc_a = pc_f + 1'b1; end @@ -35976,25 +36264,25 @@ end - - - + + +assign instruction_f = icache_data_f; + - + + + -assign instruction_f = wb_data_f; - - @@ -36002,11 +36290,11 @@ assign instruction_f = wb_data_f; - -assign i_dat_o = 32'd0; -assign i_we_o = 1'b0; -assign i_sel_o = 4'b1111; + + + + assign i_bte_o = 2'b00; @@ -36015,31 +36303,32 @@ assign i_bte_o = 2'b00; - - - - - - - - - - - - - - - - - - - - - - - - - +generate + case (bytes_per_line) + 4: + begin +assign first_cycle_type = 3'b111; +assign next_cycle_type = 3'b111; +assign last_word = 1'b1; +assign first_address = icache_refill_address; + end + 8: + begin +assign first_cycle_type = 3'b010; +assign next_cycle_type = 3'b111; +assign last_word = i_adr_o[addr_offset_msb:addr_offset_lsb] == 1'b1; +assign first_address = {icache_refill_address[ (clogb2(32'h7fffffff-32'h0)-2)+2-1:addr_offset_msb+1], {addr_offset_width{1'b0}}}; + end + 16: + begin +assign first_cycle_type = 3'b010; +assign next_cycle_type = i_adr_o[addr_offset_msb] == 1'b1 ? 3'b111 : 3'b010; +assign last_word = i_adr_o[addr_offset_msb:addr_offset_lsb] == 2'b11; +assign first_address = {icache_refill_address[ (clogb2(32'h7fffffff-32'h0)-2)+2-1:addr_offset_msb+1], {addr_offset_width{1'b0}}}; + end + endcase +endgenerate + @@ -36052,10 +36341,10 @@ begin if (rst_i == 1'b1) begin pc_f <= ( 32'h00000000-4)/4; - pc_d <= { (32-2){1'b0}}; - pc_x <= { (32-2){1'b0}}; - pc_m <= { (32-2){1'b0}}; - pc_w <= { (32-2){1'b0}}; + pc_d <= { (clogb2(32'h7fffffff-32'h0)-2){1'b0}}; + pc_x <= { (clogb2(32'h7fffffff-32'h0)-2){1'b0}}; + pc_m <= { (clogb2(32'h7fffffff-32'h0)-2){1'b0}}; + pc_w <= { (clogb2(32'h7fffffff-32'h0)-2){1'b0}}; end else begin @@ -36073,13 +36362,14 @@ end - - - - - - +always @(posedge clk_i ) +begin + if (rst_i == 1'b1) + restart_address <= { (clogb2(32'h7fffffff-32'h0)-2){1'b0}}; + else + begin + @@ -36091,14 +36381,18 @@ end - - - - - + + + if (icache_refill_request == 1'b1) + restart_address <= icache_refill_address; + + + end +end + @@ -36117,23 +36411,152 @@ end - + +assign jtag_access_complete = (i_cyc_o == 1'b1) && ((i_ack_i == 1'b1) || (i_err_i == 1'b1)) && (jtag_access == 1'b1); +always @(*) +begin + case (jtag_address[1:0]) + 2'b00: jtag_read_data = i_dat_i[ 31:24]; + 2'b01: jtag_read_data = i_dat_i[ 23:16]; + 2'b10: jtag_read_data = i_dat_i[ 15:8]; + 2'b11: jtag_read_data = i_dat_i[ 7:0]; + endcase +end - - - - - - + + + + + +always @(posedge clk_i ) +begin + if (rst_i == 1'b1) + begin + i_cyc_o <= 1'b0; + i_stb_o <= 1'b0; + i_adr_o <= { 32{1'b0}}; + i_cti_o <= 3'b111; + i_lock_o <= 1'b0; + icache_refill_data <= { 32{1'b0}}; + icache_refill_ready <= 1'b0; + + + + + + + i_we_o <= 1'b0; + i_sel_o <= 4'b1111; + jtag_access <= 1'b0; + + + end + else + begin + icache_refill_ready <= 1'b0; + + if (i_cyc_o == 1'b1) + begin + + if ((i_ack_i == 1'b1) || (i_err_i == 1'b1)) + begin + + + if (jtag_access == 1'b1) + begin + i_cyc_o <= 1'b0; + i_stb_o <= 1'b0; + i_we_o <= 1'b0; + jtag_access <= 1'b0; + end + else + + + begin + if (last_word == 1'b1) + begin + + i_cyc_o <= 1'b0; + i_stb_o <= 1'b0; + i_lock_o <= 1'b0; + end + + i_adr_o[addr_offset_msb:addr_offset_lsb] <= i_adr_o[addr_offset_msb:addr_offset_lsb] + 1'b1; + i_cti_o <= next_cycle_type; + + icache_refill_ready <= 1'b1; + icache_refill_data <= i_dat_i; + end + end + + + + + + + + + end + else + begin + if ((icache_refill_request == 1'b1) && (icache_refill_ready == 1'b0)) + begin + + + + i_sel_o <= 4'b1111; + + i_adr_o <= {first_address, 2'b00}; + i_cyc_o <= 1'b1; + i_stb_o <= 1'b1; + i_cti_o <= first_cycle_type; + + + + end + else + begin + if ((jtag_read_enable == 1'b1) || (jtag_write_enable == 1'b1)) + begin + case (jtag_address[1:0]) + 2'b00: i_sel_o <= 4'b1000; + 2'b01: i_sel_o <= 4'b0100; + 2'b10: i_sel_o <= 4'b0010; + 2'b11: i_sel_o <= 4'b0001; + endcase + i_adr_o <= jtag_address; + i_dat_o <= {4{jtag_write_data}}; + i_cyc_o <= 1'b1; + i_stb_o <= 1'b1; + i_we_o <= jtag_write_enable; + i_cti_o <= 3'b111; + jtag_access <= 1'b1; + end + end + + + + + + + + + + + + end + end +end + @@ -36144,50 +36567,23 @@ end - - - - - - - - + - - - - - - - - - - - - - - - - - - - - - - - + + + @@ -36199,7 +36595,12 @@ end + + + + + @@ -36207,129 +36608,28 @@ end - - + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + - -always @(posedge clk_i ) -begin - if (rst_i == 1'b1) - begin - i_cyc_o <= 1'b0; - i_stb_o <= 1'b0; - i_adr_o <= { 32{1'b0}}; - i_cti_o <= 3'b111; - i_lock_o <= 1'b0; - wb_data_f <= { 32{1'b0}}; - - - - - end - else - begin - - if (i_cyc_o == 1'b1) - begin - - if((i_ack_i == 1'b1) || (i_err_i == 1'b1)) - begin - - i_cyc_o <= 1'b0; - i_stb_o <= 1'b0; - - wb_data_f <= i_dat_i; - end - - - - - - - - - end - else - begin - - if ( (stall_a == 1'b0) - - - - - ) - begin - - - - - - i_adr_o <= {pc_a, 2'b00}; - i_cyc_o <= 1'b1; - i_stb_o <= 1'b1; - - - - - end - else - begin - if ( (stall_a == 1'b0) - - - - - ) - begin - - - - - end - end - end - end -end - @@ -36710,443 +37010,523 @@ endmodule - - - + - - - - - - - - + + - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +module lm32_jtag_medium_debug ( - - - - - - + clk_i, + rst_i, + jtag_clk, + jtag_update, + jtag_reg_q, + jtag_reg_addr_q, + + + csr, + csr_write_enable, + csr_write_data, + stall_x, - - - - + + + jtag_read_data, + jtag_access_complete, - - + + + exception_q_w, - + + + jtx_csr_read_data, + jrx_csr_read_data, - - + + + jtag_csr_write_enable, + jtag_csr_write_data, + jtag_csr, + jtag_read_enable, + jtag_write_enable, + jtag_write_data, + jtag_address, - - - - - - - + + + jtag_break, + jtag_reset, - - - - - + jtag_reg_d, + jtag_reg_addr_d + ); - - +input clk_i; +input rst_i; - - - - +input jtag_clk; +input jtag_update; +input [ 7:0] jtag_reg_q; +input [2:0] jtag_reg_addr_q; + + +input [ (5-1):0] csr; +input csr_write_enable; +input [ (32-1):0] csr_write_data; +input stall_x; - - - - + + +input [ 7:0] jtag_read_data; +input jtag_access_complete; - - + + +input exception_q_w; - - - - - - + +output [ (32-1):0] jtx_csr_read_data; +wire [ (32-1):0] jtx_csr_read_data; +output [ (32-1):0] jrx_csr_read_data; +wire [ (32-1):0] jrx_csr_read_data; - - - - - - - - - - - - - - + + +output jtag_csr_write_enable; +reg jtag_csr_write_enable; +output [ (32-1):0] jtag_csr_write_data; +wire [ (32-1):0] jtag_csr_write_data; +output [ (5-1):0] jtag_csr; +wire [ (5-1):0] jtag_csr; +output jtag_read_enable; +reg jtag_read_enable; +output jtag_write_enable; +reg jtag_write_enable; +output [ 7:0] jtag_write_data; +wire [ 7:0] jtag_write_data; +output [ (32-1):0] jtag_address; +wire [ (32-1):0] jtag_address; - - - - - - - + +output jtag_break; +reg jtag_break; +output jtag_reset; +reg jtag_reset; + + +output [ 7:0] jtag_reg_d; +reg [ 7:0] jtag_reg_d; +output [2:0] jtag_reg_addr_d; +wire [2:0] jtag_reg_addr_d; - - - - +reg rx_update; +reg rx_update_r; +reg rx_update_r_r; +reg rx_update_r_r_r; - +wire [ 7:0] rx_byte; +wire [2:0] rx_addr; + + +reg [ 7:0] uart_tx_byte; +reg uart_tx_valid; +reg [ 7:0] uart_rx_byte; +reg uart_rx_valid; + - - - - - +reg [ 3:0] command; + - +reg [ 7:0] jtag_byte_0; +reg [ 7:0] jtag_byte_1; +reg [ 7:0] jtag_byte_2; +reg [ 7:0] jtag_byte_3; +reg [ 7:0] jtag_byte_4; +reg processing; - - - - - - - +reg [ 3:0] state; + + +assign jtag_csr_write_data = {jtag_byte_0, jtag_byte_1, jtag_byte_2, jtag_byte_3}; +assign jtag_csr = jtag_byte_4[ (5-1):0]; +assign jtag_address = {jtag_byte_0, jtag_byte_1, jtag_byte_2, jtag_byte_3}; +assign jtag_write_data = jtag_byte_4; - - - - - - - + + +assign jtag_reg_addr_d[1:0] = {uart_rx_valid, uart_tx_valid}; + + + + +assign jtag_reg_addr_d[2] = processing; - - - - + + +assign jtx_csr_read_data = {{ 32-9{1'b0}}, uart_tx_valid, 8'h00}; +assign jrx_csr_read_data = {{ 32-9{1'b0}}, uart_rx_valid, uart_rx_byte}; + - - +assign rx_byte = jtag_reg_q; +assign rx_addr = jtag_reg_addr_q; - +always @(posedge clk_i ) +begin + if (rst_i == 1'b1) + begin + rx_update <= 1'b0; + rx_update_r <= 1'b0; + rx_update_r_r <= 1'b0; + rx_update_r_r_r <= 1'b0; + end + else + begin + rx_update <= jtag_update; + rx_update_r <= rx_update; + rx_update_r_r <= rx_update_r; + rx_update_r_r_r <= rx_update_r_r; + end +end - - - - - - - - - - - - - - +always @(posedge clk_i ) +begin + if (rst_i == 1'b1) + begin + state <= 4'h0; + command <= 4'b0000; + jtag_reg_d <= 8'h00; + + processing <= 1'b0; + jtag_csr_write_enable <= 1'b0; + jtag_read_enable <= 1'b0; + jtag_write_enable <= 1'b0; + - + - - - - - + jtag_break <= 1'b0; + jtag_reset <= 1'b0; - - - - + + + uart_tx_byte <= 8'h00; + uart_tx_valid <= 1'b0; + uart_rx_byte <= 8'h00; + uart_rx_valid <= 1'b0; - - - - - - - - - - - - - - - - - + end + else + begin + + + if ((csr_write_enable == 1'b1) && (stall_x == 1'b0)) + begin + case (csr) + 5'he: + begin - - - - - + uart_tx_byte <= csr_write_data[ 7:0]; + uart_tx_valid <= 1'b1; + end + 5'hf: + begin - - - - - + uart_rx_valid <= 1'b0; + end + endcase + end - - - - - - - - + + - - - - - - - - - + if (exception_q_w == 1'b1) + begin + jtag_break <= 1'b0; + jtag_reset <= 1'b0; + end - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + case (state) + 4'h0: + begin + + if ((~rx_update_r_r_r & rx_update_r_r) == 1'b1) + begin + command <= rx_byte[7:4]; + case (rx_addr) + - + 3'b000: + begin + case (rx_byte[7:4]) + + + 4'b0001: + state <= 4'h1; + 4'b0011: + begin + {jtag_byte_2, jtag_byte_3} <= {jtag_byte_2, jtag_byte_3} + 1'b1; + state <= 4'h6; + end + 4'b0010: + state <= 4'h1; + 4'b0100: + begin + {jtag_byte_2, jtag_byte_3} <= {jtag_byte_2, jtag_byte_3} + 1'b1; + state <= 5; + end + 4'b0101: + state <= 4'h1; + - - + 4'b0110: + begin + + + uart_rx_valid <= 1'b0; + uart_tx_valid <= 1'b0; + - - - - - - - - - - - + jtag_break <= 1'b1; + end + 4'b0111: + begin + + + uart_rx_valid <= 1'b0; + uart_tx_valid <= 1'b0; + - - - - - + jtag_reset <= 1'b1; + end + endcase + end - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + 3'b001: + begin + uart_rx_byte <= rx_byte; + uart_rx_valid <= 1'b1; + end + 3'b010: + begin + jtag_reg_d <= uart_tx_byte; + uart_tx_valid <= 1'b0; + end + + default: + ; + endcase + end + end + 4'h1: + begin + if ((~rx_update_r_r_r & rx_update_r_r) == 1'b1) + begin + jtag_byte_0 <= rx_byte; + state <= 4'h2; + end + end + 4'h2: + begin + if ((~rx_update_r_r_r & rx_update_r_r) == 1'b1) + begin + jtag_byte_1 <= rx_byte; + state <= 4'h3; + end + end + 4'h3: + begin + if ((~rx_update_r_r_r & rx_update_r_r) == 1'b1) + begin + jtag_byte_2 <= rx_byte; + state <= 4'h4; + end + end + 4'h4: + begin + if ((~rx_update_r_r_r & rx_update_r_r) == 1'b1) + begin + jtag_byte_3 <= rx_byte; + if (command == 4'b0001) + state <= 4'h6; + else + state <= 4'h5; + end + end + 4'h5: + begin + if ((~rx_update_r_r_r & rx_update_r_r) == 1'b1) + begin + jtag_byte_4 <= rx_byte; + state <= 4'h6; + end + end + 4'h6: + begin + case (command) + 4'b0001, + 4'b0011: + begin + jtag_read_enable <= 1'b1; + processing <= 1'b1; + state <= 4'h7; + end + 4'b0010, + 4'b0100: + begin + jtag_write_enable <= 1'b1; + processing <= 1'b1; + state <= 4'h7; + end + 4'b0101: + begin + jtag_csr_write_enable <= 1'b1; + processing <= 1'b1; + state <= 4'h8; + end + endcase + end + 4'h7: + begin + if (jtag_access_complete == 1'b1) + begin + jtag_read_enable <= 1'b0; + jtag_reg_d <= jtag_read_data; + jtag_write_enable <= 1'b0; + processing <= 1'b0; + state <= 4'h0; + end + end + 4'h8: + begin + jtag_csr_write_enable <= 1'b0; + processing <= 1'b0; + state <= 4'h0; + end + + endcase + end +end + +endmodule + @@ -37501,7 +37881,7 @@ endmodule -module lm32_interrupt_medium ( +module lm32_interrupt_medium_debug ( clk_i, rst_i, @@ -37510,17 +37890,18 @@ module lm32_interrupt_medium ( stall_x, - - - - exception, + non_debug_exception, + debug_exception, + + eret_q_x, - + bret_q_x, + csr, csr_write_data, @@ -37549,20 +37930,21 @@ input [interrupts-1:0] interrupt; input stall_x; - - - -input exception; +input non_debug_exception; +input debug_exception; + + input eret_q_x; - +input bret_q_x; + -input [ (3-1):0] csr; +input [ (5-1):0] csr; input [ (32-1):0] csr_write_data; input csr_write_enable; @@ -37589,8 +37971,9 @@ wire [interrupts-1:0] interrupt_n_exception; reg ie; reg eie; - +reg bie; + reg [interrupts-1:0] ip; reg [interrupts-1:0] im; @@ -37610,11 +37993,11 @@ assign asserted = ip | interrupt; assign ie_csr_read_data = {{ 32-3{1'b0}}, - - - 1'b0, + bie, + + eie, ie @@ -37628,19 +38011,19 @@ generate always @(*) begin case (csr) - 3'h0: csr_read_data = {{ 32-3{1'b0}}, + 5'h0: csr_read_data = {{ 32-3{1'b0}}, - - - 1'b0, + bie, + + eie, ie }; - 3'h2: csr_read_data = ip; - 3'h1: csr_read_data = im; + 5'h2: csr_read_data = ip; + 5'h1: csr_read_data = im; default: csr_read_data = { 32{1'bx}}; endcase end @@ -37651,18 +38034,18 @@ end always @(*) begin case (csr) - 3'h0: csr_read_data = {{ 32-3{1'b0}}, + 5'h0: csr_read_data = {{ 32-3{1'b0}}, - - - 1'b0, + bie, + + eie, ie }; - 3'h2: csr_read_data = ip; + 5'h2: csr_read_data = ip; default: csr_read_data = { 32{1'bx}}; endcase end @@ -37691,8 +38074,9 @@ always @(posedge clk_i ) ie <= 1'b0; eie <= 1'b0; - + bie <= 1'b0; + im <= {interrupts{1'b0}}; ip <= {interrupts{1'b0}}; @@ -37704,13 +38088,21 @@ always @(posedge clk_i ) ip <= asserted; - - + + if (non_debug_exception == 1'b1) + begin - - - + eie <= ie; + ie <= 1'b0; + end + else if (debug_exception == 1'b1) + begin + bie <= ie; + ie <= 1'b0; + end + + @@ -37718,14 +38110,6 @@ always @(posedge clk_i ) - if (exception == 1'b1) - begin - - eie <= ie; - ie <= 1'b0; - end - - else if (stall_x == 1'b0) begin @@ -37743,26 +38127,28 @@ always @(posedge clk_i ) - - - + else if (bret_q_x == 1'b1) + + ie <= bie; + else if (csr_write_enable == 1'b1) begin - if (csr == 3'h0) + if (csr == 5'h0) begin ie <= csr_write_data[0]; eie <= csr_write_data[1]; - + bie <= csr_write_data[2]; + end - if (csr == 3'h1) + if (csr == 5'h1) im <= csr_write_data[interrupts-1:0]; - if (csr == 3'h2) + if (csr == 5'h2) ip <= asserted & ~csr_write_data[interrupts-1:0]; end end @@ -37779,8 +38165,9 @@ always @(posedge clk_i ) ie <= 1'b0; eie <= 1'b0; - + bie <= 1'b0; + ip <= {interrupts{1'b0}}; eie_delay <= 0; @@ -37790,13 +38177,21 @@ always @(posedge clk_i ) ip <= asserted; - - + + if (non_debug_exception == 1'b1) + begin - - - + eie <= ie; + ie <= 1'b0; + end + else if (debug_exception == 1'b1) + begin + bie <= ie; + ie <= 1'b0; + end + + @@ -37804,14 +38199,6 @@ always @(posedge clk_i ) - if (exception == 1'b1) - begin - - eie <= ie; - ie <= 1'b0; - end - - else if (stall_x == 1'b0) begin @@ -37827,24 +38214,26 @@ always @(posedge clk_i ) end - - - + else if (bret_q_x == 1'b1) + + ie <= bie; + else if (csr_write_enable == 1'b1) begin - if (csr == 3'h0) + if (csr == 5'h0) begin ie <= csr_write_data[0]; eie <= csr_write_data[1]; - + bie <= csr_write_data[2]; + end - if (csr == 3'h2) + if (csr == 5'h2) ip <= asserted & ~csr_write_data[interrupts-1:0]; end end @@ -38428,7 +38817,7 @@ endmodule -module lm32_top_medium_debug ( +module lm32_top_medium_icache_debug ( clk_i, rst_i, @@ -38672,7 +39061,7 @@ endfunction -lm32_cpu_medium_debug cpu ( +lm32_cpu_medium_icache_debug cpu ( .clk_i (clk_i), @@ -39152,7 +39541,7 @@ endmodule -module lm32_mc_arithmetic_medium_debug ( +module lm32_mc_arithmetic_medium_icache_debug ( clk_i, rst_i, @@ -39808,7 +40197,7 @@ endmodule -module lm32_cpu_medium_debug ( +module lm32_cpu_medium_icache_debug ( clk_i, @@ -40646,7 +41035,7 @@ endfunction -lm32_instruction_unit_medium_debug #( +lm32_instruction_unit_medium_icache_debug #( .associativity (icache_associativity), .sets (icache_sets), .bytes_per_line (icache_bytes_per_line), @@ -40762,7 +41151,7 @@ lm32_instruction_unit_medium_debug #( ); -lm32_decoder_medium_debug decoder ( +lm32_decoder_medium_icache_debug decoder ( .instruction (instruction_d), @@ -40860,7 +41249,7 @@ lm32_decoder_medium_debug decoder ( ); -lm32_load_store_unit_medium_debug #( +lm32_load_store_unit_medium_icache_debug #( .associativity (dcache_associativity), .sets (dcache_sets), .bytes_per_line (dcache_bytes_per_line), @@ -41026,7 +41415,7 @@ lm32_multiplier multiplier ( -lm32_interrupt_medium_debug interrupt_unit ( +lm32_interrupt_medium_icache_debug interrupt_unit ( .clk_i (clk_i), .rst_i (rst_i), @@ -41062,7 +41451,7 @@ lm32_interrupt_medium_debug interrupt_unit ( -lm32_jtag_medium_debug jtag ( +lm32_jtag_medium_icache_debug jtag ( .clk_i (clk_i), .rst_i (rst_i), @@ -41126,7 +41515,7 @@ lm32_jtag_medium_debug jtag ( -lm32_debug_medium_debug #( +lm32_debug_medium_icache_debug #( .breakpoints (breakpoints), .watchpoints (watchpoints) ) hw_debug ( @@ -43297,7 +43686,7 @@ endmodule -module lm32_load_store_unit_medium_debug ( +module lm32_load_store_unit_medium_icache_debug ( clk_i, rst_i, @@ -44609,7 +44998,7 @@ endmodule -module lm32_decoder_medium_debug ( +module lm32_decoder_medium_icache_debug ( instruction, @@ -45639,7 +46028,7 @@ endmodule -module lm32_icache_medium_debug ( +module lm32_icache_medium_icache_debug ( clk_i, rst_i, @@ -47290,7 +47679,7 @@ endmodule -module lm32_debug_medium_debug ( +module lm32_debug_medium_icache_debug ( clk_i, rst_i, @@ -48039,7 +48428,7 @@ endmodule -module lm32_instruction_unit_medium_debug ( +module lm32_instruction_unit_medium_icache_debug ( clk_i, rst_i, @@ -48494,7 +48883,7 @@ endfunction -lm32_icache_medium_debug #( +lm32_icache_medium_icache_debug #( .associativity (associativity), .sets (sets), .bytes_per_line (bytes_per_line), @@ -49386,7 +49775,7 @@ endmodule -module lm32_jtag_medium_debug ( +module lm32_jtag_medium_icache_debug ( clk_i, rst_i, @@ -50205,7 +50594,7 @@ endmodule -module lm32_interrupt_medium_debug ( +module lm32_interrupt_medium_icache_debug ( clk_i, rst_i, @@ -63033,18 +63422,6 @@ endmodule - - - - - - - - - - - - @@ -63070,12 +63447,13 @@ endmodule - + + + + - - - + @@ -63175,16 +63553,18 @@ endmodule + + - - - + + + @@ -63213,25 +63593,24 @@ endmodule - - - + + - - - + + + @@ -63332,47 +63711,27 @@ endmodule - - - - - - - - - - - - - - - - - + + - - + - + - - - - @@ -63381,8 +63740,6 @@ endmodule - - @@ -63390,19 +63747,28 @@ endmodule + + - + + - + + + + + + + + - @@ -63463,14 +63829,14 @@ endmodule + - - - + + @@ -63560,7 +63926,7 @@ endmodule -module lm32_top_medium_icache_debug ( +module lm32_top_medium ( clk_i, rst_i, @@ -63717,18 +64083,17 @@ wire [ (2-1):0] D_BTE_O; - -wire [ 7:0] jtag_reg_d; -wire [ 7:0] jtag_reg_q; -wire jtag_update; -wire [2:0] jtag_reg_addr_d; -wire [2:0] jtag_reg_addr_q; -wire jtck; -wire jrstn; + + + + + + + @@ -63804,7 +64169,7 @@ endfunction -lm32_cpu_medium_icache_debug cpu ( +lm32_cpu_medium cpu ( .clk_i (clk_i), @@ -63825,13 +64190,12 @@ lm32_cpu_medium_icache_debug cpu ( - - .jtag_clk (jtck), - .jtag_update (jtag_update), - .jtag_reg_q (jtag_reg_q), - .jtag_reg_addr_q (jtag_reg_addr_q), - + + + + + @@ -63860,10 +64224,9 @@ lm32_cpu_medium_icache_debug cpu ( + + - .jtag_reg_d (jtag_reg_d), - .jtag_reg_addr_d (jtag_reg_addr_d), - @@ -63898,21 +64261,20 @@ lm32_cpu_medium_icache_debug cpu ( .D_BTE_O (D_BTE_O) ); - - + -jtag_cores jtag_cores ( + - .reg_d (jtag_reg_d), - .reg_addr_d (jtag_reg_addr_d), + + - .reg_update (jtag_update), - .reg_q (jtag_reg_q), - .reg_addr_q (jtag_reg_addr_q), - .jtck (jtck), - .jrstn (jrstn) - ); - + + + + + + + endmodule @@ -64284,7 +64646,7 @@ endmodule -module lm32_mc_arithmetic_medium_icache_debug ( +module lm32_mc_arithmetic_medium ( clk_i, rst_i, @@ -64940,7 +65302,7 @@ endmodule -module lm32_cpu_medium_icache_debug ( +module lm32_cpu_medium ( clk_i, @@ -64961,13 +65323,12 @@ module lm32_cpu_medium_icache_debug ( - - jtag_clk, - jtag_update, - jtag_reg_q, - jtag_reg_addr_q, - + + + + + @@ -64996,10 +65357,9 @@ module lm32_cpu_medium_icache_debug ( + + - jtag_reg_d, - jtag_reg_addr_d, - @@ -65040,25 +65400,24 @@ module lm32_cpu_medium_icache_debug ( parameter eba_reset = 32'h00000000; + -parameter deba_reset = 32'h10000000; - + + + + + -parameter icache_associativity = 1; -parameter icache_sets = 256; -parameter icache_bytes_per_line = 16; -parameter icache_base_address = 32'h0; -parameter icache_limit = 32'h7fffffff; - - - - - - +parameter icache_associativity = 1; +parameter icache_sets = 512; +parameter icache_bytes_per_line = 16; +parameter icache_base_address = 0; +parameter icache_limit = 0; + @@ -65078,11 +65437,11 @@ parameter dcache_limit = 0; + -parameter watchpoints = 32'h4; - - +parameter watchpoints = 0; + @@ -65124,12 +65483,11 @@ input [ (32-1):0] interrupt; + + + + -input jtag_clk; -input jtag_update; -input [ 7:0] jtag_reg_q; -input [2:0] jtag_reg_addr_q; - @@ -65169,12 +65527,11 @@ input D_RTY_I; + + + + -output [ 7:0] jtag_reg_d; -wire [ 7:0] jtag_reg_d; -output [2:0] jtag_reg_addr_d; -wire [2:0] jtag_reg_addr_d; - @@ -65238,9 +65595,8 @@ wire [ (2-1):0] D_BTE_O; + -reg valid_a; - reg valid_f; reg valid_d; @@ -65263,8 +65619,8 @@ reg [ 1:0] size_x; wire branch_d; wire branch_predict_d; wire branch_predict_taken_d; -wire [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] branch_predict_address_d; -wire [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] branch_target_d; +wire [ ((32-2)+2-1):2] branch_predict_address_d; +wire [ ((32-2)+2-1):2] branch_target_d; wire bi_unconditional; wire bi_conditional; reg branch_x; @@ -65276,9 +65632,9 @@ reg branch_predict_taken_m; wire branch_mispredict_taken_m; wire branch_flushX_m; wire branch_reg_d; -wire [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] branch_offset_d; -reg [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] branch_target_x; -reg [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] branch_target_m; +wire [ ((32-2)+2-1):2] branch_offset_d; +reg [ ((32-2)+2-1):2] branch_target_x; +reg [ ((32-2)+2-1):2] branch_target_m; wire [ 0:0] d_result_sel_0_d; wire [ 1:0] d_result_sel_1_d; @@ -65353,15 +65709,14 @@ wire [ (5-1):0] write_idx_d; reg [ (5-1):0] write_idx_x; reg [ (5-1):0] write_idx_m; reg [ (5-1):0] write_idx_w; -wire [ (5-1):0] csr_d; -reg [ (5-1):0] csr_x; +wire [ (3-1):0] csr_d; +reg [ (3-1):0] csr_x; wire [ (3-1):0] condition_d; reg [ (3-1):0] condition_x; + + -wire break_d; -reg break_x; - wire scall_d; reg scall_x; @@ -65374,16 +65729,14 @@ reg eret_m; - -wire bret_d; -reg bret_x; -wire bret_q_x; -reg bret_m; - + + + + + - wire csr_write_enable_d; reg csr_write_enable_x; @@ -65535,11 +65888,11 @@ wire [ (32-1):0] cfg2; reg [ (32-1):0] csr_read_data_x; -wire [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] pc_f; -wire [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] pc_d; -wire [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] pc_x; -wire [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] pc_m; -wire [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] pc_w; +wire [ ((32-2)+2-1):2] pc_f; +wire [ ((32-2)+2-1):2] pc_d; +wire [ ((32-2)+2-1):2] pc_x; +wire [ ((32-2)+2-1):2] pc_m; +wire [ ((32-2)+2-1):2] pc_w; @@ -65553,13 +65906,12 @@ wire [ (32-1):0] instruction_f; wire [ (32-1):0] instruction_d; + + + + + -wire iflush; -wire icache_stall_request; -wire icache_restart_request; -wire icache_refill_request; -wire icache_refilling; - @@ -65585,32 +65937,25 @@ wire stall_wb_load; - - - -wire [ (32-1):0] jtx_csr_read_data; -wire [ (32-1):0] jrx_csr_read_data; + + + + + + + - -wire jtag_csr_write_enable; -wire [ (32-1):0] jtag_csr_write_data; -wire [ (5-1):0] jtag_csr; -wire jtag_read_enable; -wire [ 7:0] jtag_read_data; -wire jtag_write_enable; -wire [ 7:0] jtag_write_data; -wire [ (32-1):0] jtag_address; -wire jtag_access_complete; - - -wire jtag_break; + + + + @@ -65640,11 +65985,10 @@ wire kill_x; wire kill_m; wire kill_w; -reg [ (clogb2(32'h7fffffff-32'h0)-2)+2-1:8] eba; +reg [ (32-2)+2-1:8] eba; + -reg [ (clogb2(32'h7fffffff-32'h0)-2)+2-1:8] deba; - reg [ (3-1):0] eid_x; @@ -65654,39 +65998,34 @@ reg [ (3-1):0] eid_x; - - - -wire dc_ss; + -wire dc_re; -wire exception_x; -reg exception_m; -wire debug_exception_x; -reg debug_exception_m; -reg debug_exception_w; -wire debug_exception_q_w; -wire non_debug_exception_x; -reg non_debug_exception_m; -reg non_debug_exception_w; -wire non_debug_exception_q_w; - + + + + + + + +wire exception_x; +reg exception_m; +reg exception_w; +wire exception_q_w; + - - -wire reset_exception; + + - @@ -65694,10 +66033,9 @@ wire interrupt_exception; + + -wire breakpoint_exception; -wire watchpoint_exception; - @@ -65778,7 +66116,7 @@ endfunction -lm32_instruction_unit_medium_icache_debug #( +lm32_instruction_unit_medium #( .associativity (icache_associativity), .sets (icache_sets), .bytes_per_line (icache_bytes_per_line), @@ -65809,9 +66147,8 @@ lm32_instruction_unit_medium_icache_debug #( .branch_mispredict_taken_m (branch_mispredict_taken_m), .branch_target_m (branch_target_m), + - .iflush (iflush), - @@ -65835,12 +66172,11 @@ lm32_instruction_unit_medium_icache_debug #( + + + + - .jtag_read_enable (jtag_read_enable), - .jtag_write_enable (jtag_write_enable), - .jtag_write_data (jtag_write_data), - .jtag_address (jtag_address), - @@ -65850,12 +66186,11 @@ lm32_instruction_unit_medium_icache_debug #( .pc_m (pc_m), .pc_w (pc_w), + + + + - .icache_stall_request (icache_stall_request), - .icache_restart_request (icache_restart_request), - .icache_refill_request (icache_refill_request), - .icache_refilling (icache_refilling), - @@ -65876,10 +66211,9 @@ lm32_instruction_unit_medium_icache_debug #( + + - .jtag_read_data (jtag_read_data), - .jtag_access_complete (jtag_access_complete), - @@ -65894,7 +66228,7 @@ lm32_instruction_unit_medium_icache_debug #( ); -lm32_decoder_medium_icache_debug decoder ( +lm32_decoder_medium decoder ( .instruction (instruction_d), @@ -65973,16 +66307,14 @@ lm32_decoder_medium_icache_debug decoder ( .branch_reg (branch_reg_d), .condition (condition_d), + - .break_opcode (break_d), - .scall (scall_d), .eret (eret_d), + - .bret (bret_d), - @@ -65992,7 +66324,7 @@ lm32_decoder_medium_icache_debug decoder ( ); -lm32_load_store_unit_medium_icache_debug #( +lm32_load_store_unit_medium #( .associativity (dcache_associativity), .sets (dcache_sets), .bytes_per_line (dcache_bytes_per_line), @@ -66158,7 +66490,7 @@ lm32_multiplier multiplier ( -lm32_interrupt_medium_icache_debug interrupt_unit ( +lm32_interrupt_medium interrupt_unit ( .clk_i (clk_i), .rst_i (rst_i), @@ -66167,18 +66499,17 @@ lm32_interrupt_medium_icache_debug interrupt_unit ( .stall_x (stall_x), + + - .non_debug_exception (non_debug_exception_q_w), - .debug_exception (debug_exception_q_w), - - + .exception (exception_q_w), + .eret_q_x (eret_q_x), + - .bret_q_x (bret_q_x), - .csr (csr_x), .csr_write_data (operand_1_x), @@ -66193,116 +66524,95 @@ lm32_interrupt_medium_icache_debug interrupt_unit ( - -lm32_jtag_medium_icache_debug jtag ( + - .clk_i (clk_i), - .rst_i (rst_i), + + - .jtag_clk (jtag_clk), - .jtag_update (jtag_update), - .jtag_reg_q (jtag_reg_q), - .jtag_reg_addr_q (jtag_reg_addr_q), + + + + - - - .csr (csr_x), - .csr_write_data (operand_1_x), - .csr_write_enable (csr_write_enable_q_x), - .stall_x (stall_x), + + + + - - - .jtag_read_data (jtag_read_data), - .jtag_access_complete (jtag_access_complete), + + - - - .exception_q_w (debug_exception_q_w || non_debug_exception_q_w), + - - - .jtx_csr_read_data (jtx_csr_read_data), - .jrx_csr_read_data (jrx_csr_read_data), + + - - - .jtag_csr_write_enable (jtag_csr_write_enable), - .jtag_csr_write_data (jtag_csr_write_data), - .jtag_csr (jtag_csr), - .jtag_read_enable (jtag_read_enable), - .jtag_write_enable (jtag_write_enable), - .jtag_write_data (jtag_write_data), - .jtag_address (jtag_address), + + + + + + + - - - .jtag_break (jtag_break), - .jtag_reset (reset_exception), + + - .jtag_reg_d (jtag_reg_d), - .jtag_reg_addr_d (jtag_reg_addr_d) - ); - - + + + - -lm32_debug_medium_icache_debug #( - .breakpoints (breakpoints), - .watchpoints (watchpoints) - ) hw_debug ( - - .clk_i (clk_i), - .rst_i (rst_i), - .pc_x (pc_x), - .load_x (load_x), - .store_x (store_x), - .load_store_address_x (adder_result_x), - .csr_write_enable_x (csr_write_enable_q_x), - .csr_write_data (operand_1_x), - .csr_x (csr_x), - .jtag_csr_write_enable (jtag_csr_write_enable), - .jtag_csr_write_data (jtag_csr_write_data), - .jtag_csr (jtag_csr), + + + + + + + + + + + + + + + + + - - - .eret_q_x (eret_q_x), - .bret_q_x (bret_q_x), - .stall_x (stall_x), - .exception_x (exception_x), - .q_x (q_x), - + + + + + + + + + + + + - - .dc_ss (dc_ss), - - - .dc_re (dc_re), - .bp_match (bp_match), - .wp_match (wp_match) - ); - @@ -66747,9 +67057,8 @@ assign kill_f = ( (valid_d == 1'b1) + - || (icache_refill_request == 1'b1) - @@ -66762,9 +67071,8 @@ assign kill_d = (branch_taken_m == 1'b1) + - || (icache_refill_request == 1'b1) - @@ -66793,25 +67101,21 @@ assign kill_w = 1'b0 - -assign breakpoint_exception = ( ( (break_x == 1'b1) - || (bp_match == 1'b1) - ) - && (valid_x == 1'b1) - ) - - - || (jtag_break == 1'b1) + + + + + + + + - ; - + -assign watchpoint_exception = wp_match == 1'b1; - @@ -66835,17 +67139,38 @@ assign system_call_exception = ( (scall_x == 1'b1) ); + + + -assign debug_exception_x = (breakpoint_exception == 1'b1) - || (watchpoint_exception == 1'b1) - ; + + + -assign non_debug_exception_x = (system_call_exception == 1'b1) - + + + - || (reset_exception == 1'b1) + + + + + + + + + + + + + + + + + +assign exception_x = (system_call_exception == 1'b1) @@ -66859,9 +67184,8 @@ assign non_debug_exception_x = (system_call_exception == 1'b1) || ( (interrupt_exception == 1'b1) + - && (dc_ss == 1'b0) - @@ -66872,54 +67196,27 @@ assign non_debug_exception_x = (system_call_exception == 1'b1) ; - -assign exception_x = (debug_exception_x == 1'b1) || (non_debug_exception_x == 1'b1); - - - - - - - - - - - - - - - - - - - - - always @(*) begin - - - - if (reset_exception == 1'b1) - eid_x = 3'h0; - else + + + - + + + + - if (breakpoint_exception == 1'b1) - eid_x = 3'd1; - else - @@ -66931,11 +67228,10 @@ begin + + + - if (watchpoint_exception == 1'b1) - eid_x = 3'd3; - else - @@ -66947,9 +67243,8 @@ begin if ( (interrupt_exception == 1'b1) + - && (dc_ss == 1'b0) - ) eid_x = 3'h6; @@ -66985,19 +67280,18 @@ assign stall_d = (stall_x == 1'b1) && (kill_d == 1'b0) ) + + + + + + + + + + + - || ( ( (break_d == 1'b1) - || (bret_d == 1'b1) - ) - && ( (load_q_x == 1'b1) - || (store_q_x == 1'b1) - || (load_q_m == 1'b1) - || (store_q_m == 1'b1) - || (D_CYC_O == 1'b1) - ) - && (kill_d == 1'b0) - ) - || ( (csr_write_enable_d == 1'b1) && (load_q_x == 1'b1) @@ -67059,14 +67353,16 @@ assign stall_m = (stall_wb_load == 1'b1) + + - || (icache_stall_request == 1'b1) - || ((I_CYC_O == 1'b1) && ((branch_m == 1'b1) || (exception_m == 1'b1))) - - - + + + || (I_CYC_O == 1'b1) + + @@ -67099,24 +67395,21 @@ assign q_x = (valid_x == 1'b1) && (kill_x == 1'b0); assign csr_write_enable_q_x = (csr_write_enable_x == 1'b1) && (q_x == 1'b1); assign eret_q_x = (eret_x == 1'b1) && (q_x == 1'b1); + -assign bret_q_x = (bret_x == 1'b1) && (q_x == 1'b1); - assign load_q_x = (load_x == 1'b1) && (q_x == 1'b1) + - && (bp_match == 1'b0) - ; assign store_q_x = (store_x == 1'b1) && (q_x == 1'b1) + - && (bp_match == 1'b0) - ; @@ -67127,13 +67420,13 @@ assign q_m = (valid_m == 1'b1) && (kill_m == 1'b0) && (exception_m == 1'b0); assign load_q_m = (load_m == 1'b1) && (q_m == 1'b1); assign store_q_m = (store_m == 1'b1) && (q_m == 1'b1); - -assign debug_exception_q_w = ((debug_exception_w == 1'b1) && (valid_w == 1'b1)); -assign non_debug_exception_q_w = ((non_debug_exception_w == 1'b1) && (valid_w == 1'b1)); - + +assign exception_q_w = ((exception_w == 1'b1) && (valid_w == 1'b1)); + + assign write_enable_q_x = (write_enable_x == 1'b1) && (valid_x == 1'b1) && (branch_flushX_m == 1'b0); assign write_enable_q_m = (write_enable_m == 1'b1) && (valid_m == 1'b1); @@ -67148,12 +67441,12 @@ assign cfg = { breakpoints[3:0], interrupts[5:0], - - 1'b1, - + 1'b0, + + @@ -67162,26 +67455,26 @@ assign cfg = { - - 1'b1, - - - - 1'b1, + 1'b0, - - + - 1'b1, + + 1'b0, + + + 1'b0, + + @@ -67253,22 +67546,19 @@ assign cfg2 = { + + + + + -assign iflush = ( (csr_write_enable_d == 1'b1) - && (csr_d == 5'h3) - && (stall_d == 1'b0) - && (kill_d == 1'b0) - && (valid_d == 1'b1)) - - - - || - ( (jtag_csr_write_enable == 1'b1) - && (jtag_csr == 5'h3)) + + + + + - ; - @@ -67284,7 +67574,7 @@ assign iflush = ( (csr_write_enable_d == 1'b1) -assign csr_d = read_idx_0_d[ (5-1):0]; +assign csr_d = read_idx_0_d[ (3-1):0]; always @(*) @@ -67292,29 +67582,27 @@ begin case (csr_x) - 5'h0, - 5'h1, - 5'h2: csr_read_data_x = interrupt_csr_read_data_x; + 3'h0, + 3'h1, + 3'h2: csr_read_data_x = interrupt_csr_read_data_x; - 5'h6: csr_read_data_x = cfg; - 5'h7: csr_read_data_x = {eba, 8'h00}; + 3'h6: csr_read_data_x = cfg; + 3'h7: csr_read_data_x = {eba, 8'h00}; + - 5'h9: csr_read_data_x = {deba, 8'h00}; - + + - 5'he: csr_read_data_x = jtx_csr_read_data; - 5'hf: csr_read_data_x = jrx_csr_read_data; - - 5'ha: csr_read_data_x = cfg2; + 3'ha: csr_read_data_x = cfg2; default: csr_read_data_x = { 32{1'bx}}; endcase @@ -67328,40 +67616,36 @@ end always @(posedge clk_i ) begin if (rst_i == 1'b1) - eba <= eba_reset[ (clogb2(32'h7fffffff-32'h0)-2)+2-1:8]; + eba <= eba_reset[ (32-2)+2-1:8]; else begin - if ((csr_write_enable_q_x == 1'b1) && (csr_x == 5'h7) && (stall_x == 1'b0)) - eba <= operand_1_x[ (clogb2(32'h7fffffff-32'h0)-2)+2-1:8]; + if ((csr_write_enable_q_x == 1'b1) && (csr_x == 3'h7) && (stall_x == 1'b0)) + eba <= operand_1_x[ (32-2)+2-1:8]; + + - if ((jtag_csr_write_enable == 1'b1) && (jtag_csr == 5'h7)) - eba <= jtag_csr_write_data[ (clogb2(32'h7fffffff-32'h0)-2)+2-1:8]; - end end + -always @(posedge clk_i ) -begin - if (rst_i == 1'b1) - deba <= deba_reset[ (clogb2(32'h7fffffff-32'h0)-2)+2-1:8]; - else - begin - if ((csr_write_enable_q_x == 1'b1) && (csr_x == 5'h9) && (stall_x == 1'b0)) - deba <= operand_1_x[ (clogb2(32'h7fffffff-32'h0)-2)+2-1:8]; - - - if ((jtag_csr_write_enable == 1'b1) && (jtag_csr == 5'h9)) - deba <= jtag_csr_write_data[ (clogb2(32'h7fffffff-32'h0)-2)+2-1:8]; + + + + + + + + + + + - end -end - @@ -67396,11 +67680,10 @@ end - - + @@ -67414,20 +67697,19 @@ end - -always @(*) -begin - if (icache_refill_request == 1'b1) - valid_a = 1'b0; - else if (icache_restart_request == 1'b1) - valid_a = 1'b1; - else - valid_a = !icache_refilling; -end + + + + + + - + + + + @@ -67439,6 +67721,7 @@ end + always @(posedge clk_i ) @@ -67455,11 +67738,11 @@ begin begin if ((kill_f == 1'b1) || (stall_a == 1'b0)) + - valid_f <= valid_a; - - + valid_f <= 1'b1; + else if (stall_f == 1'b0) valid_f <= 1'b0; @@ -67504,7 +67787,7 @@ begin operand_0_x <= { 32{1'b0}}; operand_1_x <= { 32{1'b0}}; store_operand_x <= { 32{1'b0}}; - branch_target_x <= { (clogb2(32'h7fffffff-32'h0)-2){1'b0}}; + branch_target_x <= { (32-2){1'b0}}; x_result_sel_csr_x <= 1'b0; @@ -67541,7 +67824,7 @@ begin m_bypass_enable_x <= 1'b0; write_enable_x <= 1'b0; write_idx_x <= { 5{1'b0}}; - csr_x <= { 5{1'b0}}; + csr_x <= { 3{1'b0}}; load_x <= 1'b0; store_x <= 1'b0; size_x <= { 2{1'b0}}; @@ -67564,16 +67847,14 @@ begin branch_predict_taken_x <= 1'b0; condition_x <= 3'b000; + - break_x <= 1'b0; - scall_x <= 1'b0; eret_x <= 1'b0; + - bret_x <= 1'b0; - @@ -67582,7 +67863,7 @@ begin csr_write_enable_x <= 1'b0; operand_m <= { 32{1'b0}}; - branch_target_m <= { (clogb2(32'h7fffffff-32'h0)-2){1'b0}}; + branch_target_m <= { (32-2){1'b0}}; m_result_sel_compare_m <= 1'b0; @@ -67615,10 +67896,9 @@ begin + + - debug_exception_m <= 1'b0; - non_debug_exception_m <= 1'b0; - operand_w <= { 32{1'b0}}; w_result_sel_load_w <= 1'b0; @@ -67630,13 +67910,13 @@ begin write_idx_w <= { 5{1'b0}}; write_enable_w <= 1'b0; - - debug_exception_w <= 1'b0; - non_debug_exception_w <= 1'b0; - + + exception_w <= 1'b0; + + @@ -67655,7 +67935,7 @@ begin operand_0_x <= d_result_0; operand_1_x <= d_result_1; store_operand_x <= bypass_data_1; - branch_target_x <= branch_reg_d == 1'b1 ? bypass_data_0[ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] : branch_target_d; + branch_target_x <= branch_reg_d == 1'b1 ? bypass_data_0[ ((32-2)+2-1):2] : branch_target_d; x_result_sel_csr_x <= x_result_sel_csr_d; @@ -67714,9 +67994,8 @@ begin condition_x <= condition_d; csr_write_enable_x <= csr_write_enable_d; + - break_x <= break_d; - scall_x <= scall_d; @@ -67725,9 +68004,8 @@ begin eret_x <= eret_d; + - bret_x <= bret_d; - write_enable_x <= write_enable_d; end @@ -67779,40 +68057,40 @@ begin - - if (non_debug_exception_x == 1'b1) - write_idx_m <= 5'd30; - else if (debug_exception_x == 1'b1) - write_idx_m <= 5'd31; - else - write_idx_m <= write_idx_x; - - + + + + if (exception_x == 1'b1) + write_idx_m <= 5'd30; + else + write_idx_m <= write_idx_x; + + condition_met_m <= condition_met_x; + + + + + + + + + - if (exception_x == 1'b1) - if ((dc_re == 1'b1) - || ((debug_exception_x == 1'b1) - && (non_debug_exception_x == 1'b0))) - branch_target_m <= {deba, eid_x, {3{1'b0}}}; - else - branch_target_m <= {eba, eid_x, {3{1'b0}}}; - else - branch_target_m <= branch_target_x; - - + branch_target_m <= exception_x == 1'b1 ? {eba, eid_x, {3{1'b0}}} : branch_target_x; + @@ -67824,16 +68102,14 @@ begin eret_m <= eret_q_x; + - bret_m <= bret_q_x; - write_enable_m <= exception_x == 1'b1 ? 1'b1 : write_enable_x; + + - debug_exception_m <= debug_exception_x; - non_debug_exception_m <= non_debug_exception_x; - end @@ -67879,13 +68155,13 @@ begin write_enable_w <= write_enable_m; - - debug_exception_w <= debug_exception_m; - non_debug_exception_w <= non_debug_exception_m; - + + exception_w <= exception_m; + + @@ -68429,7 +68705,7 @@ endmodule -module lm32_load_store_unit_medium_icache_debug ( +module lm32_load_store_unit_medium ( clk_i, rst_i, @@ -69741,7 +70017,7 @@ endmodule -module lm32_decoder_medium_icache_debug ( +module lm32_decoder_medium ( instruction, @@ -69820,16 +70096,14 @@ module lm32_decoder_medium_icache_debug ( bi_conditional, bi_unconditional, + - break_opcode, - scall, eret, + - bret, - @@ -69913,8 +70187,8 @@ output [ (5-1):0] write_idx; wire [ (5-1):0] write_idx; output [ (32-1):0] immediate; wire [ (32-1):0] immediate; -output [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] branch_offset; -wire [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] branch_offset; +output [ ((32-2)+2-1):2] branch_offset; +wire [ ((32-2)+2-1):2] branch_offset; output load; wire load; output store; @@ -69963,20 +70237,18 @@ wire bi_conditional; output bi_unconditional; wire bi_unconditional; - -output break_opcode; -wire break_opcode; + + output scall; wire scall; output eret; wire eret; - -output bret; -wire bret; + + @@ -70330,16 +70602,14 @@ assign branch = bra | call; assign branch_reg = op_call | op_b; assign condition = instruction[28:26]; + -assign break_opcode = op_raise & ~instruction[2]; - assign scall = op_raise & instruction[2]; assign eret = op_b & (instruction[25:21] == 5'd30); + -assign bret = op_b & (instruction[25:21] == 5'd31); - @@ -70728,190 +70998,210 @@ endmodule + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + - + + + + + + + + + -module lm32_icache_medium_icache_debug ( + - clk_i, - rst_i, - stall_a, - stall_f, - address_a, - address_f, - read_enable_f, - refill_ready, - refill_data, - iflush, - + + + + + + + + + + + - - valid_d, - branch_predict_taken_d, - stall_request, - restart_request, - refill_request, - refill_address, - refilling, - inst - ); + + + + + + + + + -parameter associativity = 1; -parameter sets = 512; -parameter bytes_per_line = 16; -parameter base_address = 0; -parameter limit = 0; + + + + + -localparam addr_offset_width = clogb2(bytes_per_line)-1-2; -localparam addr_set_width = clogb2(sets)-1; -localparam addr_offset_lsb = 2; -localparam addr_offset_msb = (addr_offset_lsb+addr_offset_width-1); -localparam addr_set_lsb = (addr_offset_msb+1); -localparam addr_set_msb = (addr_set_lsb+addr_set_width-1); -localparam addr_tag_lsb = (addr_set_msb+1); -localparam addr_tag_msb = clogb2( 32'h7fffffff- 32'h0)-1; -localparam addr_tag_width = (addr_tag_msb-addr_tag_lsb+1); + + + + + + + + + -input clk_i; -input rst_i; + + -input stall_a; -input stall_f; + + -input valid_d; -input branch_predict_taken_d; + + -input [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] address_a; -input [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] address_f; -input read_enable_f; + + + -input refill_ready; -input [ (32-1):0] refill_data; + + -input iflush; - + + - -output stall_request; -wire stall_request; -output restart_request; -reg restart_request; -output refill_request; -wire refill_request; -output [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] refill_address; -reg [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] refill_address; -output refilling; -reg refilling; -output [ (32-1):0] inst; -wire [ (32-1):0] inst; - - - - - -wire enable; -wire [0:associativity-1] way_mem_we; -wire [ (32-1):0] way_data[0:associativity-1]; -wire [ ((addr_tag_width+1)-1):1] way_tag[0:associativity-1]; -wire [0:associativity-1] way_valid; -wire [0:associativity-1] way_match; -wire miss; - -wire [ (addr_set_width-1):0] tmem_read_address; -wire [ (addr_set_width-1):0] tmem_write_address; -wire [ ((addr_offset_width+addr_set_width)-1):0] dmem_read_address; -wire [ ((addr_offset_width+addr_set_width)-1):0] dmem_write_address; -wire [ ((addr_tag_width+1)-1):0] tmem_write_data; - -reg [ 3:0] state; -wire flushing; -wire check; -wire refill; - -reg [associativity-1:0] refill_way_select; -reg [ addr_offset_msb:addr_offset_lsb] refill_offset; -wire last_refill; -reg [ (addr_set_width-1):0] flush_set; - -genvar i; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -70920,307 +71210,214 @@ genvar i; + + + + - -function integer clogb2; -input [31:0] value; -begin - for (clogb2 = 0; value > 0; clogb2 = clogb2 + 1) - value = value >> 1; -end -endfunction - -function integer clogb2_v1; -input [31:0] value; -reg [31:0] i; -reg [31:0] temp; -begin - temp = 0; - i = 0; - for (i = 0; temp < value; i = i + 1) - temp = 1<<i; - clogb2_v1 = i-1; -end -endfunction - - - - - - + + + + + + + + - generate - for (i = 0; i < associativity; i = i + 1) - begin : memories - - lm32_ram - #( - - .data_width (32), - .address_width ( (addr_offset_width+addr_set_width)) -) - way_0_data_ram - ( - - .read_clk (clk_i), - .write_clk (clk_i), - .reset (rst_i), - .read_address (dmem_read_address), - .enable_read (enable), - .write_address (dmem_write_address), - .enable_write ( 1'b1), - .write_enable (way_mem_we[i]), - .write_data (refill_data), - - .read_data (way_data[i]) - ); - - lm32_ram - #( - - .data_width ( (addr_tag_width+1)), - .address_width ( addr_set_width) + + + + + - ) - way_0_tag_ram - ( - - .read_clk (clk_i), - .write_clk (clk_i), - .reset (rst_i), - .read_address (tmem_read_address), - .enable_read (enable), - .write_address (tmem_write_address), - .enable_write ( 1'b1), - .write_enable (way_mem_we[i] | flushing), - .write_data (tmem_write_data), - - .read_data ({way_tag[i], way_valid[i]}) - ); - - end -endgenerate + + + + + + + + + + + -generate - for (i = 0; i < associativity; i = i + 1) - begin : match -assign way_match[i] = ({way_tag[i], way_valid[i]} == {address_f[ addr_tag_msb:addr_tag_lsb], 1'b1}); - end -endgenerate + -generate - if (associativity == 1) - begin : inst_1 -assign inst = way_match[0] ? way_data[0] : 32'b0; - end - else if (associativity == 2) - begin : inst_2 -assign inst = way_match[0] ? way_data[0] : (way_match[1] ? way_data[1] : 32'b0); - end -endgenerate -generate - if (bytes_per_line > 4) -assign dmem_write_address = {refill_address[ addr_set_msb:addr_set_lsb], refill_offset}; - else -assign dmem_write_address = refill_address[ addr_set_msb:addr_set_lsb]; -endgenerate + + + -assign dmem_read_address = address_a[ addr_set_msb:addr_offset_lsb]; + + + + + + -assign tmem_read_address = address_a[ addr_set_msb:addr_set_lsb]; -assign tmem_write_address = flushing - ? flush_set - : refill_address[ addr_set_msb:addr_set_lsb]; + + -generate - if (bytes_per_line > 4) -assign last_refill = refill_offset == {addr_offset_width{1'b1}}; - else -assign last_refill = 1'b1; -endgenerate - + + + -assign enable = (stall_a == 1'b0); + + + + -generate - if (associativity == 1) - begin : we_1 -assign way_mem_we[0] = (refill_ready == 1'b1); - end - else - begin : we_2 -assign way_mem_we[0] = (refill_ready == 1'b1) && (refill_way_select[0] == 1'b1); -assign way_mem_we[1] = (refill_ready == 1'b1) && (refill_way_select[1] == 1'b1); - end -endgenerate -assign tmem_write_data[ 0] = last_refill & !flushing; -assign tmem_write_data[ ((addr_tag_width+1)-1):1] = refill_address[ addr_tag_msb:addr_tag_lsb]; -assign flushing = |state[1:0]; -assign check = state[2]; -assign refill = state[3]; + + + -assign miss = (~(|way_match)) && (read_enable_f == 1'b1) && (stall_f == 1'b0) && !(valid_d && branch_predict_taken_d); -assign stall_request = (check == 1'b0); -assign refill_request = (refill == 1'b1); - + + + + + + + + + -generate - if (associativity >= 2) - begin : way_select -always @(posedge clk_i ) -begin - if (rst_i == 1'b1) - refill_way_select <= {{associativity-1{1'b0}}, 1'b1}; - else - begin - if (miss == 1'b1) - refill_way_select <= {refill_way_select[0], refill_way_select[1]}; - end -end - end -endgenerate + + + + -always @(posedge clk_i ) -begin - if (rst_i == 1'b1) - refilling <= 1'b0; - else - refilling <= refill; -end + -always @(posedge clk_i ) -begin - if (rst_i == 1'b1) - begin - state <= 4'b0001; - flush_set <= { addr_set_width{1'b1}}; - refill_address <= { (clogb2(32'h7fffffff-32'h0)-2){1'bx}}; - restart_request <= 1'b0; - end - else - begin - case (state) + + + + + + + + + + - 4'b0001: - begin - if (flush_set == { addr_set_width{1'b0}}) - state <= 4'b0100; - flush_set <= flush_set - 1'b1; - end + + + + + + - 4'b0010: - begin - if (flush_set == { addr_set_width{1'b0}}) - + + + + - - state <= 4'b0100; + - flush_set <= flush_set - 1'b1; - end + - 4'b0100: - begin - if (stall_a == 1'b0) - restart_request <= 1'b0; - if (iflush == 1'b1) - begin - refill_address <= address_f; - state <= 4'b0010; - end - else if (miss == 1'b1) - begin - refill_address <= address_f; - state <= 4'b1000; - end - end + + + + + + + + + + + + + + + + - 4'b1000: - begin - if (refill_ready == 1'b1) - begin - if (last_refill == 1'b1) - begin - restart_request <= 1'b1; - state <= 4'b0100; - end - end - end + + + + + + + + + + + - endcase - end -end + + -generate - if (bytes_per_line > 4) - begin -always @(posedge clk_i ) -begin - if (rst_i == 1'b1) - refill_offset <= {addr_offset_width{1'b0}}; - else - begin - case (state) + + + + + + + + + + + - 4'b0100: - begin - if (iflush == 1'b1) - refill_offset <= {addr_offset_width{1'b0}}; - else if (miss == 1'b1) - refill_offset <= {addr_offset_width{1'b0}}; - end + + + + + + + - 4'b1000: - begin - if (refill_ready == 1'b1) - refill_offset <= refill_offset + 1'b1; - end + + + + + + + + + + - endcase - end -end - end -endgenerate -endmodule - + + @@ -72404,165 +72601,127 @@ endmodule + + + + + + - - - - - - - - - - - - -module lm32_debug_medium_icache_debug ( - clk_i, - rst_i, - pc_x, - load_x, - store_x, - load_store_address_x, - csr_write_enable_x, - csr_write_data, - csr_x, - - - jtag_csr_write_enable, - jtag_csr_write_data, - jtag_csr, + + + + + + + + + - - - - eret_q_x, - bret_q_x, - stall_x, - exception_x, - q_x, - - + + - - - - dc_ss, + + + + - - dc_re, - bp_match, - wp_match - ); + + + + + + + + -parameter breakpoints = 0; -parameter watchpoints = 0; + + -input clk_i; -input rst_i; -input [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] pc_x; -input load_x; -input store_x; -input [ (32-1):0] load_store_address_x; -input csr_write_enable_x; -input [ (32-1):0] csr_write_data; -input [ (5-1):0] csr_x; - -input jtag_csr_write_enable; -input [ (32-1):0] jtag_csr_write_data; -input [ (5-1):0] jtag_csr; - - + + -input eret_q_x; -input bret_q_x; -input stall_x; -input exception_x; -input q_x; - + + + + + + + + - + + - - - - - - - - -output dc_ss; -reg dc_ss; + + + + + - -output dc_re; -reg dc_re; -output bp_match; -wire bp_match; -output wp_match; -wire wp_match; - - - - - -genvar i; - + -reg [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] bp_a[0:breakpoints-1]; -reg bp_e[0:breakpoints-1]; -wire [0:breakpoints-1]bp_match_n; - -reg [ 1:0] wpc_c[0:watchpoints-1]; -reg [ (32-1):0] wp[0:watchpoints-1]; -wire [0:watchpoints]wp_match_n; -wire debug_csr_write_enable; -wire [ (32-1):0] debug_csr_write_data; -wire [ (5-1):0] debug_csr; - -reg [ 2:0] state; + + + + + + + + - + + + + + + + + + + + + @@ -72570,6 +72729,7 @@ reg [ 2:0] state; + @@ -72577,35 +72737,48 @@ reg [ 2:0] state; + + + + + + + + + + + + + + + + + + + + + + + + + - -function integer clogb2; -input [31:0] value; -begin - for (clogb2 = 0; value > 0; clogb2 = clogb2 + 1) - value = value >> 1; -end -endfunction + + -function integer clogb2_v1; -input [31:0] value; -reg [31:0] i; -reg [31:0] temp; -begin - temp = 0; - i = 0; - for (i = 0; temp < value; i = i + 1) - temp = 1<<i; - clogb2_v1 = i-1; -end -endfunction + + + + + + @@ -72614,191 +72787,132 @@ endfunction -generate - for (i = 0; i < breakpoints; i = i + 1) - begin : bp_comb -assign bp_match_n[i] = ((bp_a[i] == pc_x) && (bp_e[i] == 1'b1)); - end -endgenerate -generate - + + + - if (breakpoints > 0) -assign bp_match = (|bp_match_n) || (state == 3'b011); - else -assign bp_match = state == 3'b011; - + + + + + + + + + + + - - + + -endgenerate - -generate - for (i = 0; i < watchpoints; i = i + 1) - begin : wp_comb -assign wp_match_n[i] = (wp[i] == load_store_address_x) && ((load_x & wpc_c[i][0]) | (store_x & wpc_c[i][1])); - end -endgenerate -generate - if (watchpoints > 0) -assign wp_match = |wp_match_n; - else -assign wp_match = 1'b0; -endgenerate - - - -assign debug_csr_write_enable = (csr_write_enable_x == 1'b1) || (jtag_csr_write_enable == 1'b1); -assign debug_csr_write_data = jtag_csr_write_enable == 1'b1 ? jtag_csr_write_data : csr_write_data; -assign debug_csr = jtag_csr_write_enable == 1'b1 ? jtag_csr : csr_x; - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + -generate - for (i = 0; i < breakpoints; i = i + 1) - begin : bp_seq -always @(posedge clk_i ) -begin - if (rst_i == 1'b1) - begin - bp_a[i] <= { (clogb2(32'h7fffffff-32'h0)-2){1'bx}}; - bp_e[i] <= 1'b0; - end - else - begin - if ((debug_csr_write_enable == 1'b1) && (debug_csr == 5'h10 + i)) - begin - bp_a[i] <= debug_csr_write_data[ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2]; - bp_e[i] <= debug_csr_write_data[0]; - end - end -end - end -endgenerate - - -generate - for (i = 0; i < watchpoints; i = i + 1) - begin : wp_seq -always @(posedge clk_i ) -begin - if (rst_i == 1'b1) - begin - wp[i] <= { 32{1'bx}}; - wpc_c[i] <= 2'b00; - end - else - begin - if (debug_csr_write_enable == 1'b1) - begin - if (debug_csr == 5'h8) - wpc_c[i] <= debug_csr_write_data[3+i*2:2+i*2]; - if (debug_csr == 5'h18 + i) - wp[i] <= debug_csr_write_data; - end - end -end - end -endgenerate - - -always @(posedge clk_i ) -begin - if (rst_i == 1'b1) - dc_re <= 1'b0; - else - begin - if ((debug_csr_write_enable == 1'b1) && (debug_csr == 5'h8)) - dc_re <= debug_csr_write_data[1]; - end -end - - - + -always @(posedge clk_i ) -begin - if (rst_i == 1'b1) - begin - state <= 3'b000; - dc_ss <= 1'b0; - end - else - begin - if ((debug_csr_write_enable == 1'b1) && (debug_csr == 5'h8)) - begin - dc_ss <= debug_csr_write_data[0]; - if (debug_csr_write_data[0] == 1'b0) - state <= 3'b000; - else - state <= 3'b001; - end - case (state) - 3'b001: - begin + + + + + + + + + + + + + + + + + + - if ( ( (eret_q_x == 1'b1) - || (bret_q_x == 1'b1) - ) - && (stall_x == 1'b0) - ) - state <= 3'b010; - end - 3'b010: - begin + + + + + + + + + - if ((q_x == 1'b1) && (stall_x == 1'b0)) - state <= 3'b011; - end - 3'b011: - begin + + + + + - + - - if ((exception_x == 1'b1) && (q_x == 1'b1) && (stall_x == 1'b0)) - begin - dc_ss <= 1'b0; - state <= 3'b100; - end - end - 3'b100: - begin + - + + + + + + + + + + + + + + - state <= 3'b000; - end - endcase - end -end - -endmodule - @@ -73171,7 +73285,7 @@ endmodule -module lm32_instruction_unit_medium_icache_debug ( +module lm32_instruction_unit_medium ( clk_i, rst_i, @@ -73196,9 +73310,8 @@ module lm32_instruction_unit_medium_icache_debug ( branch_mispredict_taken_m, branch_target_m, + - iflush, - @@ -73222,12 +73335,11 @@ module lm32_instruction_unit_medium_icache_debug ( + + + + - jtag_read_enable, - jtag_write_enable, - jtag_write_data, - jtag_address, - @@ -73237,12 +73349,11 @@ module lm32_instruction_unit_medium_icache_debug ( pc_m, pc_w, + + + + - icache_stall_request, - icache_restart_request, - icache_refill_request, - icache_refilling, - @@ -73263,10 +73374,9 @@ module lm32_instruction_unit_medium_icache_debug ( + + - jtag_read_data, - jtag_access_complete, - @@ -73312,7 +73422,7 @@ input valid_d; input kill_f; input branch_predict_taken_d; -input [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] branch_predict_address_d; +input [ ((32-2)+2-1):2] branch_predict_address_d; @@ -73322,12 +73432,11 @@ input [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] branch_predict_address_d; input exception_m; input branch_taken_m; input branch_mispredict_taken_m; -input [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] branch_target_m; +input [ ((32-2)+2-1):2] branch_target_m; + -input iflush; - @@ -73353,40 +73462,38 @@ input i_rty_i; + + + + -input jtag_read_enable; -input jtag_write_enable; -input [ 7:0] jtag_write_data; -input [ (32-1):0] jtag_address; - -output [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] pc_f; -reg [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] pc_f; -output [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] pc_d; -reg [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] pc_d; -output [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] pc_x; -reg [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] pc_x; -output [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] pc_m; -reg [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] pc_m; -output [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] pc_w; -reg [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] pc_w; +output [ ((32-2)+2-1):2] pc_f; +reg [ ((32-2)+2-1):2] pc_f; +output [ ((32-2)+2-1):2] pc_d; +reg [ ((32-2)+2-1):2] pc_d; +output [ ((32-2)+2-1):2] pc_x; +reg [ ((32-2)+2-1):2] pc_x; +output [ ((32-2)+2-1):2] pc_m; +reg [ ((32-2)+2-1):2] pc_m; +output [ ((32-2)+2-1):2] pc_w; +reg [ ((32-2)+2-1):2] pc_w; + + + + + + + + -output icache_stall_request; -wire icache_stall_request; -output icache_restart_request; -wire icache_restart_request; -output icache_refill_request; -wire icache_refill_request; -output icache_refilling; -wire icache_refilling; - @@ -73399,11 +73506,11 @@ wire icache_refilling; output [ (32-1):0] i_dat_o; + -reg [ (32-1):0] i_dat_o; - - +wire [ (32-1):0] i_dat_o; + output [ (32-1):0] i_adr_o; reg [ (32-1):0] i_adr_o; @@ -73411,21 +73518,21 @@ output i_cyc_o; reg i_cyc_o; output [ (4-1):0] i_sel_o; + -reg [ (4-1):0] i_sel_o; - - +wire [ (4-1):0] i_sel_o; + output i_stb_o; reg i_stb_o; output i_we_o; + -reg i_we_o; - - +wire i_we_o; + output [ (3-1):0] i_cti_o; reg [ (3-1):0] i_cti_o; @@ -73437,12 +73544,11 @@ wire [ (2-1):0] i_bte_o; + + + + -output [ 7:0] jtag_read_data; -reg [ 7:0] jtag_read_data; -output jtag_access_complete; -wire jtag_access_complete; - @@ -73463,30 +73569,31 @@ reg [ (32-1):0] instruction_d; -reg [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] pc_a; +reg [ ((32-2)+2-1):2] pc_a; + -reg [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] restart_address; - + + + + + + + + + -wire icache_read_enable_f; -wire [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] icache_refill_address; -reg icache_refill_ready; -reg [ (32-1):0] icache_refill_data; -wire [ (32-1):0] icache_data_f; -wire [ (3-1):0] first_cycle_type; -wire [ (3-1):0] next_cycle_type; -wire last_word; -wire [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] first_address; - - - + + +reg [ (32-1):0] wb_data_f; + + @@ -73506,9 +73613,8 @@ wire [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] first_address; + -reg jtag_access; - @@ -73625,57 +73731,53 @@ endfunction - -lm32_icache_medium_icache_debug #( - .associativity (associativity), - .sets (sets), - .bytes_per_line (bytes_per_line), - .base_address (base_address), - .limit (limit) - ) icache ( + + + + + + + - .clk_i (clk_i), - .rst_i (rst_i), - .stall_a (stall_a), - .stall_f (stall_f), - .branch_predict_taken_d (branch_predict_taken_d), - .valid_d (valid_d), - .address_a (pc_a), - .address_f (pc_f), - .read_enable_f (icache_read_enable_f), - .refill_ready (icache_refill_ready), - .refill_data (icache_refill_data), - .iflush (iflush), + + + + + + + + + + + + + + + + + + + - .stall_request (icache_stall_request), - .restart_request (icache_restart_request), - .refill_request (icache_refill_request), - .refill_address (icache_refill_address), - .refilling (icache_refilling), - .inst (icache_data_f) - ); - - - -assign icache_read_enable_f = (valid_f == 1'b1) - && (kill_f == 1'b0) - + + + + - + - - ; - + + @@ -73703,11 +73805,10 @@ begin pc_a = branch_predict_address_d; else + + + - if (icache_restart_request == 1'b1) - pc_a = restart_address; - else - pc_a = pc_f + 1'b1; end @@ -73720,25 +73821,25 @@ end - - + + -assign instruction_f = icache_data_f; - - - + + - +assign instruction_f = wb_data_f; + + @@ -73746,11 +73847,11 @@ assign instruction_f = icache_data_f; - - - - +assign i_dat_o = 32'd0; +assign i_we_o = 1'b0; +assign i_sel_o = 4'b1111; + assign i_bte_o = 2'b00; @@ -73759,32 +73860,31 @@ assign i_bte_o = 2'b00; -generate - case (bytes_per_line) - 4: - begin -assign first_cycle_type = 3'b111; -assign next_cycle_type = 3'b111; -assign last_word = 1'b1; -assign first_address = icache_refill_address; - end - 8: - begin -assign first_cycle_type = 3'b010; -assign next_cycle_type = 3'b111; -assign last_word = i_adr_o[addr_offset_msb:addr_offset_lsb] == 1'b1; -assign first_address = {icache_refill_address[ (clogb2(32'h7fffffff-32'h0)-2)+2-1:addr_offset_msb+1], {addr_offset_width{1'b0}}}; - end - 16: - begin -assign first_cycle_type = 3'b010; -assign next_cycle_type = i_adr_o[addr_offset_msb] == 1'b1 ? 3'b111 : 3'b010; -assign last_word = i_adr_o[addr_offset_msb:addr_offset_lsb] == 2'b11; -assign first_address = {icache_refill_address[ (clogb2(32'h7fffffff-32'h0)-2)+2-1:addr_offset_msb+1], {addr_offset_width{1'b0}}}; - end - endcase -endgenerate - + + + + + + + + + + + + + + + + + + + + + + + + + @@ -73797,10 +73897,10 @@ begin if (rst_i == 1'b1) begin pc_f <= ( 32'h00000000-4)/4; - pc_d <= { (clogb2(32'h7fffffff-32'h0)-2){1'b0}}; - pc_x <= { (clogb2(32'h7fffffff-32'h0)-2){1'b0}}; - pc_m <= { (clogb2(32'h7fffffff-32'h0)-2){1'b0}}; - pc_w <= { (clogb2(32'h7fffffff-32'h0)-2){1'b0}}; + pc_d <= { (32-2){1'b0}}; + pc_x <= { (32-2){1'b0}}; + pc_m <= { (32-2){1'b0}}; + pc_w <= { (32-2){1'b0}}; end else begin @@ -73818,14 +73918,13 @@ end + -always @(posedge clk_i ) -begin - if (rst_i == 1'b1) - restart_address <= { (clogb2(32'h7fffffff-32'h0)-2){1'b0}}; - else - begin - + + + + + @@ -73837,18 +73936,14 @@ begin + + + - - - if (icache_refill_request == 1'b1) - restart_address <= icache_refill_address; - - + + - end -end - @@ -73867,138 +73962,125 @@ end - -assign jtag_access_complete = (i_cyc_o == 1'b1) && ((i_ack_i == 1'b1) || (i_err_i == 1'b1)) && (jtag_access == 1'b1); -always @(*) -begin - case (jtag_address[1:0]) - 2'b00: jtag_read_data = i_dat_i[ 31:24]; - 2'b01: jtag_read_data = i_dat_i[ 23:16]; - 2'b10: jtag_read_data = i_dat_i[ 15:8]; - 2'b11: jtag_read_data = i_dat_i[ 7:0]; - endcase -end + + + + + + + + - - -always @(posedge clk_i ) -begin - if (rst_i == 1'b1) - begin - i_cyc_o <= 1'b0; - i_stb_o <= 1'b0; - i_adr_o <= { 32{1'b0}}; - i_cti_o <= 3'b111; - i_lock_o <= 1'b0; - icache_refill_data <= { 32{1'b0}}; - icache_refill_ready <= 1'b0; - - - + + - i_we_o <= 1'b0; - i_sel_o <= 4'b1111; - jtag_access <= 1'b0; + + + + + + + + + + - end - else - begin - icache_refill_ready <= 1'b0; + + + + + + + + + + + - if (i_cyc_o == 1'b1) - begin - if ((i_ack_i == 1'b1) || (i_err_i == 1'b1)) - begin - - - if (jtag_access == 1'b1) - begin - i_cyc_o <= 1'b0; - i_stb_o <= 1'b0; - i_we_o <= 1'b0; - jtag_access <= 1'b0; - end - else + + + + + + + + + + - begin - if (last_word == 1'b1) - begin + + + - i_cyc_o <= 1'b0; - i_stb_o <= 1'b0; - i_lock_o <= 1'b0; - end + + + - i_adr_o[addr_offset_msb:addr_offset_lsb] <= i_adr_o[addr_offset_msb:addr_offset_lsb] + 1'b1; - i_cti_o <= next_cycle_type; - icache_refill_ready <= 1'b1; - icache_refill_data <= i_dat_i; - end - end - + + + + + + + + - - end - else - begin - if ((icache_refill_request == 1'b1) && (icache_refill_ready == 1'b0)) - begin - - - - i_sel_o <= 4'b1111; - - - i_adr_o <= {first_address, 2'b00}; - i_cyc_o <= 1'b1; - i_stb_o <= 1'b1; - i_cti_o <= first_cycle_type; + + + + + - + + + + + + + + - end - - - else - begin - if ((jtag_read_enable == 1'b1) || (jtag_write_enable == 1'b1)) - begin - case (jtag_address[1:0]) - 2'b00: i_sel_o <= 4'b1000; - 2'b01: i_sel_o <= 4'b0100; - 2'b10: i_sel_o <= 4'b0010; - 2'b11: i_sel_o <= 4'b0001; - endcase - i_adr_o <= jtag_address; - i_dat_o <= {4{jtag_write_data}}; - i_cyc_o <= 1'b1; - i_stb_o <= 1'b1; - i_we_o <= jtag_write_enable; - i_cti_o <= 3'b111; - jtag_access <= 1'b1; - end - end + + + + + + + + + + - + + + + + + + + + + + @@ -74008,84 +74090,91 @@ begin + + - end - end -end - - - - - - - - - - - + +always @(posedge clk_i ) +begin + if (rst_i == 1'b1) + begin + i_cyc_o <= 1'b0; + i_stb_o <= 1'b0; + i_adr_o <= { 32{1'b0}}; + i_cti_o <= 3'b111; + i_lock_o <= 1'b0; + wb_data_f <= { 32{1'b0}}; + - - - - - + + end + else + begin + if (i_cyc_o == 1'b1) + begin - - + if((i_ack_i == 1'b1) || (i_err_i == 1'b1)) + begin - - + i_cyc_o <= 1'b0; + i_stb_o <= 1'b0; - - - + wb_data_f <= i_dat_i; + end + - - - + + end + else + begin + if ( (stall_a == 1'b0) + - - + - - + ) + begin - + - - - - - - - - - + i_adr_o <= {pc_a, 2'b00}; + i_cyc_o <= 1'b1; + i_stb_o <= 1'b1; + + + + end + else + begin + if ( (stall_a == 1'b0) + + - - - + ) + begin + - - - - - + end + end + end + end +end + @@ -74466,523 +74555,443 @@ endmodule + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + - - + + + + + + + + + + - - - - - - - - - - -module lm32_jtag_medium_icache_debug ( - clk_i, - rst_i, - jtag_clk, - jtag_update, - jtag_reg_q, - jtag_reg_addr_q, - - - csr, - csr_write_enable, - csr_write_data, - stall_x, + + + + + + + + + + - - - jtag_read_data, - jtag_access_complete, + + - - - exception_q_w, - - - jtx_csr_read_data, - jrx_csr_read_data, + + + - - - jtag_csr_write_enable, - jtag_csr_write_data, - jtag_csr, - jtag_read_enable, - jtag_write_enable, - jtag_write_data, - jtag_address, + + + + + + + - - - jtag_break, - jtag_reset, + + - jtag_reg_d, - jtag_reg_addr_d - ); - + + + -input clk_i; -input rst_i; -input jtag_clk; -input jtag_update; -input [ 7:0] jtag_reg_q; -input [2:0] jtag_reg_addr_q; + + - + + + + -input [ (5-1):0] csr; -input csr_write_enable; -input [ (32-1):0] csr_write_data; -input stall_x; + + + + - - -input [ 7:0] jtag_read_data; -input jtag_access_complete; + + - - -input exception_q_w; + - - -output [ (32-1):0] jtx_csr_read_data; -wire [ (32-1):0] jtx_csr_read_data; -output [ (32-1):0] jrx_csr_read_data; -wire [ (32-1):0] jrx_csr_read_data; + + + + - - -output jtag_csr_write_enable; -reg jtag_csr_write_enable; -output [ (32-1):0] jtag_csr_write_data; -wire [ (32-1):0] jtag_csr_write_data; -output [ (5-1):0] jtag_csr; -wire [ (5-1):0] jtag_csr; -output jtag_read_enable; -reg jtag_read_enable; -output jtag_write_enable; -reg jtag_write_enable; -output [ 7:0] jtag_write_data; -wire [ 7:0] jtag_write_data; -output [ (32-1):0] jtag_address; -wire [ (32-1):0] jtag_address; + + + + + + + + + + + + + + - - -output jtag_break; -reg jtag_break; -output jtag_reset; -reg jtag_reset; + + + + -output [ 7:0] jtag_reg_d; -reg [ 7:0] jtag_reg_d; -output [2:0] jtag_reg_addr_d; -wire [2:0] jtag_reg_addr_d; + + + + -reg rx_update; -reg rx_update_r; -reg rx_update_r_r; -reg rx_update_r_r_r; - + + + + -wire [ 7:0] rx_byte; -wire [2:0] rx_addr; + - -reg [ 7:0] uart_tx_byte; -reg uart_tx_valid; -reg [ 7:0] uart_rx_byte; -reg uart_rx_valid; - + + + + + -reg [ 3:0] command; - -reg [ 7:0] jtag_byte_0; -reg [ 7:0] jtag_byte_1; -reg [ 7:0] jtag_byte_2; -reg [ 7:0] jtag_byte_3; -reg [ 7:0] jtag_byte_4; -reg processing; + + + + + + + -reg [ 3:0] state; - + - -assign jtag_csr_write_data = {jtag_byte_0, jtag_byte_1, jtag_byte_2, jtag_byte_3}; -assign jtag_csr = jtag_byte_4[ (5-1):0]; -assign jtag_address = {jtag_byte_0, jtag_byte_1, jtag_byte_2, jtag_byte_3}; -assign jtag_write_data = jtag_byte_4; + + + + - - -assign jtag_reg_addr_d[1:0] = {uart_rx_valid, uart_tx_valid}; - - - + + - + -assign jtag_reg_addr_d[2] = processing; + - - -assign jtx_csr_read_data = {{ 32-9{1'b0}}, uart_tx_valid, 8'h00}; -assign jrx_csr_read_data = {{ 32-9{1'b0}}, uart_rx_valid, uart_rx_byte}; - + + + -assign rx_byte = jtag_reg_q; -assign rx_addr = jtag_reg_addr_q; - + + -always @(posedge clk_i ) -begin - if (rst_i == 1'b1) - begin - rx_update <= 1'b0; - rx_update_r <= 1'b0; - rx_update_r_r <= 1'b0; - rx_update_r_r_r <= 1'b0; - end - else - begin - rx_update <= jtag_update; - rx_update_r <= rx_update; - rx_update_r_r <= rx_update_r; - rx_update_r_r_r <= rx_update_r_r; - end -end + -always @(posedge clk_i ) -begin - if (rst_i == 1'b1) - begin - state <= 4'h0; - command <= 4'b0000; - jtag_reg_d <= 8'h00; - + + + + + + + + + + + + + + - processing <= 1'b0; - jtag_csr_write_enable <= 1'b0; - jtag_read_enable <= 1'b0; - jtag_write_enable <= 1'b0; - - - jtag_break <= 1'b0; - jtag_reset <= 1'b0; - + - - - uart_tx_byte <= 8'h00; - uart_tx_valid <= 1'b0; - uart_rx_byte <= 8'h00; - uart_rx_valid <= 1'b0; + + + + + + + + + - end - else - begin - - - if ((csr_write_enable == 1'b1) && (stall_x == 1'b0)) - begin - case (csr) - 5'he: - begin - - uart_tx_byte <= csr_write_data[ 7:0]; - uart_tx_valid <= 1'b1; - end - 5'hf: - begin - - uart_rx_valid <= 1'b0; - end - endcase - end + + - + + + + + + + + + + - if (exception_q_w == 1'b1) - begin - jtag_break <= 1'b0; - jtag_reset <= 1'b0; - end + + + + + + + + + + + + + + + + + + + + + - case (state) - 4'h0: - begin + + + - if ((~rx_update_r_r_r & rx_update_r_r) == 1'b1) - begin - command <= rx_byte[7:4]; - case (rx_addr) - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - 3'b000: - begin - case (rx_byte[7:4]) - + + + + + + + - 4'b0001: - state <= 4'h1; - 4'b0011: - begin - {jtag_byte_2, jtag_byte_3} <= {jtag_byte_2, jtag_byte_3} + 1'b1; - state <= 4'h6; - end - 4'b0010: - state <= 4'h1; - 4'b0100: - begin - {jtag_byte_2, jtag_byte_3} <= {jtag_byte_2, jtag_byte_3} + 1'b1; - state <= 5; - end - 4'b0101: - state <= 4'h1; - + - 4'b0110: - begin - - - uart_rx_valid <= 1'b0; - uart_tx_valid <= 1'b0; - + + - jtag_break <= 1'b1; - end - 4'b0111: - begin - - - uart_rx_valid <= 1'b0; - uart_tx_valid <= 1'b0; - + + + + + + + + + + + - jtag_reset <= 1'b1; - end - endcase - end + + + + + - - + + - 3'b001: - begin - uart_rx_byte <= rx_byte; - uart_rx_valid <= 1'b1; - end - 3'b010: - begin - jtag_reg_d <= uart_tx_byte; - uart_tx_valid <= 1'b0; - end - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - default: - ; - endcase - end - end - 4'h1: - begin - if ((~rx_update_r_r_r & rx_update_r_r) == 1'b1) - begin - jtag_byte_0 <= rx_byte; - state <= 4'h2; - end - end - 4'h2: - begin - if ((~rx_update_r_r_r & rx_update_r_r) == 1'b1) - begin - jtag_byte_1 <= rx_byte; - state <= 4'h3; - end - end - 4'h3: - begin - if ((~rx_update_r_r_r & rx_update_r_r) == 1'b1) - begin - jtag_byte_2 <= rx_byte; - state <= 4'h4; - end - end - 4'h4: - begin - if ((~rx_update_r_r_r & rx_update_r_r) == 1'b1) - begin - jtag_byte_3 <= rx_byte; - if (command == 4'b0001) - state <= 4'h6; - else - state <= 4'h5; - end - end - 4'h5: - begin - if ((~rx_update_r_r_r & rx_update_r_r) == 1'b1) - begin - jtag_byte_4 <= rx_byte; - state <= 4'h6; - end - end - 4'h6: - begin - case (command) - 4'b0001, - 4'b0011: - begin - jtag_read_enable <= 1'b1; - processing <= 1'b1; - state <= 4'h7; - end - 4'b0010, - 4'b0100: - begin - jtag_write_enable <= 1'b1; - processing <= 1'b1; - state <= 4'h7; - end - 4'b0101: - begin - jtag_csr_write_enable <= 1'b1; - processing <= 1'b1; - state <= 4'h8; - end - endcase - end - 4'h7: - begin - if (jtag_access_complete == 1'b1) - begin - jtag_read_enable <= 1'b0; - jtag_reg_d <= jtag_read_data; - jtag_write_enable <= 1'b0; - processing <= 1'b0; - state <= 4'h0; - end - end - 4'h8: - begin - jtag_csr_write_enable <= 1'b0; - processing <= 1'b0; - state <= 4'h0; - end - - endcase - end -end - -endmodule - @@ -75337,7 +75346,7 @@ endmodule -module lm32_interrupt_medium_icache_debug ( +module lm32_interrupt_medium ( clk_i, rst_i, @@ -75346,18 +75355,17 @@ module lm32_interrupt_medium_icache_debug ( stall_x, - - non_debug_exception, - debug_exception, - + + exception, + + eret_q_x, + - bret_q_x, - csr, csr_write_data, @@ -75386,21 +75394,20 @@ input [interrupts-1:0] interrupt; input stall_x; + + -input non_debug_exception; -input debug_exception; - - +input exception; + input eret_q_x; + -input bret_q_x; - -input [ (5-1):0] csr; +input [ (3-1):0] csr; input [ (32-1):0] csr_write_data; input csr_write_enable; @@ -75427,9 +75434,8 @@ wire [interrupts-1:0] interrupt_n_exception; reg ie; reg eie; + -reg bie; - reg [interrupts-1:0] ip; reg [interrupts-1:0] im; @@ -75449,11 +75455,11 @@ assign asserted = ip | interrupt; assign ie_csr_read_data = {{ 32-3{1'b0}}, - - bie, - + + 1'b0, + eie, ie @@ -75467,19 +75473,19 @@ generate always @(*) begin case (csr) - 5'h0: csr_read_data = {{ 32-3{1'b0}}, + 3'h0: csr_read_data = {{ 32-3{1'b0}}, + - bie, - - + 1'b0, + eie, ie }; - 5'h2: csr_read_data = ip; - 5'h1: csr_read_data = im; + 3'h2: csr_read_data = ip; + 3'h1: csr_read_data = im; default: csr_read_data = { 32{1'bx}}; endcase end @@ -75490,18 +75496,18 @@ end always @(*) begin case (csr) - 5'h0: csr_read_data = {{ 32-3{1'b0}}, + 3'h0: csr_read_data = {{ 32-3{1'b0}}, + - bie, - - + 1'b0, + eie, ie }; - 5'h2: csr_read_data = ip; + 3'h2: csr_read_data = ip; default: csr_read_data = { 32{1'bx}}; endcase end @@ -75530,9 +75536,8 @@ always @(posedge clk_i ) ie <= 1'b0; eie <= 1'b0; + - bie <= 1'b0; - im <= {interrupts{1'b0}}; ip <= {interrupts{1'b0}}; @@ -75544,21 +75549,13 @@ always @(posedge clk_i ) ip <= asserted; - - if (non_debug_exception == 1'b1) - begin + + - eie <= ie; - ie <= 1'b0; - end - else if (debug_exception == 1'b1) - begin + + + - bie <= ie; - ie <= 1'b0; - end - - @@ -75566,6 +75563,14 @@ always @(posedge clk_i ) + if (exception == 1'b1) + begin + + eie <= ie; + ie <= 1'b0; + end + + else if (stall_x == 1'b0) begin @@ -75583,28 +75588,26 @@ always @(posedge clk_i ) - - else if (bret_q_x == 1'b1) - ie <= bie; - + + + else if (csr_write_enable == 1'b1) begin - if (csr == 5'h0) + if (csr == 3'h0) begin ie <= csr_write_data[0]; eie <= csr_write_data[1]; + - bie <= csr_write_data[2]; - end - if (csr == 5'h1) + if (csr == 3'h1) im <= csr_write_data[interrupts-1:0]; - if (csr == 5'h2) + if (csr == 3'h2) ip <= asserted & ~csr_write_data[interrupts-1:0]; end end @@ -75621,9 +75624,8 @@ always @(posedge clk_i ) ie <= 1'b0; eie <= 1'b0; + - bie <= 1'b0; - ip <= {interrupts{1'b0}}; eie_delay <= 0; @@ -75633,21 +75635,13 @@ always @(posedge clk_i ) ip <= asserted; - - if (non_debug_exception == 1'b1) - begin + + - eie <= ie; - ie <= 1'b0; - end - else if (debug_exception == 1'b1) - begin + + + - bie <= ie; - ie <= 1'b0; - end - - @@ -75655,6 +75649,14 @@ always @(posedge clk_i ) + if (exception == 1'b1) + begin + + eie <= ie; + ie <= 1'b0; + end + + else if (stall_x == 1'b0) begin @@ -75670,26 +75672,24 @@ always @(posedge clk_i ) end - - else if (bret_q_x == 1'b1) - ie <= bie; - + + + else if (csr_write_enable == 1'b1) begin - if (csr == 5'h0) + if (csr == 3'h0) begin ie <= csr_write_data[0]; eie <= csr_write_data[1]; + - bie <= csr_write_data[2]; - end - if (csr == 5'h2) + if (csr == 3'h2) ip <= asserted & ~csr_write_data[interrupts-1:0]; end end diff --git a/modules/wishbone/wb_lm32/generated/xwb_lm32.vhd b/modules/wishbone/wb_lm32/generated/xwb_lm32.vhd index e5fc68a3c4e35de7d01d0d592edb5bbc156801ea..73b87ee99a4f3b12fe5107cb192e069dc77f33de 100644 --- a/modules/wishbone/wb_lm32/generated/xwb_lm32.vhd +++ b/modules/wishbone/wb_lm32/generated/xwb_lm32.vhd @@ -635,7 +635,7 @@ end generate gen_profile_full_debug; if I_CYC = '1' and inst_was_busy = '0' then inst_addr := I_ADR; if I_CTI = "010" then - inst_length := dcache_burst_length; + inst_length := icache_burst_length; else inst_length := 1; end if; diff --git a/modules/wishbone/wb_onewire_master/wb_onewire_master.vhd b/modules/wishbone/wb_onewire_master/wb_onewire_master.vhd index 56c95d534f3a0db1e45d2731ff5818f0a6edbfca..933c2c8c266c97c05b59e18c1440c350d9745bcd 100644 --- a/modules/wishbone/wb_onewire_master/wb_onewire_master.vhd +++ b/modules/wishbone/wb_onewire_master/wb_onewire_master.vhd @@ -5,7 +5,7 @@ -- Author : Tomasz Wlostowski -- Company : CERN BE-Co-HT -- Created : 2010-05-18 --- Last update: 2011-10-04 +-- Last update: 2012-02-23 -- Platform : FPGA-generic -- Standard : VHDL'93 ------------------------------------------------------------------------------- @@ -95,6 +95,8 @@ architecture rtl of wb_onewire_master is signal adp_out : t_wishbone_master_out; signal adp_in : t_wishbone_master_in; + + signal rdat_int : std_logic_vector(31 downto 0); begin -- rtl @@ -130,11 +132,22 @@ begin -- rtl master_o => adp_out); - bus_wen <= adp_out.cyc and adp_out.stb and adp_out.we; - bus_ren <= adp_out.cyc and adp_out.stb and not adp_out.we; - - adp_in.ack <= adp_out.stb and adp_out.cyc; - rst <= not rst_n_i; + bus_wen <= adp_out.cyc and adp_out.stb and adp_out.we and not adp_in.ack; + bus_ren <= adp_out.cyc and adp_out.stb and not (adp_out.we or adp_in.ack); + + process(clk_sys_i) + begin + if rising_edge(clk_sys_i) then + if rst_n_i = '0' then + adp_in.ack <= '0'; + else + adp_in.ack <= adp_out.stb and adp_out.cyc and not adp_in.ack; + adp_in.dat <= rdat_int; + end if; + end if; + end process; + + rst <= not rst_n_i; Wrapped_1wire : sockit_owm generic map ( @@ -148,7 +161,7 @@ begin -- rtl bus_wen => bus_wen, bus_adr => adp_out.adr(0 downto 0), bus_wdt => adp_out.dat, - bus_rdt => adp_in.dat, + bus_rdt => rdat_int, bus_irq => adp_in.int, owr_p => owr_pwren_o, owr_e => owr_en_o, diff --git a/modules/wishbone/wb_slave_adapter/wb_slave_adapter.vhd b/modules/wishbone/wb_slave_adapter/wb_slave_adapter.vhd index cd801762366850216dd1c9a28e38d189ca425538..ed43727f92805c08336a5e00a477b3c54007c105 100644 --- a/modules/wishbone/wb_slave_adapter/wb_slave_adapter.vhd +++ b/modules/wishbone/wb_slave_adapter/wb_slave_adapter.vhd @@ -68,10 +68,10 @@ architecture rtl of wb_slave_adapter is return integer is begin case c_wishbone_data_width is - when 8 => return 0; - when 16 => return 1; - when 32 => return 2; - when 64 => return 3; + when 8 => return 0; + when 16 => return 1; + when 32 => return 2; + when 64 => return 3; when others => report "wb_slave_adapter: invalid c_wishbone_data_width (we support 8, 16, 32 and 64)" severity failure; end case; @@ -92,6 +92,7 @@ architecture rtl of wb_slave_adapter is signal master_out : t_wishbone_master_out; signal slave_in : t_wishbone_slave_in; signal slave_out : t_wishbone_slave_out; + signal stored_we : std_logic; begin -- rtl @@ -154,7 +155,10 @@ begin -- rtl else case fsm_state is when IDLE => - if(slave_in.stb = '1' and master_in.stall = '0' and master_in.ack = '0') then + + if(slave_in.stb = '1' and (master_in.stall = '0' or g_master_mode = CLASSIC) and master_in.ack = '0') then + stored_we <= slave_in.we; + fsm_state <= WAIT4ACK; end if; when WAIT4ACK => @@ -175,13 +179,16 @@ begin -- rtl else master_out.stb <= '0'; end if; + master_out.we <= slave_in.we; slave_out.stall <= '0'; elsif(g_master_mode = CLASSIC and g_slave_mode = PIPELINED) then if(fsm_state = WAIT4ACK) then master_out.stb <= '1'; + master_out.we <= stored_we; else master_out.stb <= slave_in.stb; + master_out.we <= slave_in.we; end if; if(fsm_state = WAIT4ACK) then @@ -190,6 +197,7 @@ begin -- rtl slave_out.stall <= slave_in.stb; end if; else + master_out.we <= slave_in.we; master_out.stb <= slave_in.stb; slave_out.stall <= master_in.stall; end if; @@ -198,7 +206,7 @@ begin -- rtl master_out.dat <= slave_in.dat; master_out.cyc <= slave_in.cyc; master_out.sel <= slave_in.sel; - master_out.we <= slave_in.we; +-- master_out.we <= slave_in.we; slave_out.ack <= master_in.ack; slave_out.err <= master_in.err; diff --git a/modules/wishbone/wb_xilinx_fpga_loader/Manifest.py b/modules/wishbone/wb_xilinx_fpga_loader/Manifest.py new file mode 100644 index 0000000000000000000000000000000000000000..08062c9c6f2dfb035603b2d8e25984a672e3fbcc --- /dev/null +++ b/modules/wishbone/wb_xilinx_fpga_loader/Manifest.py @@ -0,0 +1,5 @@ +files = [ +"wb_xilinx_fpga_loader.vhd", +"xwb_xilinx_fpga_loader.vhd", +"xloader_registers_pkg.vhd", +"xloader_wb.vhd"]; diff --git a/modules/wishbone/wb_xilinx_fpga_loader/build_wb.sh b/modules/wishbone/wb_xilinx_fpga_loader/build_wb.sh new file mode 100755 index 0000000000000000000000000000000000000000..5d1d03f99cec294529db79e81a55757e4206493e --- /dev/null +++ b/modules/wishbone/wb_xilinx_fpga_loader/build_wb.sh @@ -0,0 +1,3 @@ +#!/bin/bash + +wbgen2 -V xloader_wb.vhd -H record -p xloader_registers_pkg.vhd -K ../../../sim/regs/xloader_regs.vh -s defines -C xloader_regs.h -D wb_xilinx_fpga_loader.html xloader_wb.wb \ No newline at end of file diff --git a/modules/wishbone/wb_xilinx_fpga_loader/wb_xilinx_fpga_loader.vhd b/modules/wishbone/wb_xilinx_fpga_loader/wb_xilinx_fpga_loader.vhd new file mode 100644 index 0000000000000000000000000000000000000000..77938c4611a6f70f8f27f795902c7534aa27244a --- /dev/null +++ b/modules/wishbone/wb_xilinx_fpga_loader/wb_xilinx_fpga_loader.vhd @@ -0,0 +1,363 @@ +------------------------------------------------------------------------------- +-- Title : Xilinx FPGA Loader +-- Project : General Cores Library +------------------------------------------------------------------------------- +-- File : wb_xilinx_fpga_loader.vhd +-- Author : Tomasz WÅ‚ostowski +-- Company : CERN BE-CO-HT +-- Created : 2012-01-30 +-- Last update : 2012-01-30 +-- Platform : FPGA-generic +-- Standard : VHDL '93 +-- Dependencies : xldr_wbgen2_pkg, gencores_pkg, wbgen2_pkg, gc_sync_ffs +-- xloader_wb, wb_slave_adapter, wishbone_pkg +------------------------------------------------------------------------------- +-- Description: Wishbone compatible Xilinx serial port bitstream loader. +------------------------------------------------------------------------------- +-- +-- Copyright (c) 2012 CERN +-- +-- This source file is free software; you can redistribute it +-- and/or modify it under the terms of the GNU Lesser General +-- Public License as published by the Free Software Foundation; +-- either version 2.1 of the License, or (at your option) any +-- later version. +-- +-- This source is distributed in the hope that it will be +-- useful, but WITHOUT ANY WARRANTY; without even the implied +-- warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +-- PURPOSE. See the GNU Lesser General Public License for more +-- details. +-- +-- You should have received a copy of the GNU Lesser General +-- Public License along with this source; if not, download it +-- from http://www.gnu.org/licenses/lgpl-2.1.html +-- +------------------------------------------------------------------------------- +-- Revisions : +-- Date Version Author Description +-- 2012-01-30 1.0 twlostow Created +------------------------------------------------------------------------------- + +library ieee; +use ieee.STD_LOGIC_1164.all; +use ieee.numeric_std.all; + +use work.gencores_pkg.all; +use work.wishbone_pkg.all; +use work.xldr_wbgen2_pkg.all; + +entity wb_xilinx_fpga_loader is + generic( + g_interface_mode : t_wishbone_interface_mode := CLASSIC; + g_address_granularity : t_wishbone_address_granularity := WORD + ); + port ( +-- system clock + clk_sys_i : in std_logic; +-- synchronous reset, active LOW + rst_n_i : in std_logic; + +-- Wishbone bus + wb_cyc_i : in std_logic; + wb_stb_i : in std_logic; + wb_we_i : in std_logic; + wb_adr_i : in std_logic_vector(c_wishbone_address_width - 1 downto 0); + wb_sel_i : in std_logic_vector((c_wishbone_data_width + 7) / 8 - 1 downto 0); + wb_dat_i : in std_logic_vector(c_wishbone_data_width-1 downto 0); + wb_dat_o : out std_logic_vector(c_wishbone_data_width-1 downto 0); + wb_ack_o : out std_logic; + wb_stall_o : out std_logic; + +-- Configuration clock (to pin CCLK) + xlx_cclk_o : out std_logic := '0'; +-- Data output (to pin D0/DIN) + xlx_din_o : out std_logic; +-- Program enable pin (active low, to pin PROG_B) + xlx_program_b_o : out std_logic := '1'; +-- Init ready pin (active low, to pin INIT_B) + xlx_init_b_i : in std_logic; +-- Configuration done pin (to pin DONE) + xlx_done_i : in std_logic; +-- FPGA suspend pin + xlx_suspend_o : out std_logic; + +-- FPGA mode select pin. Connect to M1..M0 pins of the FPGA or leave open if +-- the pins are hardwired on the PCB + xlx_m_o : out std_logic_vector(1 downto 0) + ); + +end wb_xilinx_fpga_loader; + +architecture behavioral of wb_xilinx_fpga_loader is + + component xloader_wb + port ( + rst_n_i : in std_logic; + wb_clk_i : in std_logic; + wb_addr_i : in std_logic_vector(1 downto 0); + wb_data_i : in std_logic_vector(31 downto 0); + wb_data_o : out std_logic_vector(31 downto 0); + wb_cyc_i : in std_logic; + wb_sel_i : in std_logic_vector(3 downto 0); + wb_stb_i : in std_logic; + wb_we_i : in std_logic; + wb_ack_o : out std_logic; + regs_i : in t_xldr_in_registers; + regs_o : out t_xldr_out_registers); + end component; + + type t_xloader_state is (IDLE, WAIT_INIT, WAIT_INIT2, READ_FIFO, READ_FIFO2, OUTPUT_BIT, CLOCK_EDGE, WAIT_DONE, EXTEND_PROG); + + signal state : t_xloader_state; + signal clk_div : unsigned(6 downto 0); + signal tick : std_logic; + signal init_b_synced : std_logic; + signal done_synced : std_logic; + signal timeout_counter : unsigned(20 downto 0); + signal wb_in : t_wishbone_master_out; + signal wb_out : t_wishbone_master_in; + signal regs_in : t_xldr_out_registers; + signal regs_out : t_xldr_in_registers; + + -- PROG_B assertion duration + constant c_MIN_PROG_DELAY : unsigned(timeout_counter'left downto 0) := to_unsigned(1000, timeout_counter'length); + + + -- PROG_B active to INIT_B active timeout + constant c_INIT_TIMEOUT : unsigned(timeout_counter'left downto 0) := to_unsigned(200000, timeout_counter'length); + + -- Last word written to DONE active timeout + constant c_DONE_TIMEOUT : unsigned(timeout_counter'left downto 0) := to_unsigned(200000, timeout_counter'length); + + signal d_data : std_logic_vector(31 downto 0); + signal d_size : std_logic_vector(1 downto 0); + signal d_last : std_logic; + + signal bit_counter : unsigned(4 downto 0); + +begin -- behavioral + + +-- Pipelined-classic adapter/converter + U_Adapter : wb_slave_adapter + generic map ( + g_master_use_struct => true, + g_master_mode => CLASSIC, + g_master_granularity => WORD, + g_slave_use_struct => false, + g_slave_mode => g_interface_mode, + g_slave_granularity => g_address_granularity) + port map ( + clk_sys_i => clk_sys_i, + rst_n_i => rst_n_i, + + sl_cyc_i => wb_cyc_i, + sl_stb_i => wb_stb_i, + sl_we_i => wb_we_i, + sl_adr_i => wb_adr_i, + sl_sel_i => wb_sel_i, + sl_dat_i => wb_dat_i, + sl_dat_o => wb_dat_o, + sl_ack_o => wb_ack_o, + sl_stall_o => wb_stall_o, + + master_i => wb_out, + master_o => wb_in); + + wb_out.err <= '0'; + wb_out.rty <= '0'; + wb_out.stall <= '0'; + wb_out.int <= '0'; + + xlx_m_o <= "11"; -- permamently select Passive serial + -- boot mode + + xlx_suspend_o <= '0'; -- suspend feature is not used + +-- Synchronization chains for async INIT_B and DONE inputs + U_Sync_INIT : gc_sync_ffs + generic map ( + g_sync_edge => "positive") + port map ( + clk_i => clk_sys_i, + rst_n_i => rst_n_i, + data_i => xlx_init_b_i, + synced_o => init_b_synced); + + U_Sync_DONE : gc_sync_ffs + generic map ( + g_sync_edge => "positive") + port map ( + clk_i => clk_sys_i, + rst_n_i => rst_n_i, + data_i => xlx_done_i, + synced_o => done_synced); + + -- Clock divider. Genrates a single-cycle pulse on "tick" signal every + -- CSR.CLKDIV system clock cycles. + p_divide_clock : process(clk_sys_i) + begin + if rising_edge(clk_sys_i) then + if rst_n_i = '0' then + clk_div <= (others => '0'); + tick <= '0'; + else + if(clk_div = unsigned(regs_in.csr_clkdiv_o)) then + tick <= '1'; + clk_div <= (others => '0'); + else + tick <= '0'; + clk_div <= clk_div + 1; + end if; + end if; + end if; + end process; + + + p_main_fsm : process(clk_sys_i) + begin + if rising_edge(clk_sys_i) then + if rst_n_i = '0' or regs_in.csr_swrst_o = '1' then + state <= IDLE; + xlx_program_b_o <= '1'; + xlx_cclk_o <= '0'; + xlx_din_o <= '0'; + timeout_counter <= (others => '0'); + + regs_out.csr_done_i <= '0'; + regs_out.csr_error_i <= '0'; + else + case state is + when IDLE => + + timeout_counter <= c_INIT_TIMEOUT; + if(regs_in.csr_start_o = '1') then + xlx_program_b_o <= '0'; + regs_out.csr_done_i <= '0'; + regs_out.csr_error_i <= '0'; + state <= EXTEND_PROG; + timeout_counter <= c_MIN_PROG_DELAY; + end if; + + when EXTEND_PROG => + timeout_counter <= timeout_counter-1; + + if(timeout_counter = 0) then + timeout_counter <= c_INIT_TIMEOUT; + state <= WAIT_INIT; + end if; + + when WAIT_INIT => + timeout_counter <= timeout_counter - 1; + + if(timeout_counter = 0) then + regs_out.csr_error_i <= '1'; + regs_out.csr_done_i <= '1'; + state <= IDLE; + end if; + + if (init_b_synced = '0') then + state <= WAIT_INIT2; + xlx_program_b_o <= '1'; + end if; + + when WAIT_INIT2 => + if (init_b_synced /= '0') then + state <= READ_FIFO; + end if; + + when READ_FIFO => + xlx_cclk_o <= '0'; + + if(regs_in.fifo_rd_empty_o = '0') then + state <= READ_FIFO2; + end if; + + when READ_FIFO2 => + + + -- handle byte swapping + if(regs_in.csr_msbf_o = '0') then + d_data(31 downto 24) <= regs_in.fifo_xdata_o(7 downto 0); + d_data(23 downto 16) <= regs_in.fifo_xdata_o(15 downto 8); + d_data(15 downto 8) <= regs_in.fifo_xdata_o(23 downto 16); + d_data(7 downto 0) <= regs_in.fifo_xdata_o(31 downto 24); -- little-endian + else + d_data <= regs_in.fifo_xdata_o; -- big-endian + end if; + + d_size <= regs_in.fifo_xsize_o; + d_last <= regs_in.fifo_xlast_o; + + if(tick = '1') then + state <= OUTPUT_BIT; + bit_counter <= unsigned(regs_in.fifo_xsize_o) & "111"; + end if; + + when OUTPUT_BIT => + if(tick = '1') then + xlx_din_o <= d_data(31); + xlx_cclk_o <= '0'; + d_data(d_data'left downto 1) <= d_data(d_data'left-1 downto 0); + state <= CLOCK_EDGE; + end if; + + when CLOCK_EDGE => + if(tick = '1') then + xlx_cclk_o <= '1'; + + bit_counter <= bit_counter - 1; + + if(bit_counter = 0) then + if(d_last = '1') then + state <= WAIT_DONE; + timeout_counter <= c_DONE_TIMEOUT; + else + state <= READ_FIFO; + end if; + else + state <= OUTPUT_BIT; + end if; + end if; + + + when WAIT_DONE => + if(done_synced = '1') then + state <= IDLE; + regs_out.csr_done_i <= '1'; + regs_out.csr_error_i <= '0'; + end if; + + timeout_counter <= timeout_counter - 1; + + if(timeout_counter = 0) then + state <= IDLE; + regs_out.csr_error_i <= '1'; + regs_out.csr_done_i <= '1'; + end if; + + end case; + end if; + end if; + end process; + + regs_out.csr_busy_i <= '0' when (state = IDLE) else '1'; + regs_out.fifo_rd_req_i <= '1' when ((regs_in.fifo_rd_empty_o = '0') and (state = IDLE or state = READ_FIFO)) else '0'; + + U_WB_SLAVE : xloader_wb + port map ( + rst_n_i => rst_n_i, + wb_clk_i => clk_sys_i, + wb_addr_i => wb_in.adr(1 downto 0), + wb_data_i => wb_in.dat(31 downto 0), + wb_data_o => wb_out.dat(31 downto 0), + wb_cyc_i => wb_in.cyc, + wb_sel_i => wb_in.sel(3 downto 0), + wb_stb_i => wb_in.stb, + wb_we_i => wb_in.we, + wb_ack_o => wb_out.ack, + regs_o => regs_in, + regs_i => regs_out); + +end behavioral; diff --git a/modules/wishbone/wb_xilinx_fpga_loader/xloader_registers_pkg.vhd b/modules/wishbone/wb_xilinx_fpga_loader/xloader_registers_pkg.vhd new file mode 100644 index 0000000000000000000000000000000000000000..3dfd987462924cfe9df9aed9a58336a9776d0658 --- /dev/null +++ b/modules/wishbone/wb_xilinx_fpga_loader/xloader_registers_pkg.vhd @@ -0,0 +1,84 @@ +--------------------------------------------------------------------------------------- +-- Title : Wishbone slave core for Xilinx FPGA loader +--------------------------------------------------------------------------------------- +-- File : xloader_registers_pkg.vhd +-- Author : auto-generated by wbgen2 from xloader_wb.wb +-- Created : Tue Jan 31 15:31:31 2012 +-- Standard : VHDL'87 +--------------------------------------------------------------------------------------- +-- THIS FILE WAS GENERATED BY wbgen2 FROM SOURCE FILE xloader_wb.wb +-- DO NOT HAND-EDIT UNLESS IT'S ABSOLUTELY NECESSARY! +--------------------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; +use work.wbgen2_pkg.all; + +package xldr_wbgen2_pkg is + + + -- Input registers (user design -> WB slave) + + type t_xldr_in_registers is record + csr_done_i : std_logic; + csr_error_i : std_logic; + csr_busy_i : std_logic; + fifo_rd_req_i : std_logic; + end record; + + constant c_xldr_in_registers_init_value: t_xldr_in_registers := ( + csr_done_i => '0', + csr_error_i => '0', + csr_busy_i => '0', + fifo_rd_req_i => '0' + ); + + -- Output registers (WB slave -> user design) + + type t_xldr_out_registers is record + csr_start_o : std_logic; + csr_msbf_o : std_logic; + csr_swrst_o : std_logic; + csr_clkdiv_o : std_logic_vector(5 downto 0); + fifo_rd_full_o : std_logic; + fifo_rd_empty_o : std_logic; + fifo_xsize_o : std_logic_vector(1 downto 0); + fifo_xlast_o : std_logic; + fifo_xdata_o : std_logic_vector(31 downto 0); + end record; + + constant c_xldr_out_registers_init_value: t_xldr_out_registers := ( + csr_start_o => '0', + csr_msbf_o => '0', + csr_swrst_o => '0', + csr_clkdiv_o => (others => '0'), + fifo_rd_full_o => '0', + fifo_rd_empty_o => '0', + fifo_xsize_o => (others => '0'), + fifo_xlast_o => '0', + fifo_xdata_o => (others => '0') + ); + function "or" (left, right: t_xldr_in_registers) return t_xldr_in_registers; + function f_x_to_zero (x:std_logic) return std_logic; +end package; + +package body xldr_wbgen2_pkg is +function f_x_to_zero (x:std_logic) return std_logic is +begin +if(x = 'X' or x = 'U') then +return '0'; +else +return x; +end if; +end function; +function "or" (left, right: t_xldr_in_registers) return t_xldr_in_registers is +variable tmp: t_xldr_in_registers; +begin +tmp.csr_done_i := left.csr_done_i or right.csr_done_i; +tmp.csr_error_i := left.csr_error_i or right.csr_error_i; +tmp.csr_busy_i := left.csr_busy_i or right.csr_busy_i; +tmp.fifo_rd_req_i := left.fifo_rd_req_i or right.fifo_rd_req_i; +return tmp; +end function; +end package body; diff --git a/modules/wishbone/wb_xilinx_fpga_loader/xloader_wb.vhd b/modules/wishbone/wb_xilinx_fpga_loader/xloader_wb.vhd new file mode 100644 index 0000000000000000000000000000000000000000..aab91d07bd5ec82988c4bb804f96df3766571b6c --- /dev/null +++ b/modules/wishbone/wb_xilinx_fpga_loader/xloader_wb.vhd @@ -0,0 +1,329 @@ +--------------------------------------------------------------------------------------- +-- Title : Wishbone slave core for Xilinx FPGA loader +--------------------------------------------------------------------------------------- +-- File : xloader_wb.vhd +-- Author : auto-generated by wbgen2 from xloader_wb.wb +-- Created : Tue Jan 31 15:31:31 2012 +-- Standard : VHDL'87 +--------------------------------------------------------------------------------------- +-- THIS FILE WAS GENERATED BY wbgen2 FROM SOURCE FILE xloader_wb.wb +-- DO NOT HAND-EDIT UNLESS IT'S ABSOLUTELY NECESSARY! +--------------------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; +use work.wbgen2_pkg.all; + +use work.xldr_wbgen2_pkg.all; + + +entity xloader_wb is + port ( + rst_n_i : in std_logic; + wb_clk_i : in std_logic; + wb_addr_i : in std_logic_vector(1 downto 0); + wb_data_i : in std_logic_vector(31 downto 0); + wb_data_o : out std_logic_vector(31 downto 0); + wb_cyc_i : in std_logic; + wb_sel_i : in std_logic_vector(3 downto 0); + wb_stb_i : in std_logic; + wb_we_i : in std_logic; + wb_ack_o : out std_logic; + regs_i : in t_xldr_in_registers; + regs_o : out t_xldr_out_registers + ); +end xloader_wb; + +architecture syn of xloader_wb is + +signal xldr_csr_start_dly0 : std_logic ; +signal xldr_csr_start_int : std_logic ; +signal xldr_csr_msbf_int : std_logic ; +signal xldr_csr_swrst_dly0 : std_logic ; +signal xldr_csr_swrst_int : std_logic ; +signal xldr_csr_clkdiv_int : std_logic_vector(5 downto 0); +signal xldr_fifo_in_int : std_logic_vector(34 downto 0); +signal xldr_fifo_out_int : std_logic_vector(34 downto 0); +signal xldr_fifo_wrreq_int : std_logic ; +signal xldr_fifo_full_int : std_logic ; +signal xldr_fifo_empty_int : std_logic ; +signal xldr_fifo_usedw_int : std_logic_vector(7 downto 0); +signal ack_sreg : std_logic_vector(9 downto 0); +signal rddata_reg : std_logic_vector(31 downto 0); +signal wrdata_reg : std_logic_vector(31 downto 0); +signal bwsel_reg : std_logic_vector(3 downto 0); +signal rwaddr_reg : std_logic_vector(1 downto 0); +signal ack_in_progress : std_logic ; +signal wr_int : std_logic ; +signal rd_int : std_logic ; +signal bus_clock_int : std_logic ; +signal allones : std_logic_vector(31 downto 0); +signal allzeros : std_logic_vector(31 downto 0); + +begin +-- Some internal signals assignments. For (foreseen) compatibility with other bus standards. + wrdata_reg <= wb_data_i; + bwsel_reg <= wb_sel_i; + bus_clock_int <= wb_clk_i; + rd_int <= wb_cyc_i and (wb_stb_i and (not wb_we_i)); + wr_int <= wb_cyc_i and (wb_stb_i and wb_we_i); + allones <= (others => '1'); + allzeros <= (others => '0'); +-- +-- Main register bank access process. + process (bus_clock_int, rst_n_i) + begin + if (rst_n_i = '0') then + ack_sreg <= "0000000000"; + ack_in_progress <= '0'; + rddata_reg <= "00000000000000000000000000000000"; + xldr_csr_start_int <= '0'; + xldr_csr_msbf_int <= '0'; + xldr_csr_swrst_int <= '0'; + xldr_csr_clkdiv_int <= "000000"; + xldr_fifo_wrreq_int <= '0'; + elsif rising_edge(bus_clock_int) then +-- advance the ACK generator shift register + ack_sreg(8 downto 0) <= ack_sreg(9 downto 1); + ack_sreg(9) <= '0'; + if (ack_in_progress = '1') then + if (ack_sreg(0) = '1') then + xldr_csr_start_int <= '0'; + xldr_csr_swrst_int <= '0'; + xldr_fifo_wrreq_int <= '0'; + ack_in_progress <= '0'; + else + end if; + else + if ((wb_cyc_i = '1') and (wb_stb_i = '1')) then + case rwaddr_reg(1 downto 0) is + when "00" => + if (wb_we_i = '1') then + xldr_csr_start_int <= wrdata_reg(0); + rddata_reg(0) <= 'X'; + rddata_reg(1) <= 'X'; + rddata_reg(2) <= 'X'; + rddata_reg(3) <= 'X'; + rddata_reg(4) <= 'X'; + xldr_csr_msbf_int <= wrdata_reg(4); + xldr_csr_swrst_int <= wrdata_reg(5); + rddata_reg(5) <= 'X'; + xldr_csr_clkdiv_int <= wrdata_reg(13 downto 8); + else + rddata_reg(0) <= 'X'; + rddata_reg(1) <= regs_i.csr_done_i; + rddata_reg(2) <= regs_i.csr_error_i; + rddata_reg(3) <= regs_i.csr_busy_i; + rddata_reg(4) <= xldr_csr_msbf_int; + rddata_reg(5) <= 'X'; + rddata_reg(13 downto 8) <= xldr_csr_clkdiv_int; + rddata_reg(6) <= 'X'; + rddata_reg(7) <= 'X'; + rddata_reg(14) <= 'X'; + rddata_reg(15) <= 'X'; + rddata_reg(16) <= 'X'; + rddata_reg(17) <= 'X'; + rddata_reg(18) <= 'X'; + rddata_reg(19) <= 'X'; + rddata_reg(20) <= 'X'; + rddata_reg(21) <= 'X'; + rddata_reg(22) <= 'X'; + rddata_reg(23) <= 'X'; + rddata_reg(24) <= 'X'; + rddata_reg(25) <= 'X'; + rddata_reg(26) <= 'X'; + rddata_reg(27) <= 'X'; + rddata_reg(28) <= 'X'; + rddata_reg(29) <= 'X'; + rddata_reg(30) <= 'X'; + rddata_reg(31) <= 'X'; + end if; + ack_sreg(2) <= '1'; + ack_in_progress <= '1'; + when "01" => + if (wb_we_i = '1') then + xldr_fifo_in_int(1 downto 0) <= wrdata_reg(1 downto 0); + xldr_fifo_in_int(2) <= wrdata_reg(2); + else + rddata_reg(0) <= 'X'; + rddata_reg(1) <= 'X'; + rddata_reg(2) <= 'X'; + rddata_reg(3) <= 'X'; + rddata_reg(4) <= 'X'; + rddata_reg(5) <= 'X'; + rddata_reg(6) <= 'X'; + rddata_reg(7) <= 'X'; + rddata_reg(8) <= 'X'; + rddata_reg(9) <= 'X'; + rddata_reg(10) <= 'X'; + rddata_reg(11) <= 'X'; + rddata_reg(12) <= 'X'; + rddata_reg(13) <= 'X'; + rddata_reg(14) <= 'X'; + rddata_reg(15) <= 'X'; + rddata_reg(16) <= 'X'; + rddata_reg(17) <= 'X'; + rddata_reg(18) <= 'X'; + rddata_reg(19) <= 'X'; + rddata_reg(20) <= 'X'; + rddata_reg(21) <= 'X'; + rddata_reg(22) <= 'X'; + rddata_reg(23) <= 'X'; + rddata_reg(24) <= 'X'; + rddata_reg(25) <= 'X'; + rddata_reg(26) <= 'X'; + rddata_reg(27) <= 'X'; + rddata_reg(28) <= 'X'; + rddata_reg(29) <= 'X'; + rddata_reg(30) <= 'X'; + rddata_reg(31) <= 'X'; + end if; + ack_sreg(0) <= '1'; + ack_in_progress <= '1'; + when "10" => + if (wb_we_i = '1') then + xldr_fifo_in_int(34 downto 3) <= wrdata_reg(31 downto 0); + xldr_fifo_wrreq_int <= '1'; + else + rddata_reg(0) <= 'X'; + rddata_reg(1) <= 'X'; + rddata_reg(2) <= 'X'; + rddata_reg(3) <= 'X'; + rddata_reg(4) <= 'X'; + rddata_reg(5) <= 'X'; + rddata_reg(6) <= 'X'; + rddata_reg(7) <= 'X'; + rddata_reg(8) <= 'X'; + rddata_reg(9) <= 'X'; + rddata_reg(10) <= 'X'; + rddata_reg(11) <= 'X'; + rddata_reg(12) <= 'X'; + rddata_reg(13) <= 'X'; + rddata_reg(14) <= 'X'; + rddata_reg(15) <= 'X'; + rddata_reg(16) <= 'X'; + rddata_reg(17) <= 'X'; + rddata_reg(18) <= 'X'; + rddata_reg(19) <= 'X'; + rddata_reg(20) <= 'X'; + rddata_reg(21) <= 'X'; + rddata_reg(22) <= 'X'; + rddata_reg(23) <= 'X'; + rddata_reg(24) <= 'X'; + rddata_reg(25) <= 'X'; + rddata_reg(26) <= 'X'; + rddata_reg(27) <= 'X'; + rddata_reg(28) <= 'X'; + rddata_reg(29) <= 'X'; + rddata_reg(30) <= 'X'; + rddata_reg(31) <= 'X'; + end if; + ack_sreg(0) <= '1'; + ack_in_progress <= '1'; + when "11" => + if (wb_we_i = '1') then + else + rddata_reg(16) <= xldr_fifo_full_int; + rddata_reg(17) <= xldr_fifo_empty_int; + rddata_reg(7 downto 0) <= xldr_fifo_usedw_int; + rddata_reg(8) <= 'X'; + rddata_reg(9) <= 'X'; + rddata_reg(10) <= 'X'; + rddata_reg(11) <= 'X'; + rddata_reg(12) <= 'X'; + rddata_reg(13) <= 'X'; + rddata_reg(14) <= 'X'; + rddata_reg(15) <= 'X'; + rddata_reg(18) <= 'X'; + rddata_reg(19) <= 'X'; + rddata_reg(20) <= 'X'; + rddata_reg(21) <= 'X'; + rddata_reg(22) <= 'X'; + rddata_reg(23) <= 'X'; + rddata_reg(24) <= 'X'; + rddata_reg(25) <= 'X'; + rddata_reg(26) <= 'X'; + rddata_reg(27) <= 'X'; + rddata_reg(28) <= 'X'; + rddata_reg(29) <= 'X'; + rddata_reg(30) <= 'X'; + rddata_reg(31) <= 'X'; + end if; + ack_sreg(0) <= '1'; + ack_in_progress <= '1'; + when others => +-- prevent the slave from hanging the bus on invalid address + ack_in_progress <= '1'; + ack_sreg(0) <= '1'; + end case; + end if; + end if; + end if; + end process; + + +-- Drive the data output bus + wb_data_o <= rddata_reg; +-- Start configuration + process (bus_clock_int, rst_n_i) + begin + if (rst_n_i = '0') then + xldr_csr_start_dly0 <= '0'; + regs_o.csr_start_o <= '0'; + elsif rising_edge(bus_clock_int) then + xldr_csr_start_dly0 <= xldr_csr_start_int; + regs_o.csr_start_o <= xldr_csr_start_int and (not xldr_csr_start_dly0); + end if; + end process; + + +-- Configuration done +-- Configuration error +-- Loader busy +-- Byte order select + regs_o.csr_msbf_o <= xldr_csr_msbf_int; +-- Software resest + process (bus_clock_int, rst_n_i) + begin + if (rst_n_i = '0') then + xldr_csr_swrst_dly0 <= '0'; + regs_o.csr_swrst_o <= '0'; + elsif rising_edge(bus_clock_int) then + xldr_csr_swrst_dly0 <= xldr_csr_swrst_int; + regs_o.csr_swrst_o <= xldr_csr_swrst_int and (not xldr_csr_swrst_dly0); + end if; + end process; + + +-- Serial clock divider + regs_o.csr_clkdiv_o <= xldr_csr_clkdiv_int; +-- extra code for reg/fifo/mem: Bitstream FIFO + regs_o.fifo_xsize_o <= xldr_fifo_out_int(1 downto 0); + regs_o.fifo_xlast_o <= xldr_fifo_out_int(2); + regs_o.fifo_xdata_o <= xldr_fifo_out_int(34 downto 3); + xldr_fifo_INST : wbgen2_fifo_sync + generic map ( + g_size => 256, + g_width => 35, + g_usedw_size => 8 + ) + port map ( + rd_req_i => regs_i.fifo_rd_req_i, + rd_full_o => regs_o.fifo_rd_full_o, + rd_empty_o => regs_o.fifo_rd_empty_o, + wr_full_o => xldr_fifo_full_int, + wr_empty_o => xldr_fifo_empty_int, + wr_usedw_o => xldr_fifo_usedw_int, + wr_req_i => xldr_fifo_wrreq_int, + clk_i => bus_clock_int, + wr_data_i => xldr_fifo_in_int, + rd_data_o => xldr_fifo_out_int + ); + +-- extra code for reg/fifo/mem: FIFO 'Bitstream FIFO' data input register 0 +-- extra code for reg/fifo/mem: FIFO 'Bitstream FIFO' data input register 1 + rwaddr_reg <= wb_addr_i; +-- ACK signal generation. Just pass the LSB of ACK counter. + wb_ack_o <= ack_sreg(0); +end syn; diff --git a/modules/wishbone/wb_xilinx_fpga_loader/xloader_wb.wb b/modules/wishbone/wb_xilinx_fpga_loader/xloader_wb.wb new file mode 100644 index 0000000000000000000000000000000000000000..f6b3c7b8b51979cd214f768fb68429587ccd850f --- /dev/null +++ b/modules/wishbone/wb_xilinx_fpga_loader/xloader_wb.wb @@ -0,0 +1,152 @@ +-- -*- Mode: LUA; tab-width: 2 -*- + +------------------------------------------------------------------------------- +-- Title : Xilinx FPGA Loader +-- Project : General Cores Library +------------------------------------------------------------------------------- +-- File : xloader_wb.wb +-- Author : Tomasz WÅ‚ostowski +-- Company : CERN BE-CO-HT +-- Created : 2012-01-30 +-- Last update : 2012-01-30 +-- Standard : Lua 5.1 +-- Dependencies : wbgen2 ver 0.6+ +------------------------------------------------------------------------------- +-- Description: Wishbone register block definition for Xilinx FPGA loader core. +------------------------------------------------------------------------------- +-- +-- Copyright (c) 2012 CERN +-- +-- This source file is free software; you can redistribute it +-- and/or modify it under the terms of the GNU Lesser General +-- Public License as published by the Free Software Foundation; +-- either version 2.1 of the License, or (at your option) any +-- later version. +-- +-- This source is distributed in the hope that it will be +-- useful, but WITHOUT ANY WARRANTY; without even the implied +-- warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +-- PURPOSE. See the GNU Lesser General Public License for more +-- details. +-- +-- You should have received a copy of the GNU Lesser General +-- Public License along with this source; if not, download it +-- from http://www.gnu.org/licenses/lgpl-2.1.html +-- +------------------------------------------------------------------------------- +-- Revisions : +-- Date Version Author Description +-- 2012-01-30 1.0 twlostow Created +------------------------------------------------------------------------------- + +peripheral { + name = "Xilinx FPGA loader"; + description = "A very simple serial firmware loader for Xilinx FPGAs. Programs the FPGA using serial slave mode method"; + prefix = "xldr"; + hdl_entity = "xloader_wb"; + + reg { + name = "Control/status register"; + prefix = "CSR"; + + field { + name = "Start configuration"; + description = "write 1: starts the configuration process.\ + write 0: no effect"; + + prefix = "START"; + type = MONOSTABLE; + }; + + field { + name = "Configuration done"; + description = "read 1: the bitstream has been loaded\ + read 0: configuration still in progress"; + prefix = "DONE"; + type = BIT; + access_bus = READ_ONLY; + access_dev = WRITE_ONLY; + }; + + field { + name = "Configuration error"; + description = "read 1: an error occured during the configuration (DONE/INIT_B timeout)\ + read 0: configuration was successful"; + prefix = "ERROR"; + type = BIT; + access_bus = READ_ONLY; + access_dev = WRITE_ONLY; + }; + + field { + name = "Loader busy"; + prefix = "BUSY"; + description = "read 1: the loader is busy (can't start configuration yet)\ + read 0: the loader is ready to re-configure the FPGA"; + type = BIT; + access_bus = READ_ONLY; + access_dev = WRITE_ONLY; + }; + + field { + name = "Byte order select"; + description = "write 1: MSB first (big endian host)\ + write 0: LSB first (little endian host)"; + prefix = "MSBF"; + type = BIT; + access_bus = READ_WRITE; + access_dev = READ_ONLY; + }; + + field { + name = "Software resest"; + description = "write 1: resets the loader core\ + write 0: no effect"; + prefix = "SWRST"; + type = MONOSTABLE; + }; + + field { + name = "Serial clock divider"; + description = "CCLK division ratio. CCLK frequency = F_sysclk / 2 / (CLKDIV + 1)"; + prefix = "CLKDIV"; + type = SLV; + align = 8; + size = 6; + access_bus = READ_WRITE; + access_dev =READ_ONLY; + }; + }; + + fifo_reg { + size = 256; + direction = BUS_TO_CORE; + prefix = "FIFO"; + name = "Bitstream FIFO"; + flags_bus = {FIFO_FULL, FIFO_EMPTY, FIFO_COUNT}; + flags_dev = {FIFO_FULL, FIFO_EMPTY}; + + field { + description = "Number of bytes to send (0 = 1 byte .. 3 = full 32-bit word)"; + name = "Entry size"; + prefix = "XSIZE"; + size = 2; + type = SLV; + }; + + field { + description = "write 1: indicates the last word to be written to the FPGA"; + name = "Last xfer"; + prefix = "XLAST"; + type = BIT; + }; + + field { + description = "Subsequent words of the bitstream"; + name = "Data"; + prefix = "XDATA"; + size = 32; + type = SLV; + }; + }; +}; \ No newline at end of file diff --git a/modules/wishbone/wb_xilinx_fpga_loader/xwb_xilinx_fpga_loader.vhd b/modules/wishbone/wb_xilinx_fpga_loader/xwb_xilinx_fpga_loader.vhd new file mode 100644 index 0000000000000000000000000000000000000000..539b4d36f2d3f8d8d17fef7a0edef5a5be222a35 --- /dev/null +++ b/modules/wishbone/wb_xilinx_fpga_loader/xwb_xilinx_fpga_loader.vhd @@ -0,0 +1,131 @@ +------------------------------------------------------------------------------- +-- Title : Xilinx FPGA Loader +-- Project : General Cores Library +------------------------------------------------------------------------------- +-- File : xwb_xilinx_fpga_loader.vhd +-- Author : Tomasz WÅ‚ostowski +-- Company : CERN BE-CO-HT +-- Created : 2012-01-30 +-- Last update : 2012-01-30 +-- Platform : FPGA-generic +-- Standard : VHDL '93 +-- Dependencies : wishbone_pkg, wb_xilinx_fpga_loader +------------------------------------------------------------------------------- +-- Description: Wishbone compatible Xilinx serial port bitstream loader +-- (structized ports wrapper) +------------------------------------------------------------------------------- +-- +-- Copyright (c) 2012 CERN +-- +-- This source file is free software; you can redistribute it +-- and/or modify it under the terms of the GNU Lesser General +-- Public License as published by the Free Software Foundation; +-- either version 2.1 of the License, or (at your option) any +-- later version. +-- +-- This source is distributed in the hope that it will be +-- useful, but WITHOUT ANY WARRANTY; without even the implied +-- warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +-- PURPOSE. See the GNU Lesser General Public License for more +-- details. +-- +-- You should have received a copy of the GNU Lesser General +-- Public License along with this source; if not, download it +-- from http://www.gnu.org/licenses/lgpl-2.1.html +-- +------------------------------------------------------------------------------- +-- Revisions : +-- Date Version Author Description +-- 2012-01-30 1.0 twlostow Created +------------------------------------------------------------------------------- + +library ieee; +use ieee.STD_LOGIC_1164.all; + +use work.wishbone_pkg.all; + +entity xwb_xilinx_fpga_loader is + + generic ( + g_interface_mode : t_wishbone_interface_mode := CLASSIC; + g_address_granularity : t_wishbone_address_granularity := WORD + ); + + port ( + clk_sys_i : in std_logic; + rst_n_i : in std_logic; + slave_i : in t_wishbone_slave_in; + slave_o : out t_wishbone_slave_out; + desc_o : out t_wishbone_device_descriptor; + + xlx_cclk_o : out std_logic := '0'; + xlx_din_o : out std_logic; + xlx_program_b_o : out std_logic := '1'; + xlx_init_b_i : in std_logic; + xlx_done_i : in std_logic; + xlx_suspend_o : out std_logic; + + xlx_m_o : out std_logic_vector(1 downto 0) + ); + +end xwb_xilinx_fpga_loader; + +architecture rtl of xwb_xilinx_fpga_loader is + + component wb_xilinx_fpga_loader + generic ( + g_interface_mode : t_wishbone_interface_mode; + g_address_granularity : t_wishbone_address_granularity); + port ( + clk_sys_i : in std_logic; + rst_n_i : in std_logic; + wb_cyc_i : in std_logic; + wb_stb_i : in std_logic; + wb_we_i : in std_logic; + wb_adr_i : in std_logic_vector(c_wishbone_address_width - 1 downto 0); + wb_sel_i : in std_logic_vector((c_wishbone_data_width + 7) / 8 - 1 downto 0); + wb_dat_i : in std_logic_vector(c_wishbone_data_width-1 downto 0); + wb_dat_o : out std_logic_vector(c_wishbone_data_width-1 downto 0); + wb_ack_o : out std_logic; + wb_stall_o : out std_logic; + xlx_cclk_o : out std_logic := '0'; + xlx_din_o : out std_logic; + xlx_program_b_o : out std_logic := '1'; + xlx_init_b_i : in std_logic; + xlx_done_i : in std_logic; + xlx_suspend_o : out std_logic; + xlx_m_o : out std_logic_vector(1 downto 0)); + end component; + +begin -- rtl + + + U_Wrapped_XLDR : wb_xilinx_fpga_loader + generic map ( + g_address_granularity => g_address_granularity, + g_interface_mode => g_interface_mode) + port map ( + clk_sys_i => clk_sys_i, + rst_n_i => rst_n_i, + wb_cyc_i => slave_i.cyc, + wb_stb_i => slave_i.stb, + wb_we_i => slave_i.we, + wb_adr_i => slave_i.adr, + wb_sel_i => slave_i.sel, + wb_dat_i => slave_i.dat, + wb_dat_o => slave_o.dat, + wb_ack_o => slave_o.ack, + wb_stall_o => slave_o.stall, + + xlx_cclk_o => xlx_cclk_o, + xlx_din_o => xlx_din_o, + xlx_program_b_o => xlx_program_b_o, + xlx_init_b_i => xlx_init_b_i, + xlx_done_i => xlx_done_i, + xlx_suspend_o => xlx_suspend_o, + xlx_m_o => xlx_m_o); + + slave_o.int <= '0'; + slave_o.err <= '0'; + slave_o.rty <= '0'; +end rtl; diff --git a/modules/wishbone/wbgen2/wbgen2_fifo_async.vhd b/modules/wishbone/wbgen2/wbgen2_fifo_async.vhd index 59357942780fff92bcbc07fbce45652e84dc6225..3fda6af68f1bd5db8a1e7102e9bded7c98b0d368 100644 --- a/modules/wishbone/wbgen2/wbgen2_fifo_async.vhd +++ b/modules/wishbone/wbgen2/wbgen2_fifo_async.vhd @@ -13,6 +13,8 @@ entity wbgen2_fifo_async is port ( + rst_n_i : in std_logic := '1'; + rd_clk_i : in std_logic; rd_req_i : in std_logic; rd_data_o : out std_logic_vector(g_width-1 downto 0); @@ -29,7 +31,7 @@ entity wbgen2_fifo_async is wr_empty_o : out std_logic; wr_full_o : out std_logic; wr_usedw_o : out std_logic_vector(g_usedw_size -1 downto 0) - ); + ); end wbgen2_fifo_async; architecture rtl of wbgen2_fifo_async is @@ -73,7 +75,7 @@ architecture rtl of wbgen2_fifo_async is begin - wrapped_fifo: generic_async_fifo + wrapped_fifo : generic_async_fifo generic map ( g_data_width => g_width, g_size => g_size, @@ -91,7 +93,7 @@ begin g_almost_empty_threshold => 0, g_almost_full_threshold => 0) port map ( - rst_n_i => '1', + rst_n_i => rst_n_i, clk_wr_i => wr_clk_i, d_i => wr_data_i, we_i => wr_req_i, @@ -108,5 +110,5 @@ begin rd_almost_empty_o => open, rd_almost_full_o => open, rd_count_o => rd_usedw_o); - + end rtl; diff --git a/modules/wishbone/wbgen2/wbgen2_fifo_sync.vhd b/modules/wishbone/wbgen2/wbgen2_fifo_sync.vhd index 1641280eb982484eb34cee633e5e6629bbdbe5a1..8b0985068bb574011df6741729dea378954dd537 100644 --- a/modules/wishbone/wbgen2/wbgen2_fifo_sync.vhd +++ b/modules/wishbone/wbgen2/wbgen2_fifo_sync.vhd @@ -13,7 +13,10 @@ entity wbgen2_fifo_sync is port ( + clk_i : in std_logic; + rst_n_i : in std_logic := '1'; + wr_data_i : in std_logic_vector(g_width-1 downto 0); wr_req_i : in std_logic; @@ -88,7 +91,7 @@ begin g_with_almost_full => false, g_with_count => true) port map ( - rst_n_i => '1', + rst_n_i => rst_n_i, clk_i => clk_i, d_i => wr_data_i, we_i => wr_req_i, diff --git a/modules/wishbone/wbgen2/wbgen2_pkg.vhd b/modules/wishbone/wbgen2/wbgen2_pkg.vhd index 0269919585d8745d55e5b2324759a7188f66f081..18dc0a47b4ab595d832e81a3af4a507beef7f28c 100644 --- a/modules/wishbone/wbgen2/wbgen2_pkg.vhd +++ b/modules/wishbone/wbgen2/wbgen2_pkg.vhd @@ -28,7 +28,7 @@ package wbgen2_pkg is wr_b_i : in std_logic); end component; - + component wbgen2_eic generic ( g_num_interrupts : natural; @@ -86,6 +86,7 @@ package wbgen2_pkg is g_width : integer; g_usedw_size : integer); port ( + rst_n_i : in std_logic := '1'; rd_clk_i : in std_logic; rd_req_i : in std_logic; rd_data_o : out std_logic_vector(g_width-1 downto 0); @@ -108,6 +109,7 @@ package wbgen2_pkg is g_usedw_size : integer); port ( clk_i : in std_logic; + rst_n_i : in std_logic := '1'; wr_data_i : in std_logic_vector(g_width-1 downto 0); wr_req_i : in std_logic; rd_data_o : out std_logic_vector(g_width-1 downto 0); diff --git a/modules/wishbone/wishbone_pkg.vhd b/modules/wishbone/wishbone_pkg.vhd index 8985a1ef49dc8ae4c7b5854019abf15b99c64194..4c773b9adeb9f7d428b91e7cd435bf1e9608e75a 100644 --- a/modules/wishbone/wishbone_pkg.vhd +++ b/modules/wishbone/wishbone_pkg.vhd @@ -4,6 +4,7 @@ use ieee.std_logic_1164.all; use ieee.numeric_std.all; library work; +use work.genram_pkg.all; package wishbone_pkg is @@ -49,7 +50,7 @@ package wishbone_pkg is - type t_wishbone_address_array is array(integer range <>) of t_wishbone_address; + type t_wishbone_address_array is array(natural range <>) of t_wishbone_address; type t_wishbone_master_out_array is array (natural range <>) of t_wishbone_master_out; type t_wishbone_slave_out_array is array (natural range <>) of t_wishbone_slave_out; type t_wishbone_master_in_array is array (natural range <>) of t_wishbone_master_in; @@ -63,10 +64,41 @@ package wishbone_pkg is constant cc_dummy_sel : std_logic_vector(c_wishbone_data_width/8-1 downto 0) := (others => 'X'); constant cc_dummy_slave_in : t_wishbone_slave_in := - ('X', 'X', cc_dummy_address, cc_dummy_sel, 'X', cc_dummy_data); + ('0', 'X', cc_dummy_address, cc_dummy_sel, 'X', cc_dummy_data); + constant cc_dummy_master_out : t_wishbone_master_out := cc_dummy_slave_in; + + -- Dangerous! Will stall a bus. constant cc_dummy_slave_out : t_wishbone_slave_out := ('X', 'X', 'X', 'X', 'X', cc_dummy_data); + constant cc_dummy_master_in : t_wishbone_master_in := cc_dummy_slave_out; + -- A generally useful function. + function f_ceil_log2(x : natural) return natural; + +------------------------------------------------------------------------------ +-- SDWB declaration +------------------------------------------------------------------------------ + constant c_sdwb_device_length : natural := 512; -- bits + type t_sdwb_device is record + wbd_begin : unsigned(63 downto 0); + wbd_end : unsigned(63 downto 0); + sdwb_child : unsigned(63 downto 0); + wbd_flags : std_logic_vector(7 downto 0); + wbd_width : std_logic_vector(7 downto 0); + abi_ver_major : unsigned(7 downto 0); + abi_ver_minor : unsigned(7 downto 0); + abi_class : std_logic_vector(31 downto 0); + dev_vendor : std_logic_vector(31 downto 0); + dev_device : std_logic_vector(31 downto 0); + dev_version : std_logic_vector(31 downto 0); + dev_date : std_logic_vector(31 downto 0); + description : string(1 to 16); + end record t_sdwb_device; + type t_sdwb_device_array is array(natural range <>) of t_sdwb_device; + + -- Used to configure a device at a certain address + function f_sdwb_set_address(device : t_sdwb_device; address : t_wishbone_address) + return t_sdwb_device; ------------------------------------------------------------------------------ -- Components declaration @@ -179,22 +211,111 @@ package wishbone_pkg is generic ( g_num_masters : integer; g_num_slaves : integer; - g_registered : boolean); + g_registered : boolean; + g_address : t_wishbone_address_array; + g_mask : t_wishbone_address_array); + port ( + clk_sys_i : in std_logic; + rst_n_i : in std_logic; + slave_i : in t_wishbone_slave_in_array(g_num_masters-1 downto 0); + slave_o : out t_wishbone_slave_out_array(g_num_masters-1 downto 0); + master_i : in t_wishbone_master_in_array(g_num_slaves-1 downto 0); + master_o : out t_wishbone_master_out_array(g_num_slaves-1 downto 0)); + end component; + + -- Use the f_xwb_bridge_*_sdwb to bridge a crossbar to another + function f_xwb_bridge_manual_sdwb( -- take a manual bus size + g_bus_end : t_wishbone_address; + g_sdwb_addr : t_wishbone_address) return t_sdwb_device; + + function f_xwb_bridge_layout_sdwb( -- determine bus size from layout + g_wraparound : boolean := true; + g_layout : t_sdwb_device_array; + g_sdwb_addr : t_wishbone_address) return t_sdwb_device; + + component xwb_sdwb_crossbar + generic ( + g_num_masters : integer; + g_num_slaves : integer; + g_registered : boolean := false; + g_wraparound : boolean := true; + g_layout : t_sdwb_device_array; + g_sdwb_addr : t_wishbone_address); port ( clk_sys_i : in std_logic; rst_n_i : in std_logic; slave_i : in t_wishbone_slave_in_array(g_num_masters-1 downto 0); slave_o : out t_wishbone_slave_out_array(g_num_masters-1 downto 0); master_i : in t_wishbone_master_in_array(g_num_slaves-1 downto 0); - master_o : out t_wishbone_master_out_array(g_num_slaves-1 downto 0); - cfg_address_i : in t_wishbone_address_array(g_num_slaves-1 downto 0); - cfg_mask_i : in t_wishbone_address_array(g_num_slaves-1 downto 0)); + master_o : out t_wishbone_master_out_array(g_num_slaves-1 downto 0)); end component; + + component sdwb_rom is + generic( + g_layout : t_sdwb_device_array; + g_bus_end : unsigned(63 downto 0)); + port( + clk_sys_i : in std_logic; + slave_i : in t_wishbone_slave_in; + slave_o : out t_wishbone_slave_out); + end component; + + component xwb_dma is + generic( + -- Value 0 cannot stream + -- Value 1 only slaves with async ACK can stream + -- Value 2 only slaves with combined latency <= 2 can stream + -- Value 3 only slaves with combined latency <= 6 can stream + -- Value 4 only slaves with combined latency <= 14 can stream + -- .... + logRingLen : integer := 4 + ); + port( + -- Common wishbone signals + clk_i : in std_logic; + rst_n_i : in std_logic; + -- Slave control port + slave_i : in t_wishbone_slave_in; + slave_o : out t_wishbone_slave_out; + -- Master reader port + r_master_i : in t_wishbone_master_in; + r_master_o : out t_wishbone_master_out; + -- Master writer port + w_master_i : in t_wishbone_master_in; + w_master_o : out t_wishbone_master_out; + -- Pulsed high completion signal + interrupt_o : out std_logic + ); + end component; + + component xwb_clock_crossing is + generic( + sync_depth : natural := 2; + log2fifo : natural := 4); + port( + -- Common wishbone signals + rst_n_i : in std_logic; + -- Slave control port + slave_clk_i : in std_logic; + slave_i : in t_wishbone_slave_in; + slave_o : out t_wishbone_slave_out; + -- Master reader port + master_clk_i : in std_logic; + master_i : in t_wishbone_master_in; + master_o : out t_wishbone_master_out); + end component; + + subtype t_xwb_dpram_init is t_generic_ram_init; + constant c_xwb_dpram_init_nothing : t_xwb_dpram_init := c_generic_ram_nothing; + + -- g_size is in words + function f_xwb_dpram(g_size : natural) return t_sdwb_device; component xwb_dpram generic ( g_size : natural; g_init_file : string := ""; + g_init_value : t_xwb_dpram_init := c_xwb_dpram_init_nothing; g_must_have_init_file : boolean := true; g_slave1_interface_mode : t_wishbone_interface_mode := CLASSIC; g_slave2_interface_mode : t_wishbone_interface_mode := CLASSIC; @@ -495,3 +616,132 @@ package wishbone_pkg is irq_master_o : out std_logic); end component; end wishbone_pkg; + +package body wishbone_pkg is + function f_ceil_log2(x : natural) return natural is + begin + if x <= 1 + then return 0; + else return f_ceil_log2((x+1)/2) +1; + end if; + end f_ceil_log2; + + -- Used to configure a device at a certain address + function f_sdwb_set_address(device : t_sdwb_device; address : t_wishbone_address) + return t_sdwb_device + is + variable result : t_sdwb_device; + begin + result := device; + result.wbd_begin := (others => '0'); + + result.wbd_begin(c_wishbone_address_width-1 downto 0) := unsigned(address); + result.wbd_end := result.wbd_begin + (device.wbd_end - device.wbd_begin); + + -- If it has a child, remap the SDWB record address as well + if result.wbd_flags(2) = '1' then + result.sdwb_child := result.wbd_begin + (device.sdwb_child - device.wbd_begin); + end if; + return result; + end; + + function f_xwb_bridge_manual_sdwb( + g_bus_end : t_wishbone_address; + g_sdwb_addr : t_wishbone_address) return t_sdwb_device + is + variable result : t_sdwb_device; + begin + result.wbd_begin := x"0000000000000000"; + result.wbd_end := x"0000000000000000"; + result.sdwb_child := x"0000000000000000"; + + result.wbd_end (c_wishbone_address_width-1 downto 0) := unsigned(g_bus_end); + result.sdwb_child(c_wishbone_address_width-1 downto 0) := unsigned(g_sdwb_addr); + + result.wbd_flags := x"05"; -- present, bigendian, child + result.wbd_width := std_logic_vector(to_unsigned(c_wishbone_address_width/4 - 1, 8)); + + result.abi_ver_major := x"01"; + result.abi_ver_minor := x"00"; + result.abi_class := x"00000002"; -- bridge device + + result.dev_vendor := x"00000651"; -- GSI + result.dev_device := x"eef0b198"; + result.dev_version := x"00000001"; + result.dev_date := x"20120305"; + result.description := "WB4-Bridge-GSI "; + + return result; + end f_xwb_bridge_manual_sdwb; + + function f_xwb_bridge_layout_sdwb( + g_wraparound : boolean := true; + g_layout : t_sdwb_device_array; + g_sdwb_addr : t_wishbone_address) return t_sdwb_device + is + alias c_layout : t_sdwb_device_array(g_layout'length-1 downto 0) is g_layout; + + -- How much space does the ROM need? + constant c_used_entries : natural := c_layout'length + 1; + constant c_rom_entries : natural := 2**f_ceil_log2(c_used_entries); -- next power of 2 + constant c_sdwb_bytes : natural := c_sdwb_device_length / 8; + constant c_rom_bytes : natural := c_rom_entries * c_sdwb_bytes; + + -- Step 2. Find the size of the bus + function f_bus_end return unsigned is + variable result : unsigned(63 downto 0); + begin + if not g_wraparound then + result := (others => '0'); + for i in 0 to c_wishbone_address_width-1 loop + result(i) := '1'; + end loop; + else + -- The ROM will be an addressed slave as well + result := (others => '0'); + result(c_wishbone_address_width-1 downto 0) := unsigned(g_sdwb_addr); + result := result + to_unsigned(c_rom_bytes, 64) - 1; + + for i in c_layout'range loop + if c_layout(i).wbd_end > result then + result := c_layout(i).wbd_end; + end if; + end loop; + -- round result up to a power of two -1 + for i in 62 downto 0 loop + result(i) := result(i) or result(i+1); + end loop; + end if; + return result; + end f_bus_end; + + constant bus_end : unsigned(63 downto 0) := f_bus_end; + begin + return f_xwb_bridge_manual_sdwb(std_logic_vector(f_bus_end(c_wishbone_address_width-1 downto 0)), g_sdwb_addr); + end f_xwb_bridge_layout_sdwb; + + function f_xwb_dpram(g_size : natural) return t_sdwb_device + is + variable result : t_sdwb_device; + begin + result.wbd_begin := x"0000000000000000"; + result.sdwb_child := x"0000000000000000"; + + result.wbd_end := to_unsigned(g_size*4-1, 64); + + result.wbd_flags := x"01"; -- present, bigendian, no-child + result.wbd_width := std_logic_vector(to_unsigned(c_wishbone_address_width/4 - 1, 8)); + + result.abi_ver_major := x"01"; + result.abi_ver_minor := x"00"; + result.abi_class := x"00000002"; -- bridge device + + result.dev_vendor := x"0000CE42"; -- CERN + result.dev_device := x"66cfeb52"; + result.dev_version := x"00000001"; + result.dev_date := x"20120305"; + result.description := "WB4-BlockRAM "; + + return result; + end f_xwb_dpram; +end wishbone_pkg; diff --git a/sim/if_wb_link.svh b/sim/if_wb_link.svh new file mode 100644 index 0000000000000000000000000000000000000000..7ae928bf3cfbf8d3028ce45770784d9f9d86f4a5 --- /dev/null +++ b/sim/if_wb_link.svh @@ -0,0 +1,50 @@ + +interface IWishboneLink; + + parameter g_data_width = 32; + parameter g_addr_width = 32; + + + wire [g_addr_width - 1 : 0] adr; + wire [g_data_width - 1 : 0] dat_o; + wire [g_data_width - 1 : 0] dat_i; + wire [(g_data_width/8)-1 : 0] sel; + wire ack; + wire stall; + wire err; + wire rty; + wire cyc; + wire stb; + wire we; + + modport slave + ( + output adr, + output dat_o, + input dat_i, + output sel, + output cyc, + output stb, + output we, + input ack, + input stall, + input err, + input rty + ); + + modport master + ( + input adr, + input dat_o, + output dat_i, + input sel, + input cyc, + input stb, + input we, + output ack, + output stall, + output err, + output rty + ); + +endinterface // IWishboneLink diff --git a/sim/if_wb_master.svh b/sim/if_wb_master.svh new file mode 100644 index 0000000000000000000000000000000000000000..66dcc8c96b4afc5df7045b58bdea5db47854c86a --- /dev/null +++ b/sim/if_wb_master.svh @@ -0,0 +1,438 @@ +// +// Title : Software Wishbone master unit for testbenches +// +// File : if_wishbone.sv +// Author : Tomasz Wlostowski <tomasz.wlostowski@cern.ch> +// Created : Tue Mar 23 12:19:36 2010 +// Standard : SystemVerilog +// + + +/* Todo: + pipelined reads + settings wrapped in the accessor object +*/ + +`include "simdrv_defs.svh" +`include "if_wishbone_types.svh" +`include "if_wishbone_accessor.svh" + +interface IWishboneMaster + ( + input clk_i, + input rst_n_i + ); + + parameter g_addr_width = 32; + parameter g_data_width = 32; + + logic [g_addr_width - 1 : 0] adr; + logic [g_data_width - 1 : 0] dat_o; + logic [(g_data_width/8)-1 : 0] sel; + wire [g_data_width - 1 : 0] dat_i; + wire ack; + wire stall; + wire err; + wire rty; + logic cyc; + logic stb; + logic we; + + wire clk; + wire rst_n; + + time last_access_t = 0; + + struct { + int gen_random_throttling; + real throttle_prob; + int little_endian; + int cyc_on_stall; + wb_address_granularity_t addr_gran; + } settings; + + modport master + ( + output adr, + output dat_o, + output sel, + output cyc, + output stb, + output we, + input ack, + input dat_i, + input stall, + input err, + input rty + ); + + function automatic logic[g_addr_width-1:0] gen_addr(uint64_t addr, int xfer_size); + if(settings.addr_gran == WORD) + case(g_data_width) + 8: return addr; + 16: return addr >> 1; + 32: return addr >> 2; + 64: return addr >> 3; + default: $error("IWishbone: invalid WB data bus width [%d bits\n]", g_data_width); + endcase // case (xfer_size) + else + return addr; + endfunction + + function automatic logic[63:0] rev_bits(logic [63:0] x, int nbits); + logic[63:0] tmp; + int i; + + for (i=0;i<nbits;i++) + tmp[nbits-1-i] = x[i]; + + return tmp; + endfunction // rev_bits + + + //FIXME: little endian + function automatic logic[(g_data_width/8)-1:0] gen_sel(uint64_t addr, int xfer_size, int little_endian); + logic [(g_data_width/8)-1:0] sel; + const int dbytes = (g_data_width/8-1); + + + sel = ((1<<xfer_size) - 1); + + return rev_bits(sel << (addr % xfer_size), g_data_width/8); + endfunction + + function automatic logic[g_data_width-1:0] gen_data(uint64_t addr, uint64_t data, int xfer_size, int little_endian); + const int dbytes = (g_data_width/8-1); + logic[g_data_width-1:0] tmp; + + tmp = data << (8 * (dbytes - (xfer_size - 1 - (addr % xfer_size)))); + +// $display("GenData: xs %d dbytes %d %x", tmp, xfer_size, dbytes); + + + return tmp; + + endfunction // gen_data + + function automatic uint64_t decode_data(uint64_t addr, logic[g_data_width-1:0] data, int xfer_size); + int rem; + + // $display("decode: a %x d %x xs %x", addr, data ,xfer_size); + + + rem = addr % xfer_size; + return (data >> (8*rem)) & ((1<<(xfer_size*8)) - 1); + endfunction // decode_data + + + task automatic classic_cycle + ( + inout wb_xfer_t xfer[], + input bit rw, + input int n_xfers, + output wb_cycle_result_t result + ); + + int i; + + if($time != last_access_t) + @(posedge clk_i); /* resynchronize, just in case */ + + for(i=0;i<n_xfers;i++) + begin + + stb <= 1'b1; + cyc <= 1'b1; + adr <= gen_addr(xfer[i].a, xfer[i].size); + we <= rw; + sel <= gen_sel(xfer[i].a, xfer[i].size, settings.little_endian); +//gen_sel(xfer[i].a, xfer[i].size); + dat_o <= gen_data(xfer[i].a, xfer[i].d, xfer[i].size, settings.little_endian); + + @(posedge clk_i); + + if(ack == 0) begin + while(ack == 0) begin @(posedge clk_i); end + end else if(err == 1'b1 || rty == 1'b1) + begin + cyc <= 0; + we <= 0; + stb <= 0; + result = (err ==1'b1 ? R_ERROR: R_RETRY); + break; + end + + xfer[i].d = decode_data(xfer[i].a, dat_i, xfer[i].size); + + cyc <= 0; + we <= 0; + stb <= 0; + + end // if (ack == 0) + + @(posedge clk_i); + + result = R_OK; + last_access_t = $time; + endtask // automatic + + reg xf_idle = 1; + + + int ack_cnt_int; + + always@(posedge clk_i) + begin + if(!cyc) + ack_cnt_int <= 0; + else if(stb && !stall && !ack) + ack_cnt_int++; + else if((!stb || stall) && ack) + ack_cnt_int--; + end + + + task automatic count_ack(ref int ack_cnt); +// if(stb && !stall && !ack) +// ack_cnt++; + if (ack) + ack_cnt--; + endtask + + task automatic handle_readback(ref wb_xfer_t xf [$], input int read, ref int cur_rdbk); + if(ack && read) + begin + xf[cur_rdbk].d = dat_i; + cur_rdbk++; + end + endtask // handle_readback + + + task automatic pipelined_cycle + ( + ref wb_xfer_t xfer[$], + input int write, + input int n_xfers, + output wb_cycle_result_t result + ); + + int i; + int ack_count ; + int failure ; + int cur_rdbk; + + + ack_count = 0; + failure = 0; + + xf_idle = 0; + cur_rdbk = 0; + + + if($time != last_access_t) + @(posedge clk_i); /* resynchronize, just in case */ + + while(stall && !settings.cyc_on_stall) + @(posedge clk_i); + + cyc <= 1'b1; + i =0; + + ack_count = n_xfers; + + while(i<n_xfers) + begin + count_ack(ack_count); + handle_readback(xfer, !write, cur_rdbk); + + + if(err) begin + result = R_ERROR; + failure = 1; + break; + end + + if(rty) begin + result = R_RETRY; + failure = 1; + break; + end + + + if (!stall && settings.gen_random_throttling && probability_hit(settings.throttle_prob)) begin + stb <= 1'b0; + we <= 1'b0; + @(posedge clk_i); + + + end else begin + adr <= gen_addr(xfer[i].a, xfer[i].size); + stb <= 1'b1; + if(write) + begin + we <= 1'b1; + sel <= gen_sel(xfer[i].a, xfer[i].size, settings.little_endian); + dat_o <= gen_data(xfer[i].a, xfer[i].d, xfer[i].size, settings.little_endian); + end else begin + we<=1'b0; + sel <= 'hffffffff; + end + + @(posedge clk_i); + stb <= 1'b0; + we <= 1'b0; + if(stall) + begin + stb <= 1'b1; + + if(write) + we <= 1'b1; + + while(stall) + begin + count_ack(ack_count); + @(posedge clk_i); + + + end + stb <= 1'b0; + we <= 1'b0; + end + i++; + end + + end // for (i =0;i<n_xfers;i++) + + + while((ack_count > 0) && !failure) + begin + // $display("AckCount %d", ack_count); + + if(err) begin + result = R_ERROR; + failure = 1; + break; + end + + if(rty) begin + result = R_RETRY; + failure = 1; + break; + end + + + count_ack(ack_count); + handle_readback(xfer, !write, cur_rdbk); + + if(stb && !ack) + ack_count++; + else if(!stb && ack) + ack_count--; + @(posedge clk_i); + end + + + + cyc <= 1'b0; + @(posedge clk_i); + if(!failure) + result = R_OK; + xf_idle = 1; + last_access_t = $time; + endtask // automatic + + + wb_cycle_t request_queue[$]; + wb_cycle_t result_queue[$]; + +class CIWBMasterAccessor extends CWishboneAccessor; + + function automatic int poll(); + return 0; + endfunction + + task get(ref wb_cycle_t xfer); + while(!result_queue.size()) + @(posedge clk_i); + xfer = result_queue.pop_front(); + endtask + + task clear(); + endtask // clear + + task put(ref wb_cycle_t xfer); + // $display("WBMaster[%d]: PutCycle",g_data_width); + request_queue.push_back(xfer); + endtask // put + + function int idle(); + return (request_queue.size() == 0) && xf_idle; + endfunction // idle +endclass // CIWBMasterAccessor + + + function CIWBMasterAccessor get_accessor(); + CIWBMasterAccessor tmp; + tmp = new; + return tmp; + endfunction // get_accessoror + + always@(posedge clk_i) + if(!rst_n_i) + begin + request_queue = {}; + result_queue = {}; + xf_idle = 1; + cyc <= 0; + dat_o <= 0; + stb <= 0; + sel <= 0; + adr <= 0; + we <= 0; + end + + initial begin + settings.gen_random_throttling = 0; + settings.throttle_prob = 0.1; + settings.cyc_on_stall = 0; + settings.addr_gran = WORD; + end + + + initial forever + begin + @(posedge clk_i); + + + if(request_queue.size() > 0) + begin + + + wb_cycle_t c; + wb_cycle_result_t res; + + c = request_queue.pop_front(); + + case(c.ctype) + PIPELINED: + begin + pipelined_cycle(c.data, c.rw, c.data.size(), res); + c.result =res; + end + CLASSIC: + begin + // $display("WBMaster: got classic cycle [%d, rw %d]", c.data.size(), c.rw); + classic_cycle(c.data, c.rw, c.data.size, res); + + c.result =res; + + + end + endcase // case (c.ctype) + + result_queue.push_back(c); + end + end + + +endinterface // IWishbone diff --git a/sim/if_wb_slave.svh b/sim/if_wb_slave.svh new file mode 100644 index 0000000000000000000000000000000000000000..14034b53037dc985d9788cc710750d3832b52260 --- /dev/null +++ b/sim/if_wb_slave.svh @@ -0,0 +1,241 @@ +`ifndef __IF_WISHBONE_SLAVE_SVH +`define __IF_WISHBONE_SLAVE_SVH + +`timescale 1ns/1ps + +`include "if_wishbone_types.svh" + + + +interface IWishboneSlave + ( + input clk_i, + input rst_n_i + ); + + parameter g_addr_width = 32; + parameter g_data_width = 32; + + + wire [g_addr_width - 1: 0] adr; + wire [g_data_width - 1: 0] dat_i; + wire [(g_data_width/8)-1 : 0] sel; + logic [g_data_width - 1 : 0] dat_o; + logic ack; + logic stall; + logic err; + logic rty; + wire cyc; + wire stb; + wire we; + + + + time last_access_t = 0; + + modport slave + ( + input adr, + input dat_o, + input sel, + input cyc, + input stb, + input we, + output ack, + output dat_i, + output stall, + output err, + output rty + ); + + wb_cycle_t c_queue[$]; + wb_cycle_t current_cycle; + + reg cyc_prev; + int trans_index; + int first_transaction; + + struct { + wb_cycle_type_t mode; + int gen_random_stalls; + int stall_min_duration; + int stall_max_duration; + real stall_prob; + } settings; + + + function automatic int _poll(); return poll(); endfunction + task automatic _get(ref wb_cycle_t xfer); get(xfer); endtask + + class CIWBSlaveAccessor extends CWishboneAccessor; + + function automatic int poll(); + return _poll(); + endfunction + + task get(ref wb_cycle_t xfer); + _get(xfer); + endtask + + task clear(); + endtask // clear + + endclass // CIWBSlaveAccessor + + + function CIWBSlaveAccessor get_accessor(); + CIWBSlaveAccessor tmp; + tmp = new; + return tmp; + endfunction // get_accessor + + + function automatic int poll(); + return c_queue.size() != 0; + endfunction // poll + + task automatic get(ref wb_cycle_t xfer); + while(c_queue.size() <= 0) + @(posedge clk_i); + + xfer = c_queue.pop_front(); + endtask // pop_cycle + + + always@(posedge clk_i) cyc_prev <= cyc; + wire cyc_start = !cyc_prev && cyc; + wire cyc_end = cyc_prev && !cyc; + + + task gen_random_stalls(); + static int stall_remaining = 0; + static int seed = 0; + +// $display("stallr: %d\n", stall_remaining); + + if(settings.gen_random_stalls && (probability_hit(settings.stall_prob) || stall_remaining > 0)) + begin + + if(stall_remaining == 0) + stall_remaining = $dist_uniform(seed, + settings.stall_min_duration, + settings.stall_max_duration); + if(stall_remaining) + stall_remaining--; + + stall <= 1; + end else + stall <= 0; + + + endtask // gen_random_stalls + + function automatic int count_ones(int x, int n_bits); + int i, cnt; + cnt = 0; + for(i=0;i<n_bits;i++) if(x & (1<<i)) cnt ++; + return cnt; + endfunction + + function automatic int count_leading_zeroes(int x, int n_bits); + int i; + for(i=0;i<n_bits && !(x & (1<<i)); i++); + return i; + endfunction // count_leading_zeroes + + function automatic int count_trailing_zeroes(int x, int n_bits); + int i; + for(i=n_bits-1;i>=0 && !(x & (1<<i)); i--); + return (n_bits-1-i); + endfunction + + + task pipelined_fsm(); + + if(settings.gen_random_stalls) + gen_random_stalls(); + else + stall <= 0; + +/* -----\/----- EXCLUDED -----\/----- + if(cyc) begin + + end else + stall <= 0; + -----/\----- EXCLUDED -----/\----- */ + + if(cyc_start) begin + current_cycle.data = {}; + trans_index <= 0; + first_transaction = 1; + end + + if(cyc_end) begin + c_queue.push_back(current_cycle); + end + + if(stb && we && !stall && cyc) begin + int oc, lzc, tzc; + + wb_xfer_t d; + + oc = count_ones(sel, g_data_width/8); + lzc = count_leading_zeroes(sel, g_data_width/8); + tzc = count_trailing_zeroes(sel, g_data_width/8); + d.a = adr * (g_data_width / 8); + d.size = oc; + d.d = (dat_i>>(8*lzc)) & ((1<<(oc*8)) -1); + + if(lzc + tzc + oc != g_data_width/8) + $error("IWishboneSlave [write a %x d %x sel %x]: non-contiguous sel", adr, dat_i, sel); + + d.sel [g_data_width/8-1:0] = sel; + + current_cycle.data.push_back(d); + +// $display("ifWb:[%d] write a %x d %x sel %x",current_cycle.data.size(), adr, dat_i, sel); + ack <= 1; + + end else if(stb && !we && !stall) begin +// $error("Sorry, no pipelined read for slave yet implemented"); + ack <= 0; + end else + ack <= 0; + + + + endtask // pipelined_fsm + + always@(posedge clk_i) + begin + if(!rst_n_i) + begin + c_queue = {}; + current_cycle.data = {}; + trans_index = 0; + ack <= 0; + rty <= 0; + err <= 0; + dat_o <= 0; + stall <= 0; + + end else begin + if(settings.mode == PIPELINED) + pipelined_fsm(); + end + end + + initial begin + settings.mode = PIPELINED; + settings.gen_random_stalls = 1; + settings.stall_prob = 0.1; + settings.stall_min_duration = 1; + settings.stall_max_duration = 2; + + end + + + +endinterface // IWishboneSlave + +`endif \ No newline at end of file diff --git a/sim/if_wishbone_accessor.svh b/sim/if_wishbone_accessor.svh new file mode 100644 index 0000000000000000000000000000000000000000..b0f789719d420305c934cf6589576cde971b3eb4 --- /dev/null +++ b/sim/if_wishbone_accessor.svh @@ -0,0 +1,137 @@ +`ifndef IF_WISHBONE_ACCESSOR_SV +`define IF_WISHBONE_ACCESSOR_SV + +`include "if_wishbone_types.svh" + +virtual class CWishboneAccessor extends CBusAccessor; + + static int _null = 0; + protected wb_cycle_type_t m_cycle_type; + + function new(); + m_cycle_type = CLASSIC; + endfunction // new + + virtual task set_mode(wb_cycle_type_t mode); + m_cycle_type = mode; + endtask // set_mode + + + // [slave only] checks if there are any transactions in the queue + virtual function automatic int poll(); + return 0; + endfunction // poll + + // [slave only] adds a simulation event (e.g. a forced STALL, RETRY, ERROR) + // evt = event type (STALL, ERROR, RETRY) + // behv = event behavior: DELAYED - event occurs after a predefined delay (dly_start) + // RANDOM - event occurs randomly with probability (prob) + // These two can be combined (random events occuring after a certain initial delay) + // DELAYED events can be repeated (rep_rate parameter) + virtual task add_event(wba_sim_event_t evt, wba_sim_behavior_t behv, int dly_start, real prob, int rep_rate); + + endtask // add_event + + + // [slave only] gets a cycle from the queue + virtual task get(ref wb_cycle_t xfer); + + endtask // get + + // [master only] executes a cycle and returns its result + virtual task put(ref wb_cycle_t xfer); + + endtask // put + + virtual function int idle(); + return 1; + endfunction // idle + + // [master only] generic write(s), blocking + virtual task writem(uint64_t addr[], uint64_t data[], int size = 4, ref int result = _null); + wb_cycle_t cycle; + int i; + + cycle.ctype = m_cycle_type; + cycle.rw = 1'b1; + + for(i=0;i < addr.size(); i++) + begin + wb_xfer_t xfer; + xfer.a = addr[i]; + xfer.d = data[i]; + xfer.size = size; + cycle.data.push_back(xfer); + end + +// $display("DS: %d", cycle.data.size()); + + put(cycle); + get(cycle); + result = cycle.result; + + endtask // write + + // [master only] generic read(s), blocking + virtual task readm(uint64_t addr[], ref uint64_t data[],input int size = 4, ref int result = _null); + wb_cycle_t cycle; + int i; + + cycle.ctype = m_cycle_type; + cycle.rw = 1'b0; + + for(i=0;i < addr.size(); i++) + begin + wb_xfer_t xfer; + xfer.a = addr[i]; + xfer.size = size; + cycle.data.push_back(xfer); + end + + put(cycle); + get(cycle); + + for(i=0;i < addr.size(); i++) + data[i] = cycle.data[i].d; + + result = cycle.result; + + endtask // readm + + virtual task read(uint64_t addr, ref uint64_t data, input int size = 4, ref int result = _null); + uint64_t aa[], da[]; + aa = new[1]; + da = new[1]; + aa[0] = addr; + readm(aa, da, size, result); + data = da[0]; + endtask + + virtual task write(uint64_t addr, uint64_t data, int size = 4, ref int result = _null); + uint64_t aa[], da[]; + aa = new[1]; + da = new[1]; + + aa[0] = addr; + da[0] = data; + writem(aa, da, size, result); + endtask + +endclass // CWishboneAccessor + +static int seed = 0; + +function automatic int probability_hit(real prob); + real rand_val; + rand_val = real'($dist_uniform(seed, 0, 1000)) / 1000.0; + + if(rand_val < prob) + return 1; + else + return 0; + +endfunction // probability_hit + + +`endif // `ifndef IF_WISHBONE_ACCESSOR_SV + diff --git a/sim/if_wishbone_defs.svh b/sim/if_wishbone_defs.svh new file mode 100644 index 0000000000000000000000000000000000000000..3b13f1101a61edcba86bf9ece25bd184dab5b874 --- /dev/null +++ b/sim/if_wishbone_defs.svh @@ -0,0 +1,77 @@ +// +// Title : Software Wishbone master unit for testbenches +// +// File : wishbone_master_tb.v +// Author : Tomasz Wlostowski <tomasz.wlostowski@cern.ch> +// Created : Tue Mar 23 12:19:36 2010 +// Standard : Verilog 2001 +// + +`ifndef __IF_WB_DEFS_SV +`define __IF_WB_DEFS_SV + +`include "simdrv_defs.sv" + +typedef enum +{ + R_OK = 0, + R_ERROR, + R_RETRY +} wb_cycle_result_t; + +typedef enum +{ + CLASSIC = 0, + PIPELINED = 1 +} wb_cycle_type_t; + +typedef struct { + uint64_t a; + uint64_t d; + bit[7:0] sel; + int size; +} wb_xfer_t; + +typedef struct { + int rw; + wb_cycle_type_t ctype; + wb_xfer_t data[$]; + wb_cycle_result_t result; +} wb_cycle_t; + + +virtual class CWishboneAccessor; + + virtual function automatic int poll(); + return 0; + endfunction // poll + + virtual task get(output wb_cycle_t xfer); + endtask // get + + virtual task put(input wb_cycle_t xfer); + endtask // put + + virtual function int idle(); + return 0; + endfunction // idle + + virtual task clear(); endtask + +endclass // CWishboneAccessor + +int seed = 0; + + function automatic int probability_hit(real prob); + real rand_val; + rand_val = real'($dist_uniform(seed, 0, 1000)) / 1000.0; + + if(rand_val < prob) + return 1; + else + return 0; + + endfunction // probability_hit + + +`endif // `ifndef __IF_WB_DEFS_SV diff --git a/sim/if_wishbone_types.svh b/sim/if_wishbone_types.svh new file mode 100644 index 0000000000000000000000000000000000000000..5849afe7a12241f1ca2aa5bbfb60b5091b2ee03d --- /dev/null +++ b/sim/if_wishbone_types.svh @@ -0,0 +1,61 @@ +// +// Title : Pipelined Wishbone BFM - type definitions +// +// File : if_wishbone_types.sv +// Author : Tomasz Wlostowski <tomasz.wlostowski@cern.ch> +// Created : Tue Mar 23 12:19:36 2010 +// Standard : Verilog 2001 +// + +`ifndef __IF_WB_TYPES_SVH +`define __IF_WB_TYPES_SVH + +`include "simdrv_defs.svh" + +typedef enum +{ + R_OK = 0, + R_ERROR, + R_RETRY +} wb_cycle_result_t; + +typedef enum +{ + CLASSIC = 0, + PIPELINED = 1 +} wb_cycle_type_t; + +typedef enum { + WORD = 0, + BYTE = 1 +} wb_address_granularity_t; + +typedef struct { + uint64_t a; + uint64_t d; + int size; + bit [7:0] sel; +} wb_xfer_t; + +typedef struct { + int rw; + wb_cycle_type_t ctype; + wb_xfer_t data[$]; + wb_cycle_result_t result; +} wb_cycle_t; + +typedef enum + { + RETRY = 0, + STALL, + ERROR +} wba_sim_event_t; + +typedef enum +{ + RANDOM = (1<<0), + DELAYED = (1<<1) + } wba_sim_behavior_t; + +`endif // `ifndef __IF_WB_TYPES_SVH + diff --git a/sim/regs/xloader_regs.vh b/sim/regs/xloader_regs.vh new file mode 100644 index 0000000000000000000000000000000000000000..550ac21e1724b666dc24065f5eafd176dafddc28 --- /dev/null +++ b/sim/regs/xloader_regs.vh @@ -0,0 +1,30 @@ +`define ADDR_XLDR_CSR 4'h0 +`define XLDR_CSR_START_OFFSET 0 +`define XLDR_CSR_START 32'h00000001 +`define XLDR_CSR_DONE_OFFSET 1 +`define XLDR_CSR_DONE 32'h00000002 +`define XLDR_CSR_ERROR_OFFSET 2 +`define XLDR_CSR_ERROR 32'h00000004 +`define XLDR_CSR_BUSY_OFFSET 3 +`define XLDR_CSR_BUSY 32'h00000008 +`define XLDR_CSR_MSBF_OFFSET 4 +`define XLDR_CSR_MSBF 32'h00000010 +`define XLDR_CSR_SWRST_OFFSET 5 +`define XLDR_CSR_SWRST 32'h00000020 +`define XLDR_CSR_CLKDIV_OFFSET 8 +`define XLDR_CSR_CLKDIV 32'h00003f00 +`define ADDR_XLDR_FIFO_R0 4'h4 +`define XLDR_FIFO_R0_XSIZE_OFFSET 0 +`define XLDR_FIFO_R0_XSIZE 32'h00000003 +`define XLDR_FIFO_R0_XLAST_OFFSET 2 +`define XLDR_FIFO_R0_XLAST 32'h00000004 +`define ADDR_XLDR_FIFO_R1 4'h8 +`define XLDR_FIFO_R1_XDATA_OFFSET 0 +`define XLDR_FIFO_R1_XDATA 32'hffffffff +`define ADDR_XLDR_FIFO_CSR 4'hc +`define XLDR_FIFO_CSR_FULL_OFFSET 16 +`define XLDR_FIFO_CSR_FULL 32'h00010000 +`define XLDR_FIFO_CSR_EMPTY_OFFSET 17 +`define XLDR_FIFO_CSR_EMPTY 32'h00020000 +`define XLDR_FIFO_CSR_USEDW_OFFSET 0 +`define XLDR_FIFO_CSR_USEDW 32'h000000ff diff --git a/sim/simdrv_defs.svh b/sim/simdrv_defs.svh new file mode 100644 index 0000000000000000000000000000000000000000..e7e04bc799491fe528f0dad39eca62781e9014f3 --- /dev/null +++ b/sim/simdrv_defs.svh @@ -0,0 +1,104 @@ +`ifndef SIMDRV_DEFS_SV + `define SIMDRV_DEFS_SV 1 + +typedef longint unsigned uint64_t; +typedef int unsigned uint32_t; +typedef shortint unsigned uint16_t; + + + +typedef uint64_t u64_array_t[]; +typedef byte byte_array_t[]; + + + + +virtual class CBusAccessor; + static int _null = 0; + + pure virtual task writem(uint64_t addr[], uint64_t data[], input int size, ref int result); + pure virtual task readm(uint64_t addr[], ref uint64_t data[], input int size, ref int result); + + virtual task read(uint64_t addr, ref uint64_t data, input int size = 4, ref int result = _null); + int res; + uint64_t aa[1], da[]; + + da= new[1]; + + aa[0] = addr; + readm(aa, da, size, res); + data = da[0]; + endtask + + + virtual task write(uint64_t addr, uint64_t data, input int size = 4, ref int result = _null); + uint64_t aa[1], da[1]; + aa[0] = addr; + da[0] = data; + writem(aa, da, size, result); + endtask + +endclass // CBusAccessor + +class CSimUtils; + + static function automatic u64_array_t pack(byte x[], int size, int big_endian = 1); + u64_array_t tmp; + int i, j; + int nwords, nbytes; + + nwords = (x.size() + size - 1) / size; + tmp = new [nwords]; + + for(i=0;i<nwords;i++) + begin + uint64_t d; + d =0; + nbytes = (x.size() - i * nbytes > size ? size : x.size() - i*nbytes); + + for(j=0;j<nbytes;j++) + begin + if(big_endian) + d = d | ((x[i*size+j] << (8*(size-1-j)))); + else + d = d | ((x[i*size+j] << (8*j))); + end + + + tmp[i] = d; + end + return tmp; + endfunction // pack + + + static function automatic byte_array_t unpack(u64_array_t x, int entry_size, int size, int big_endian = 1); + byte_array_t tmp; + int i, n; + + tmp = new[size]; + n = 0; + i = 0; + + + while(n < size) + begin + tmp[n] = x[i] >> (8*(entry_size-1 - (n % entry_size))); + + n++; + if(n % entry_size == 0) + i++; + end + + return tmp; + endfunction // unpack + + + + +endclass // CSimUtils + +static CSimUtils SimUtils; + + + +`endif \ No newline at end of file diff --git a/testbench/wishbone/lm32_testsys/lm32_test_system.vhd b/testbench/wishbone/lm32_testsys/lm32_test_system.vhd index fef8b8fa496d177ad6b1fc8cd4ab755606a1a95d..02fc46fdfe5a2cc61f254fd1cc88416a3c013ce9 100644 --- a/testbench/wishbone/lm32_testsys/lm32_test_system.vhd +++ b/testbench/wishbone/lm32_testsys/lm32_test_system.vhd @@ -64,16 +64,16 @@ begin -- rtl generic map ( g_num_masters => c_cnx_slave_ports, g_num_slaves => c_cnx_master_ports, - g_registered => true) + g_registered => true, + g_address => c_cfg_base_addr, + g_mask => c_cfg_base_mask) port map ( clk_sys_i => clk_sys_i, rst_n_i => rst_n_i, slave_i => cnx_slave_in, slave_o => cnx_slave_out, master_i => cnx_master_in, - master_o => cnx_master_out, - cfg_address_i => c_cfg_base_addr, - cfg_mask_i => c_cfg_base_mask); + master_o => cnx_master_out); U_DPRAM : xwb_dpram generic map ( diff --git a/testbench/wishbone/wb_xilinx_fpga_loader/Manifest.py b/testbench/wishbone/wb_xilinx_fpga_loader/Manifest.py new file mode 100644 index 0000000000000000000000000000000000000000..9e50477039e9d56d6747e3371c35c49b7d5e5f1e --- /dev/null +++ b/testbench/wishbone/wb_xilinx_fpga_loader/Manifest.py @@ -0,0 +1,9 @@ +action = "simulation" + +fetchto="../../../ip_cores" + +modules = { "local" : "../../../" }; + +files = ["main.sv", "SIM_CONFIG_S6_SERIAL.v", "glbl.v" ] + +vlog_opt= "+incdir+../../../sim" \ No newline at end of file diff --git a/testbench/wishbone/wb_xilinx_fpga_loader/SIM_CONFIG_S6_SERIAL.v b/testbench/wishbone/wb_xilinx_fpga_loader/SIM_CONFIG_S6_SERIAL.v new file mode 100644 index 0000000000000000000000000000000000000000..db263517bc899199b6343cfae2d681c814257106 --- /dev/null +++ b/testbench/wishbone/wb_xilinx_fpga_loader/SIM_CONFIG_S6_SERIAL.v @@ -0,0 +1,841 @@ +// Copyright (c) 1995/2005 Xilinx, Inc. +// All Right Reserved. +/////////////////////////////////////////////////////////////////////////////// +// ____ ____ +// / /\/ / +// /___/ \ / Vendor : Xilinx +// \ \ \/ Version : 10.1 +// \ \ Description : Xilinx Function Simulation Library Component +// / / Configuration Simulation Model +// /___/ /\ Filename : SIM_CONFIG_S6_SERIAL.v +// \ \ / \ Timestamp : +// \___\/\___\ +// +// Revision: +// 03/22/09 - Initial version of serial configuration simulation model for +// Spartann6. +// 11/25/09 - Fix CRC (CR538766) +// 02/24/10 - Change Tprog to 500 ns (CR550552) +// 03/03/10 - set mode_sample_flag to 0 when mode pin set wrong (CR552316) +// End Revision +//////////////////////////////////////////////////////////////////////////////// + +`timescale 1 ps / 1 ps + +module SIM_CONFIG_S6_SERIAL2 ( + DONE, + CCLK, + DIN, + INITB, + M, + PROGB + ); + + inout DONE; + input CCLK; + input DIN; + inout INITB; + input [1:0] M; + input PROGB; + + parameter DEVICE_ID = 32'h0; + + localparam cfg_Tprog = 500000; // min PROG must be low, 300 ns + localparam cfg_Tpl = 100000; // max program latency us. + localparam STARTUP_PH0 = 3'b000; + localparam STARTUP_PH1 = 3'b001; + localparam STARTUP_PH2 = 3'b010; + localparam STARTUP_PH3 = 3'b011; + localparam STARTUP_PH4 = 3'b100; + localparam STARTUP_PH5 = 3'b101; + localparam STARTUP_PH6 = 3'b110; + localparam STARTUP_PH7 = 3'b111; + + wire GSR, GTS, GWE; + wire cclk_in; + wire init_b_in; + wire prog_b_in; + wire crc_err_flag_tot; + reg crc_err_flag_reg = 0; + reg mode_sample_flag = 0; + reg init_b_p = 1; + reg done_o = 0; + tri1 p_up; + + triand (weak1, strong0) INITB=(mode_sample_flag) ? ~crc_err_flag_tot : init_b_p; + triand (weak1, strong0) DONE=done_o; + + assign DONE = p_up; + assign INITB = p_up; + + wire done_in; + reg por_b; + wire [1:0] m_in; + reg [2:0] mode_pin_in = 3'b0; + wire [15:0] d_in; + wire [15:0] d_out; + +// assign glbl.GSR = GSR; +// assign glbl.GTS = GTS; +// assign glbl.GWE = GWE; + wire d_out_en; + wire init_b_t; + wire prog_b_t; + wire crc_rst; + + buf buf_cclk (cclk_in, CCLK); + + buf buf_din (ds_in, DIN); +// buf buf_dout (DOUT, ds_out); + buf buf_init (init_b_in, INITB); + buf buf_m_0 (m_in[0], M[0]); + buf buf_m_1 (m_in[1], M[1]); + buf buf_prog (prog_b_in, PROGB); + + time prog_pulse_low_edge = 0; + time prog_pulse_low = 0; + integer wr_cnt = 0; + reg [4:0] csbo_cnt = 5'b0; + reg csbo_flag = 0; + reg dcm_locked = 1; + reg [4:0] conti_data_cnt = 5'b0; + reg [5:0] rd_data_cnt = 6'b0; + reg [15:0] pack_in_reg = 16'b0; + reg [5:0] reg_addr; + reg [5:0] rd_reg_addr; + reg new_data_in_flag = 0; + reg wr_flag = 1; + reg rd_flag = 0; + reg cmd_wr_flag = 0; + reg cmd_rd_flag = 0; + reg bus_sync_flag = 0; + reg [1:0] buswidth = 2'b00; + reg rd_sw_en = 0; + reg conti_data_flag = 0; + reg conti_data_flag_set = 0; + reg [2:0] st_state = STARTUP_PH0; + reg startup_begin_flag = 0; + reg startup_end_flag = 0; + reg cmd_reg_new_flag = 0; + reg far_maj_min_flag = 0; + reg crc_reset = 0; + reg crc_ck = 0; + reg crc_err_flag = 0; + wire crc_en, desync_flag; + reg [21:0] crc_curr = 22'b0; + reg [21:0] crc_new = 22'b0; + reg [21:0] crc_input = 22'b0; + reg gwe_out = 0; + reg gts_out = 1; + reg reboot_set = 0; + reg gsr_set = 0; + reg gts_usr_b = 1; + reg done_pin_drv = 0; + reg crc_bypass = 0; + reg reset_on_err = 0; + reg sync_timeout = 0; + reg [31:0] crc_reg, idcode_reg, idcode_tmp; + reg [15:0] far_maj_reg; + reg [15:0] far_min_reg; + reg [15:0] fdri_reg; + reg [15:0] fdro_reg; + reg [15:0] cwdt_reg; + reg [15:0] ctl_reg = 8'b10000001; + reg [4:0] cmd_reg; + reg [15:0] general1_reg; + reg [15:0] mask_reg = 8'b0; + reg [15:0] lout_reg, flr_reg; + reg [15:0] cor1_reg = 16'b0x11011100000000; + reg [15:0] cor2_reg = 16'b0000100111101110; + reg [15:0] pwrdn_reg = 16'bx00010001000x001; + reg [15:0] snowplow_reg; + reg [15:0] hc_opt_reg; + reg [15:0] csbo_reg; + reg [15:0] general2_reg; + reg [15:0] mode_reg; + reg [15:0] general3_reg; + reg [15:0] general4_reg; + reg [15:0] general5_reg; + reg [15:0] eye_mask_reg; + reg [15:0] cbc_reg; + reg [15:0] seu_reg; + reg [15:0] bootsts_reg; + reg [15:0] pu_gwe_reg; + reg [15:0] pu_gts_reg; + reg [15:0] mfwr_reg; + reg [15:0] cclk_freq_reg; + reg [15:0] seu_opt_reg; + reg [31:0] exp_sign_reg; + reg [15:0] rdbk_sign_reg; + + reg shutdown_set = 0; + reg desynch_set = 0; + reg [2:0] done_cycle_reg = 3'b100; + reg [2:0] gts_cycle_reg = 3'b101; + reg [2:0] gwe_cycle_reg=3'b110; + reg [2:0] nx_st_state = 3'b000; + reg ghigh_b = 0; + reg eos_startup = 0; + reg startup_set = 0; + reg [1:0] startup_set_pulse = 2'b0; + reg [7:0] tmp_byte; + reg [7:0] tmp_byte1; + reg [7:0] tmp_byte2; + reg [7:0] tmp_byte3; + reg [7:0] tmp_byte4; + reg [7:0] tmp_byte5; + reg [7:0] tmp_byte6; + reg [7:0] tmp_byte7; + reg [15:0] tmp_word; + reg [7:0] ctl_reg_tmp; + reg id_error_flag = 0; + reg iprog_b = 1; + reg persist_en = 0; + reg rst_sync = 0; + reg [2:0] lock_cycle_reg = 3'b0; + reg rbcrc_no_pin = 0; + reg gsr_st_out = 1; + reg gsr_cmd_out = 0; + wire [15:0] stat_reg; + wire rst_intl; + wire rw_en; + wire gsr_out; + wire cfgerr_b_flag; + reg [27:0] downcont = 28'b0; + reg type2_flag = 0; + reg rst_en=1, prog_b_a=1; + reg [31:0] tmp_dword1; + reg [31:0] tmp_dword2; + integer wr_bit_addr; + + initial begin + if (DEVICE_ID == 32'h0) begin + $display("Attribute Error : The attribute DEVICE_ID on SIM_CONFIG_S6_SERIAL instance %m is not set."); + end + end + + + assign GSR = gsr_out; + assign GTS = gts_out; + assign GWE = gwe_out; + assign cfgerr_b_flag = rw_en & ~crc_err_flag_tot; + assign crc_err_flag_tot = id_error_flag | crc_err_flag_reg; + assign crc_en = 1; + assign done_in = DONE; + + assign init_b_t = init_b_in; + + always @( negedge prog_b_in) begin + rst_en = 0; + rst_en <= #cfg_Tprog 1; + end + + always @( posedge rst_en or posedge prog_b_in ) + if (rst_en == 1) begin + if (prog_b_in == 0 ) + init_b_p <= 0; + else + init_b_p <= #(cfg_Tpl) 1; + end + + always @( rst_en or prog_b_in or prog_pulse_low) + if (rst_en == 1) begin + if (prog_pulse_low == cfg_Tprog) begin + prog_b_a = 0; + prog_b_a <= #500 1; + end + else + prog_b_a = prog_b_in; + end + else + prog_b_a = 1; + + initial begin + por_b = 0; + por_b = #400000 1; + end + + assign prog_b_t = prog_b_a & iprog_b & por_b; + + assign rst_intl = (prog_b_t == 0 ) ? 0 : 1; + + + always @( init_b_t or prog_b_t) + begin + $display("StupidP"); + + if (prog_b_t == 0) + mode_sample_flag <= 0; + else if (init_b_t && mode_sample_flag == 0) begin + if (prog_b_t == 1) begin + mode_pin_in <= m_in; + if (m_in != 2'b11) begin + mode_sample_flag <= 0; + $display("Error: input M is %h. Only Slave Serial mode M=11 supported on SIM_CONFIG_S6_SERIAL instance %m.", m_in); + end + else + mode_sample_flag <= #1 1; + end + end + end // always @ ( init_b_t or prog_b_t) + + always @(posedge init_b_t ) + if (prog_b_t != 1) begin + if ($time != 0 ) + $display("Error: PROGB is not high when INITB goes high on SIM_CONFIG_S6_SERIAL instance %m at time %t.", $time); + end + + always @(m_in) + if (mode_sample_flag == 1 && persist_en == 1) + $display("Error : Mode pine M[2:0] changed after rising edge of INITB on SIM_CONFIG_S6_SERIAL instance %m at time %t.", $time); + + always @(posedge prog_b_in or negedge prog_b_in) + if (prog_b_in == 0) + prog_pulse_low_edge <= $time; + else if (prog_b_in == 1 && $time > 0) begin + prog_pulse_low = $time - prog_pulse_low_edge; + if (prog_pulse_low < cfg_Tprog ) + $display("Error: Low time of PROGB is less than required minimum Tprogram time %d on SIM_CONFIG_S6_SERIAL instance %m at time %t.", cfg_Tprog, $time); + end + + assign rw_en = (mode_sample_flag == 1 && done_o === 0) ? 1 : 0; + assign desync_flag = ~rst_intl | desynch_set | crc_err_flag | id_error_flag; + + always @(posedge cclk_in or posedge desync_flag) + if (desync_flag == 1) begin + pack_in_reg <= 16'b0; + new_data_in_flag <= 0; + bus_sync_flag <= 0; + wr_cnt <= 0; + wr_flag <= 1; + tmp_dword1 <= 32'b0; + tmp_dword2 <= 32'b0; + end + else begin + if (rw_en == 1 ) begin + if (bus_sync_flag == 0) begin + tmp_dword1 = { tmp_dword2[30:0], ds_in}; + if (tmp_dword1[31:0] == 32'hAA995566) begin + bus_sync_flag <= 1; + new_data_in_flag <= 0; + tmp_dword2 <= 32'b0; + pack_in_reg <= 16'b0; + wr_cnt <= 0; + end + else begin + tmp_dword2 <= tmp_dword1; + end + end + else begin + pack_in_reg <= {pack_in_reg[14:0], ds_in}; + if (wr_cnt == 15) begin + new_data_in_flag <= 1; + wr_cnt <= 0; + end + else begin + new_data_in_flag <= 0; + wr_cnt <= wr_cnt + 1; + end + end + end + else begin //rw_en = 0 + new_data_in_flag <= 0; + end + end + + always @(negedge cclk_in or negedge rst_intl) + if (rst_intl == 0) begin + conti_data_flag <= 0; + conti_data_cnt <= 5'b0; + cmd_wr_flag <= 0; + cmd_rd_flag <= 0; + id_error_flag <= 0; + far_maj_min_flag <= 0; + cmd_reg_new_flag <= 0; + crc_curr <= 22'b0; + crc_ck <= 0; + csbo_cnt <= 0; + csbo_flag <= 0; + downcont <= 28'b0; + rd_data_cnt <= 0; + end + else begin + if (crc_reset == 1 ) begin + crc_reg <= 32'b0; + exp_sign_reg <= 32'b0; + crc_ck <= 0; + crc_curr <= 22'b0; + end + if (desynch_set == 1 || crc_err_flag==1) begin + conti_data_flag <= 0; + conti_data_cnt <= 5'b0; + cmd_wr_flag <= 0; + cmd_rd_flag <= 0; + far_maj_min_flag <= 0; + cmd_reg_new_flag <= 0; + crc_ck <= 0; + csbo_cnt <= 0; + csbo_flag <= 0; + downcont <= 28'b0; + rd_data_cnt <= 0; + end + + if (new_data_in_flag == 1 && wr_flag == 1) begin + if (conti_data_flag == 1 ) begin + if (type2_flag == 0) begin + case (reg_addr) + 6'b000000 : if (conti_data_cnt == 5'b00001) begin + crc_reg[15:0] <= pack_in_reg; + crc_ck <= 1; + end + else if (conti_data_cnt == 5'b00010) begin + crc_reg[31:16] <= pack_in_reg; + crc_ck <= 0; + end + 6'b000001 : if (conti_data_cnt == 5'b00010) begin + far_maj_reg <= pack_in_reg; + far_maj_min_flag <=1; + end + else if (conti_data_cnt == 5'b00001) begin + if (far_maj_min_flag ==1) begin + far_min_reg <= pack_in_reg; + far_maj_min_flag <= 0; + end + else + far_maj_reg <= pack_in_reg; + end + 6'b000010 : far_min_reg <= pack_in_reg; + 6'b000011 : fdri_reg <= pack_in_reg; + 6'b000101 : cmd_reg <= pack_in_reg[4:0]; + 6'b000110 : begin + ctl_reg_tmp = (pack_in_reg & ~mask_reg) | (ctl_reg & mask_reg); + ctl_reg <= {8'b0, ctl_reg_tmp[7:0]}; + end + 6'b000111 : mask_reg <= pack_in_reg; + 6'b001001 : lout_reg <= pack_in_reg; + 6'b001010 : cor1_reg <= pack_in_reg; + 6'b001011 : cor2_reg <= pack_in_reg; + 6'b001100 : pwrdn_reg <= pack_in_reg; + 6'b001101 : flr_reg <= pack_in_reg; + 6'b001110 : + if (conti_data_cnt == 5'b00001) begin + idcode_reg[15:0] <= pack_in_reg; + idcode_tmp = {idcode_reg[31:16], pack_in_reg}; + $display("IDCode: %x", idcode_tmp); + + if (idcode_tmp[27:0] != DEVICE_ID[27:0]) begin + id_error_flag <= 1; + $display("Error : written value to IDCODE register is %h which does not match DEVICE ID %h on SIM_CONFIG_S6_SERIAL instance %m at time %t.", idcode_tmp, DEVICE_ID, $time); + end + else + id_error_flag <= 0; + end + else if (conti_data_cnt == 5'b00010) + idcode_reg[31:16] <= pack_in_reg; + + 6'b001111 : cwdt_reg <= pack_in_reg; + 6'b010000 : hc_opt_reg[6:0] <= pack_in_reg[6:0]; + 6'b010011 : general1_reg <= pack_in_reg; + 6'b010100 : general2_reg <= pack_in_reg; + 6'b010101 : general3_reg <= pack_in_reg; + 6'b010110 : general4_reg <= pack_in_reg; + 6'b010111 : general5_reg <= pack_in_reg; + 6'b011000 : mode_reg <= pack_in_reg; + 6'b011001 : pu_gwe_reg <= pack_in_reg; + 6'b011010 : pu_gts_reg <= pack_in_reg; + 6'b011011 : mfwr_reg <= pack_in_reg; + 6'b011100 : cclk_freq_reg <= pack_in_reg; + 6'b011101 : seu_opt_reg <= pack_in_reg; + 6'b011110 : if (conti_data_cnt == 5'b00001) + exp_sign_reg[15:0] <= pack_in_reg; + else if (conti_data_cnt == 5'b00010) + exp_sign_reg[31:16] <= pack_in_reg; + 6'b011111 : if (conti_data_cnt == 5'b00001) + rdbk_sign_reg[15:0] <= pack_in_reg; + else if (conti_data_cnt == 5'b00010) + rdbk_sign_reg[31:16] <= pack_in_reg; + 6'b100001 : eye_mask_reg <= pack_in_reg; + 6'b100010 : cbc_reg <= pack_in_reg; + endcase + + if (reg_addr == 6'b000101) + cmd_reg_new_flag <= 1; + else + cmd_reg_new_flag <= 0; + + if (crc_en == 1) begin + if (reg_addr == 6'h05 && pack_in_reg[4:0] == 5'b00111) + crc_curr[21:0] = 22'b0; + else begin + if (reg_addr != 6'h04 && reg_addr != 6'h08 && reg_addr != 6'h09 && + reg_addr != 6'h12 && reg_addr != 6'h1f && + reg_addr != 6'h20 && reg_addr != 6'h00) begin + + crc_input[21:0] = {reg_addr[5:0], pack_in_reg}; + crc_new[21:0] = crc_next(crc_curr, crc_input); + crc_curr[21:0] <= crc_new; + end + end + end + end + else begin // type2_flag + if (conti_data_cnt == 2) + downcont[27:16] <= pack_in_reg[11:0]; + else if (conti_data_cnt ==1) + downcont[15:0] <= pack_in_reg; + end + + if (conti_data_cnt <= 5'b00001) begin + conti_data_cnt <= 5'b0; + type2_flag <= 0; + end + else + conti_data_cnt <= conti_data_cnt - 1; + end + else begin //if (conti_data_flag == 0 ) + if ( downcont >= 1) begin + if (crc_en == 1) begin + crc_input[21:0] = {6'b000011, pack_in_reg}; //FDRI address plus data + crc_new[21:0] = crc_next(crc_curr, crc_input); + crc_curr[21:0] <= crc_new; + end + end + + if (pack_in_reg[15:13] == 3'b010 && downcont == 0 ) begin +// $display("Warning : only Type 1 Packet supported on SIM_CONFIG_S6_SERIAL instance %m at time %t.", $time); + cmd_wr_flag <= 0; + type2_flag <= 1; + conti_data_flag <= 1; + conti_data_cnt <= 5'b00010; + end + else if (pack_in_reg[15:13] == 3'b001 ) begin + if (pack_in_reg[12:11] == 2'b01 && downcont == 0) begin + if (pack_in_reg[4:0] != 5'b0) begin + cmd_rd_flag <= 1; + cmd_wr_flag <= 0; +// rd_data_cnt <= {pack_in_reg[4:0], 1'b0}; + rd_data_cnt <= 6'b000100; + conti_data_cnt <= 5'b0; + conti_data_flag = 0; + rd_reg_addr <= pack_in_reg[10:5]; + end + end + else if (pack_in_reg[12:11] == 2'b10 && downcont == 0) begin + if (pack_in_reg[15:5] == 11'b00110010010) begin // csbo reg + csbo_reg <= pack_in_reg; + csbo_cnt = pack_in_reg[4:0]; + csbo_flag <= 1; + conti_data_flag = 0; + reg_addr <= pack_in_reg[10:5]; + cmd_wr_flag <= 1; + conti_data_cnt <= 5'b0; + end + else if (pack_in_reg[4:0] != 5'b0 ) begin + cmd_wr_flag <= 1; + conti_data_flag <= 1; + conti_data_cnt <= pack_in_reg[4:0]; + reg_addr <= pack_in_reg[10:5]; + end + end + else begin + cmd_wr_flag <= 0; + conti_data_flag <= 0; + conti_data_cnt <= 5'b0; + end + end + cmd_reg_new_flag <= 0; + crc_ck <= 0; + end // if (conti_data_flag == 0 ) + + if (csbo_cnt != 0 ) begin + if (csbo_flag) + csbo_cnt <= csbo_cnt - 1; + end + else + csbo_flag <= 0; + + if (conti_data_cnt == 5'b00001 ) + conti_data_flag <= 0; + + end + + if (rw_en == 1) begin + if (rd_data_cnt == 1) begin + rd_data_cnt <= 0; + end + else if (rd_data_cnt == 0 && rd_flag == 1) + cmd_rd_flag <= 0; + else if (cmd_rd_flag == 1 && rd_flag == 1) + rd_data_cnt <= rd_data_cnt - 1; + + if (downcont >= 1 && conti_data_flag == 0 && new_data_in_flag == 1 && wr_flag == 1) + downcont <= downcont - 1; + end + if (crc_ck == 1) + crc_ck <= 0; + end + + assign crc_rst = crc_reset | ~rst_intl; + + always @(posedge cclk_in or posedge crc_rst ) + if (crc_rst == 1) + crc_err_flag <= 0; + else + if (crc_ck == 1) begin + if (crc_bypass == 1) begin + if (crc_reg[31:0] != 32'h9876defc) + crc_err_flag <= 1; + else + crc_err_flag <= 0; + end + else begin + if (crc_curr[21:0] != crc_reg[21:0]) + crc_err_flag <= 1; + else + crc_err_flag <= 0; + end + end + else + crc_err_flag <= 0; + + always @(posedge crc_err_flag or negedge rst_intl or posedge bus_sync_flag) + if (rst_intl == 0) + crc_err_flag_reg <= 0; + else if (crc_err_flag == 1) + crc_err_flag_reg <= 1; + else + crc_err_flag_reg <= 0; + + always @(posedge cclk_in or negedge rst_intl) + if (rst_intl == 0) begin + startup_set <= 0; + crc_reset <= 0; + gsr_set <= 0; + shutdown_set <= 0; + desynch_set <= 0; + reboot_set <= 0; + ghigh_b <= 0; + end + else begin + if (cmd_reg_new_flag == 1) begin + if (cmd_reg == 5'b00011) + ghigh_b <= 1; + else if (cmd_reg == 5'b01000) + ghigh_b <= 0; + + if (cmd_reg == 5'b00101) + startup_set <= 1; + if (cmd_reg == 5'b00111) + crc_reset <= 1; + if (cmd_reg == 5'b01010) + gsr_set <= 1; + if (cmd_reg == 5'b01011) + shutdown_set <= 1; + if (cmd_reg == 5'b01101) + desynch_set <= 1; + if (cmd_reg == 5'b01110) + reboot_set <= 1; + end + else begin + startup_set <= 0; + crc_reset <= 0; + gsr_set <= 0; + shutdown_set <= 0; + desynch_set <= 0; + reboot_set <= 0; + end + end + + + always @(posedge startup_set or posedge desynch_set or negedge rw_en ) + if (rw_en == 0) + startup_set_pulse <= 2'b0; + else begin + if (startup_set_pulse == 2'b00 && startup_set ==1) + startup_set_pulse <= 2'b01; + else if (desynch_set == 1 && startup_set_pulse == 2'b01) begin + startup_set_pulse <= 2'b11; + @(posedge cclk_in ) + startup_set_pulse <= 2'b00; + end + end + always @(ctl_reg) begin + if (ctl_reg[3] == 1) + persist_en = 1; + else + persist_en = 0; + + if (ctl_reg[0] == 1) + gts_usr_b = 1; + else + gts_usr_b = 0; + end + + always @(cor1_reg) + begin + if (cor1_reg[2] ==1) + done_pin_drv = 1; + else + done_pin_drv = 0; + + if (cor1_reg[4] == 1) + crc_bypass = 1; + else + crc_bypass = 0; + end + + always @(cor2_reg) begin + if (cor2_reg[15] ==1) + reset_on_err = 1; + else + reset_on_err = 0; + + done_cycle_reg = cor2_reg[11:9]; + lock_cycle_reg = cor2_reg[8:6]; + gts_cycle_reg = cor2_reg[5:3]; + gwe_cycle_reg = cor2_reg[2:0]; + end + + + assign stat_reg[15] = sync_timeout; + assign stat_reg[14] = 0; + assign stat_reg[13] = DONE; + assign stat_reg[12] = INITB; + assign stat_reg[11:9] = {1'b0, mode_pin_in}; + assign stat_reg[8:6] = 3'b0; + assign stat_reg[5] = ghigh_b; + assign stat_reg[4] = gwe_out; + assign stat_reg[3] = gts_out; + assign stat_reg[2] = 1'bx; + assign stat_reg[1] = id_error_flag; + assign stat_reg[0] = crc_err_flag_reg; + + + always @(posedge cclk_in or negedge rst_intl) + if (rst_intl == 0) begin + st_state <= STARTUP_PH0; + startup_begin_flag <= 0; + startup_end_flag <= 0; + end + else begin + if (nx_st_state == STARTUP_PH1) begin + startup_begin_flag <= 1; + startup_end_flag <= 0; + end + else if (st_state == STARTUP_PH7) begin + startup_end_flag <= 1; + startup_begin_flag <= 0; + end + if (lock_cycle_reg == 3'b111 || dcm_locked == 1 || st_state != lock_cycle_reg) begin + st_state <= nx_st_state; + end + else + st_state <= st_state; + end + + always @(st_state or startup_set_pulse or DONE ) + if (( st_state == done_cycle_reg) && (DONE != 0) || ( st_state != done_cycle_reg))begin + $display("NextState?"); + + case (st_state) + STARTUP_PH0 : if (startup_set_pulse == 2'b11 ) + nx_st_state = STARTUP_PH1; + else + nx_st_state = STARTUP_PH0; + STARTUP_PH1 : nx_st_state = STARTUP_PH2; + + STARTUP_PH2 : nx_st_state = STARTUP_PH3; + + STARTUP_PH3 : nx_st_state = STARTUP_PH4; + + STARTUP_PH4 : nx_st_state = STARTUP_PH5; + + STARTUP_PH5 : nx_st_state = STARTUP_PH6; + + STARTUP_PH6 : nx_st_state = STARTUP_PH7; + + STARTUP_PH7 : nx_st_state = STARTUP_PH0; + endcase // case (st_state) + end // if (( st_state == done_cycle_reg) && (DONE != 0) || ( st_state != done_cycle_reg)) + + + always @(posedge cclk_in or negedge rst_intl ) + if (rst_intl == 0) begin + gwe_out <= 0; + gts_out <= 1; + eos_startup <= 0; + gsr_st_out <= 1; + done_o <= 0; + end + else begin + + if ((nx_st_state == done_cycle_reg) || (st_state == done_cycle_reg)) + if (DONE != 0 || done_pin_drv == 1) + done_o <= 1'b1; + else + done_o <= 1'bz; + + if (nx_st_state == gwe_cycle_reg) begin + gwe_out <= 1; + end + + if (nx_st_state == gts_cycle_reg) begin + gts_out <= 0; + end + + if (nx_st_state == STARTUP_PH6) + gsr_st_out <= 0; + + if (nx_st_state == STARTUP_PH7) + eos_startup <= 1; + + end + + + assign gsr_out = gsr_st_out | gsr_cmd_out; + +function [21:0] crc_next; + input [21:0] crc_curr; + input [21:0] crc_input; + integer i_crc; + begin + for(i_crc = 21; i_crc > 15; i_crc=i_crc -1) + crc_next[i_crc] = crc_curr[i_crc-1] ^ crc_input[i_crc]; + + crc_next[15] = crc_curr[14] ^ crc_input[15] ^ crc_curr[21]; + + for(i_crc = 14; i_crc > 12; i_crc=i_crc -1) + crc_next[i_crc] = crc_curr[i_crc-1] ^ crc_input[i_crc]; + + crc_next[12] = crc_curr[11] ^ crc_input[12] ^ crc_curr[21]; + + for(i_crc = 11; i_crc > 7; i_crc=i_crc -1) + crc_next[i_crc] = crc_curr[i_crc-1] ^ crc_input[i_crc]; + + crc_next[7] = crc_curr[6] ^ crc_input[7] ^ crc_curr[21]; + + for(i_crc = 6; i_crc > 0; i_crc=i_crc -1) + crc_next[i_crc] = crc_curr[i_crc-1] ^ crc_input[i_crc]; + + crc_next[0] = crc_input[0] ^ crc_curr[21]; + + end +endfunction + +function [7:0] bit_revers8; + input [7:0] din8; + begin + bit_revers8[0] = din8[7]; + bit_revers8[1] = din8[6]; + bit_revers8[2] = din8[5]; + bit_revers8[3] = din8[4]; + bit_revers8[4] = din8[3]; + bit_revers8[5] = din8[2]; + bit_revers8[6] = din8[1]; + bit_revers8[7] = din8[0]; + end +endfunction + + + +endmodule diff --git a/testbench/wishbone/wb_xilinx_fpga_loader/glbl.v b/testbench/wishbone/wb_xilinx_fpga_loader/glbl.v new file mode 100644 index 0000000000000000000000000000000000000000..69ac7306f1e99374977a5740f38759609a44df6f --- /dev/null +++ b/testbench/wishbone/wb_xilinx_fpga_loader/glbl.v @@ -0,0 +1,65 @@ +// $Header: /devl/xcs/repo/env/Databases/CAEInterfaces/verunilibs/data/glbl.v,v 1.14 2010/10/28 20:44:00 fphillip Exp $ + +`timescale 1 ps / 1 ps + +module glbl (); + + parameter ROC_WIDTH = 100000; + parameter TOC_WIDTH = 0; + +//-------- STARTUP Globals -------------- + wire GSR; + wire GTS; + wire GWE; + wire PRLD; + tri1 p_up_tmp; + tri (weak1, strong0) PLL_LOCKG = p_up_tmp; + + wire PROGB_GLBL; + + reg GSR_int; + reg GTS_int; + reg PRLD_int; + +//-------- JTAG Globals -------------- + wire JTAG_TDO_GLBL; + wire JTAG_TCK_GLBL; + wire JTAG_TDI_GLBL; + wire JTAG_TMS_GLBL; + wire JTAG_TRST_GLBL; + + reg JTAG_CAPTURE_GLBL; + reg JTAG_RESET_GLBL; + reg JTAG_SHIFT_GLBL; + reg JTAG_UPDATE_GLBL; + reg JTAG_RUNTEST_GLBL; + + reg JTAG_SEL1_GLBL = 0; + reg JTAG_SEL2_GLBL = 0 ; + reg JTAG_SEL3_GLBL = 0; + reg JTAG_SEL4_GLBL = 0; + + reg JTAG_USER_TDO1_GLBL = 1'bz; + reg JTAG_USER_TDO2_GLBL = 1'bz; + reg JTAG_USER_TDO3_GLBL = 1'bz; + reg JTAG_USER_TDO4_GLBL = 1'bz; + + assign (weak1, weak0) GSR = GSR_int; + assign (weak1, weak0) GTS = GTS_int; + assign (weak1, weak0) PRLD = PRLD_int; + + initial begin + GSR_int = 1'b1; + PRLD_int = 1'b1; + #(ROC_WIDTH) + GSR_int = 1'b0; + PRLD_int = 1'b0; + end + + initial begin + GTS_int = 1'b1; + #(TOC_WIDTH) + GTS_int = 1'b0; + end + +endmodule diff --git a/testbench/wishbone/wb_xilinx_fpga_loader/main.sv b/testbench/wishbone/wb_xilinx_fpga_loader/main.sv new file mode 100644 index 0000000000000000000000000000000000000000..38ecc26ed13b58772862910f9fffdbb99c8b56cd --- /dev/null +++ b/testbench/wishbone/wb_xilinx_fpga_loader/main.sv @@ -0,0 +1,120 @@ +`timescale 1ns/1ps + +`include "simdrv_defs.svh" +`include "if_wb_master.svh" + +`include "regs/xloader_regs.vh" + +module main; + + reg clk_sys=1, rst_n=0; + + always + #5ns clk_sys <= ~clk_sys; + + initial begin + repeat(5) @(posedge clk_sys); + rst_n <= 1; + end + + + IWishboneMaster #(32, 32) U_WB + ( + .clk_i(clk_sys), + .rst_n_i(rst_n) + ); + + + wire cclk, din, program_b, init_b, done, suspend; + wire [1:0] m; + + wb_xilinx_fpga_loader DUT + ( + .clk_sys_i (clk_sys), + .rst_n_i (rst_n), + + .wb_adr_i (U_WB.master.adr), + .wb_dat_i (U_WB.master.dat_o), + .wb_dat_o (U_WB.master.dat_i), + .wb_cyc_i (U_WB.master.cyc), + .wb_stb_i (U_WB.master.stb), + .wb_we_i (U_WB.master.we), + .wb_ack_o (U_WB.master.ack), + .wb_sel_i (U_WB.master.sel), + + .xlx_cclk_o (cclk), + .xlx_din_o (din), + .xlx_program_b_o (program_b), + .xlx_init_b_i (init_b), + .xlx_done_i (done), + .xlx_suspend_o (suspend), + + .xlx_m_o (m) + ); + + + SIM_CONFIG_S6_SERIAL2 + #( + .DEVICE_ID(32'h34000093) // xc6slx150t + ) U_serial_sim + ( + .DONE(done), + .CCLK(cclk), + .DIN(din), + .INITB(init_b), + .M(m), + .PROGB(program_b) + ); + + task load_bitstream(CBusAccessor acc, string filename); + int f,i; + uint64_t csr; + + + acc.write( `ADDR_XLDR_CSR, `XLDR_CSR_SWRST ); + acc.write( `ADDR_XLDR_CSR, `XLDR_CSR_START | `XLDR_CSR_MSBF); + f = $fopen(filename, "r"); + + while(!$feof(f)) + begin + uint64_t rval; + acc.read(`ADDR_XLDR_FIFO_CSR, rval); + + if(!(rval&`XLDR_FIFO_CSR_FULL)) begin + int n; + bit [31:0] word; + + n = $fread(word, f); + acc.write(`ADDR_XLDR_FIFO_R0, (n - 1) | ($feof(f) ? `XLDR_FIFO_R0_XLAST : 0)); + acc.write(`ADDR_XLDR_FIFO_R1, word); + end + end + + $fclose(f); + + while(1) begin + acc.read( `ADDR_XLDR_CSR, csr); + if(csr & `XLDR_CSR_DONE) begin + $display("Bitstream loaded, status: %s", (csr & `XLDR_CSR_ERROR ? "ERROR" : "OK")); + break; + end + end + endtask + + + initial begin + CBusAccessor acc; + int i; + + #1000ns; + acc = U_WB.get_accessor(); + + /* Load a sample spartan-6 bitstream */ + + load_bitstream(acc, "sample_bitstream/crc_gen.bin"); + $stop; + + end // initial begin + +endmodule // main + diff --git a/testbench/wishbone/wb_xilinx_fpga_loader/run.do b/testbench/wishbone/wb_xilinx_fpga_loader/run.do new file mode 100644 index 0000000000000000000000000000000000000000..5703c6b2b7b02f13abb362845248eafcf577ff87 --- /dev/null +++ b/testbench/wishbone/wb_xilinx_fpga_loader/run.do @@ -0,0 +1,8 @@ +make + +vsim work.main -voptargs="+acc" + +do wave.do +run 30ms +wave zoomfull +radix -hex \ No newline at end of file diff --git a/testbench/wishbone/wb_xilinx_fpga_loader/sample_bitstream/Manifest.py b/testbench/wishbone/wb_xilinx_fpga_loader/sample_bitstream/Manifest.py new file mode 100644 index 0000000000000000000000000000000000000000..1ca929fa31539937389045c995b89416558b783b --- /dev/null +++ b/testbench/wishbone/wb_xilinx_fpga_loader/sample_bitstream/Manifest.py @@ -0,0 +1,10 @@ +target = "xilinx" +action = "synthesis" + +files = "crc_gen.vhd" + +syn_device = "xc6slx4" +syn_grade = "-2" +syn_package = "csg225" +syn_top = "crc_gen" +syn_project = "test.xise" diff --git a/testbench/wishbone/wb_xilinx_fpga_loader/sample_bitstream/crc_gen.vhd b/testbench/wishbone/wb_xilinx_fpga_loader/sample_bitstream/crc_gen.vhd new file mode 100644 index 0000000000000000000000000000000000000000..6e589abe203bd96fc8019594cefa4788824bdae0 --- /dev/null +++ b/testbench/wishbone/wb_xilinx_fpga_loader/sample_bitstream/crc_gen.vhd @@ -0,0 +1,245 @@ +---------------------------------------------------------------------- +---- ---- +---- Ultimate CRC. ---- +---- ---- +---- This file is part of the ultimate CRC projectt ---- +---- http://www.opencores.org/cores/ultimate_crc/ ---- +---- ---- +---- Description ---- +---- CRC generator/checker, parallel implementation. ---- +---- ---- +---- ---- +---- To Do: ---- +---- - ---- +---- ---- +---- Author(s): ---- +---- - Geir Drange, gedra@opencores.org ---- +---- ---- +---------------------------------------------------------------------- +---- ---- +---- Copyright (C) 2005 Authors and OPENCORES.ORG ---- +---- ---- +---- This source file may be used and distributed without ---- +---- restriction provided that this copyright statement is not ---- +---- removed from the file and that any derivative work contains ---- +---- the original copyright notice and the associated disclaimer. ---- +---- ---- +---- This source file is free software; you can redistribute it ---- +---- and/or modify it under the terms of the GNU General ---- +---- Public License as published by the Free Software Foundation; ---- +---- either version 2.0 of the License, or (at your option) any ---- +---- later version. ---- +---- ---- +---- This source is distributed in the hope that it will be ---- +---- useful, but WITHOUT ANY WARRANTY; without even the implied ---- +---- warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR ---- +---- PURPOSE. See the GNU General Public License for more details.---- +---- ---- +---- You should have received a copy of the GNU General ---- +---- Public License along with this source; if not, download it ---- +---- from http://www.gnu.org/licenses/gpl.txt ---- +---- ---- +---------------------------------------------------------------------- +-- +-- CVS Revision History +-- +-- $Log: ucrc_par.vhd,v $ +-- Revision 1.1 2005/05/09 15:58:38 gedra +-- Parallel implementation +-- +-- Modified by T.W. for use in WhiteRabbit endpoint +-- + +library ieee; +use ieee.std_logic_1164.all; + +entity crc_gen is + generic ( +-- polynomial of our CRC generator + g_polynomial : std_logic_vector := x"04C11DB7"; +-- initial (after-reset) value of CRC + g_init_value : std_logic_vector := x"ffffffff"; +-- residual value of CRC when matched + g_residue : std_logic_vector := x"38fb2284"; +-- width of full data input word + g_data_width : integer range 2 to 256 := 16; +-- width of smaller-than-full data input word + g_half_width : integer range 2 to 256 := 8; +-- use synchronous reset when 1 + g_sync_reset : integer range 0 to 1 := 0; +-- dual-width mode (g_data_width - wide input word when 1 and g_half_width input +-- word when 0) + g_dual_width : integer range 0 to 1 := 0); -- use sync./async reset + port ( + clk_i : in std_logic; -- clock + rst_i : in std_logic; -- reset, active high + en_i : in std_logic; -- enable input, active high + half_i : in std_logic; -- 1: input word has g_half_width bits + -- 0: input word has g_data_width bits + + data_i : in std_logic_vector(g_data_width - 1 downto 0); -- data input + + match_o : out std_logic; -- CRC match flag: 1 - CRC matches + + crc_o : out std_logic_vector(g_polynomial'length - 1 downto 0)); -- CRC + -- output value +end crc_gen; + +architecture rtl of crc_gen is + + function f_reverse_vector (a : in std_logic_vector) + return std_logic_vector is + variable v_result : std_logic_vector(a'reverse_range); + begin + for i in a'range loop + v_result(i) := a(i); + end loop; + return v_result; + end; + + constant msb : integer := g_polynomial'length - 1; + constant init_msb : integer := g_init_value'length - 1; + constant p : std_logic_vector(msb downto 0) := g_polynomial; + constant dw : integer := g_data_width; + constant pw : integer := g_polynomial'length; + type fb_array is array (dw downto 1) of std_logic_vector(msb downto 0); + type dmsb_array is array (dw downto 1) of std_logic_vector(msb downto 1); + signal crca : fb_array; + signal da, ma : dmsb_array; + signal crc, zero : std_logic_vector(msb downto 0); + signal arst, srst : std_logic; + + signal a, b : std_logic_vector(g_polynomial'length - 1 downto 0); + signal data_i2 : std_logic_vector(15 downto 0); + signal en_d0 : std_logic; + signal half_d0 : std_logic; + signal crc_tmp : std_logic_vector(31 downto 0); + signal crc_int : std_logic_vector(31 downto 0); + + + +begin + + a <= g_init_value; + b <= g_polynomial; + +-- Parameter checking: Invalid generics will abort simulation/synthesis + PCHK1 : if msb /= init_msb generate + process + begin + report "g_polynomial and g_init_value vectors must be equal length!" + severity failure; + wait; + end process; + end generate PCHK1; + + PCHK2 : if (msb < 3) or (msb > 31) generate + process + begin + report "g_polynomial must be of order 4 to 32!" + severity failure; + wait; + end process; + end generate PCHK2; + + PCHK3 : if p(0) /= '1' generate -- LSB must be 1 + process + begin + report "g_polynomial must have lsb set to 1!" + severity failure; + wait; + end process; + end generate PCHK3; + + data_i2(15 downto 0) <= (data_i(7 downto 0) & data_i(15 downto 8)); +-- data_i2(15 downto 0) <= f_reverse_vector(data_i(15 downto 0)); + +-- Generate vector of each data bit + CA : for i in 1 to dw generate -- data bits + DAT : for j in 1 to msb generate + da(i)(j) <= data_i2(i - 1); + end generate DAT; + end generate CA; + +-- Generate vector of each CRC MSB + MS0 : for i in 1 to msb generate + ma(1)(i) <= crc(msb); + end generate MS0; + MSP : for i in 2 to dw generate + MSU : for j in 1 to msb generate + ma(i)(j) <= crca(i - 1)(msb); + end generate MSU; + end generate MSP; + +-- Generate feedback matrix + crca(1)(0) <= da(1)(1) xor crc(msb); + crca(1)(msb downto 1) <= crc(msb - 1 downto 0) xor ((da(1) xor ma(1)) and p(msb downto 1)); + FB : for i in 2 to dw generate + crca(i)(0) <= da(i)(1) xor crca(i - 1)(msb); + crca(i)(msb downto 1) <= crca(i - 1)(msb - 1 downto 0) xor + ((da(i) xor ma(i)) and p(msb downto 1)); + end generate FB; + +-- Reset signal + SR : if g_sync_reset = 1 generate + srst <= rst_i; + arst <= '0'; + end generate SR; + AR : if g_sync_reset = 0 generate + srst <= '0'; + arst <= rst_i; + end generate AR; + +-- CRC process + crc_tmp <= f_reverse_vector(not crc); + crc_int <= crc_tmp(7 downto 0) & crc_tmp(15 downto 8) & crc_tmp(23 downto 16) & crc_tmp(31 downto 24); + zero <= (others => '0'); + + crc_o <= crc_int; + + CRCP : process (clk_i, arst) + begin + if arst = '1' then -- async. reset + crc <= g_init_value; + half_d0 <= '0'; + elsif rising_edge(clk_i) then + if srst = '1' then -- sync. reset + crc <= g_init_value; + elsif en_i = '1' then + + if(half_i = '1' and g_dual_width = 1) then + crc <= crca(g_half_width); + else + crc <= crca(g_data_width); + end if; + end if; + end if; + end process; + + match_gen : process (clk_i, arst) + begin + if arst = '1' then -- async. reset + match_o <= '0'; + en_d0 <= '0'; + elsif rising_edge(clk_i) then + if srst = '1' then -- sync. reset + match_o <= '0'; + en_d0 <= '0'; + else + en_d0 <= en_i; + + if(en_d0 = '1') then + if crc_int = g_residue then + match_o <= '1'; + else + match_o <= '0'; + end if; + end if; + end if; + end if; + end process; + + + +end rtl; + diff --git a/testbench/wishbone/wb_xilinx_fpga_loader/sample_bitstream/test.xise b/testbench/wishbone/wb_xilinx_fpga_loader/sample_bitstream/test.xise new file mode 100644 index 0000000000000000000000000000000000000000..fa9884eb6f4908fea3e2538c5c86256129800530 --- /dev/null +++ b/testbench/wishbone/wb_xilinx_fpga_loader/sample_bitstream/test.xise @@ -0,0 +1,348 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no" ?> +<project xmlns="http://www.xilinx.com/XMLSchema" xmlns:xil_pn="http://www.xilinx.com/XMLSchema"> + + <header> + <!-- ISE source project file created by Project Navigator. --> + <!-- --> + <!-- This file contains project source information including a list of --> + <!-- project source files, project and process properties. This file, --> + <!-- along with the project source files, is sufficient to open and --> + <!-- implement in ISE Project Navigator. --> + <!-- --> + <!-- Copyright (c) 1995-2011 Xilinx, Inc. All rights reserved. --> + </header> + + <version xil_pn:ise_version="13.1" xil_pn:schema_version="2"/> + + <files> + <file xil_pn:name="crc_gen.vhd" xil_pn:type="FILE_VHDL"> + <association xil_pn:name="Implementation" xil_pn:seqID="1"/> + </file> + </files> + + <properties> + <property xil_pn:name="AES Initial Vector spartan6" xil_pn:value="" xil_pn:valueState="default"/> + <property xil_pn:name="AES Key (Hex String) spartan6" xil_pn:value="" xil_pn:valueState="default"/> + <property xil_pn:name="Add I/O Buffers" xil_pn:value="true" xil_pn:valueState="default"/> + <property xil_pn:name="Allow Logic Optimization Across Hierarchy" xil_pn:value="false" xil_pn:valueState="default"/> + <property xil_pn:name="Allow SelectMAP Pins to Persist" xil_pn:value="false" xil_pn:valueState="default"/> + <property xil_pn:name="Allow Unexpanded Blocks" xil_pn:value="false" xil_pn:valueState="default"/> + <property xil_pn:name="Allow Unmatched LOC Constraints" xil_pn:value="false" xil_pn:valueState="default"/> + <property xil_pn:name="Allow Unmatched Timing Group Constraints" xil_pn:value="false" xil_pn:valueState="default"/> + <property xil_pn:name="Analysis Effort Level" xil_pn:value="Standard" xil_pn:valueState="default"/> + <property xil_pn:name="Asynchronous To Synchronous" xil_pn:value="false" xil_pn:valueState="default"/> + <property xil_pn:name="Auto Implementation Compile Order" xil_pn:value="false" xil_pn:valueState="non-default"/> + <property xil_pn:name="Auto Implementation Top" xil_pn:value="false" xil_pn:valueState="non-default"/> + <property xil_pn:name="Automatic BRAM Packing" xil_pn:value="false" xil_pn:valueState="default"/> + <property xil_pn:name="Automatically Insert glbl Module in the Netlist" xil_pn:value="true" xil_pn:valueState="default"/> + <property xil_pn:name="Automatically Run Generate Target PROM/ACE File" xil_pn:value="false" xil_pn:valueState="default"/> + <property xil_pn:name="BRAM Utilization Ratio" xil_pn:value="100" xil_pn:valueState="default"/> + <property xil_pn:name="Bring Out Global Set/Reset Net as a Port" xil_pn:value="false" xil_pn:valueState="default"/> + <property xil_pn:name="Bring Out Global Tristate Net as a Port" xil_pn:value="false" xil_pn:valueState="default"/> + <property xil_pn:name="Bus Delimiter" xil_pn:value="<>" xil_pn:valueState="default"/> + <property xil_pn:name="Case" xil_pn:value="Maintain" xil_pn:valueState="default"/> + <property xil_pn:name="Case Implementation Style" xil_pn:value="None" xil_pn:valueState="default"/> + <property xil_pn:name="Change Device Speed To" xil_pn:value="-2" xil_pn:valueState="default"/> + <property xil_pn:name="Change Device Speed To Post Trace" xil_pn:value="-2" xil_pn:valueState="default"/> + <property xil_pn:name="Combinatorial Logic Optimization" xil_pn:value="false" xil_pn:valueState="default"/> + <property xil_pn:name="Compile EDK Simulation Library" xil_pn:value="false" xil_pn:valueState="default"/> + <property xil_pn:name="Compile SIMPRIM (Timing) Simulation Library" xil_pn:value="true" xil_pn:valueState="default"/> + <property xil_pn:name="Compile UNISIM (Functional) Simulation Library" xil_pn:value="true" xil_pn:valueState="default"/> + <property xil_pn:name="Compile XilinxCoreLib (CORE Generator) Simulation Library" xil_pn:value="true" xil_pn:valueState="default"/> + <property xil_pn:name="Compile for HDL Debugging" xil_pn:value="true" xil_pn:valueState="default"/> + <property xil_pn:name="Configuration Pin Done" xil_pn:value="Pull Up" xil_pn:valueState="default"/> + <property xil_pn:name="Configuration Pin Program" xil_pn:value="Pull Up" xil_pn:valueState="default"/> + <property xil_pn:name="Configuration Rate spartan6" xil_pn:value="2" xil_pn:valueState="default"/> + <property xil_pn:name="Correlate Output to Input Design" xil_pn:value="false" xil_pn:valueState="default"/> + <property xil_pn:name="Create ASCII Configuration File" xil_pn:value="false" xil_pn:valueState="default"/> + <property xil_pn:name="Create Binary Configuration File" xil_pn:value="true" xil_pn:valueState="non-default"/> + <property xil_pn:name="Create Bit File" xil_pn:value="true" xil_pn:valueState="default"/> + <property xil_pn:name="Create I/O Pads from Ports" xil_pn:value="false" xil_pn:valueState="default"/> + <property xil_pn:name="Create IEEE 1532 Configuration File spartan6" xil_pn:value="false" xil_pn:valueState="default"/> + <property xil_pn:name="Create Logic Allocation File" xil_pn:value="false" xil_pn:valueState="default"/> + <property xil_pn:name="Create Mask File" xil_pn:value="false" xil_pn:valueState="default"/> + <property xil_pn:name="Create ReadBack Data Files" xil_pn:value="false" xil_pn:valueState="default"/> + <property xil_pn:name="Cross Clock Analysis" xil_pn:value="false" xil_pn:valueState="default"/> + <property xil_pn:name="DSP Utilization Ratio" xil_pn:value="100" xil_pn:valueState="default"/> + <property xil_pn:name="Delay Values To Be Read from SDF" xil_pn:value="Setup Time" xil_pn:valueState="default"/> + <property xil_pn:name="Device" xil_pn:value="xc6slx4" xil_pn:valueState="default"/> + <property xil_pn:name="Device Family" xil_pn:value="Spartan6" xil_pn:valueState="non-default"/> + <property xil_pn:name="Device Speed Grade/Select ABS Minimum" xil_pn:value="-2" xil_pn:valueState="default"/> + <property xil_pn:name="Disable Detailed Package Model Insertion" xil_pn:value="false" xil_pn:valueState="default"/> + <property xil_pn:name="Do Not Escape Signal and Instance Names in Netlist" xil_pn:value="false" xil_pn:valueState="default"/> + <property xil_pn:name="Done (Output Events)" xil_pn:value="Default (4)" xil_pn:valueState="default"/> + <property xil_pn:name="Drive Awake Pin During Suspend/Wake Sequence spartan6" xil_pn:value="false" xil_pn:valueState="default"/> + <property xil_pn:name="Drive Done Pin High" xil_pn:value="false" xil_pn:valueState="default"/> + <property xil_pn:name="Enable BitStream Compression" xil_pn:value="false" xil_pn:valueState="default"/> + <property xil_pn:name="Enable Cyclic Redundancy Checking (CRC) spartan6" xil_pn:value="true" xil_pn:valueState="default"/> + <property xil_pn:name="Enable Debugging of Serial Mode BitStream" xil_pn:value="false" xil_pn:valueState="default"/> + <property xil_pn:name="Enable External Master Clock spartan6" xil_pn:value="false" xil_pn:valueState="default"/> + <property xil_pn:name="Enable Internal Done Pipe" xil_pn:value="true" xil_pn:valueState="non-default"/> + <property xil_pn:name="Enable Message Filtering" xil_pn:value="false" xil_pn:valueState="default"/> + <property xil_pn:name="Enable Multi-Pin Wake-Up Suspend Mode spartan6" xil_pn:value="false" xil_pn:valueState="default"/> + <property xil_pn:name="Enable Multi-Threading" xil_pn:value="2" xil_pn:valueState="non-default"/> + <property xil_pn:name="Enable Multi-Threading par spartan6" xil_pn:value="Off" xil_pn:valueState="default"/> + <property xil_pn:name="Enable Outputs (Output Events)" xil_pn:value="Default (5)" xil_pn:valueState="default"/> + <property xil_pn:name="Enable Suspend/Wake Global Set/Reset spartan6" xil_pn:value="false" xil_pn:valueState="default"/> + <property xil_pn:name="Encrypt Bitstream spartan6" xil_pn:value="false" xil_pn:valueState="default"/> + <property xil_pn:name="Encrypt Key Select spartan6" xil_pn:value="BBRAM" xil_pn:valueState="default"/> + <property xil_pn:name="Equivalent Register Removal Map" xil_pn:value="true" xil_pn:valueState="default"/> + <property xil_pn:name="Equivalent Register Removal XST" xil_pn:value="true" xil_pn:valueState="default"/> + <property xil_pn:name="Exclude Compilation of Deprecated EDK Cores" xil_pn:value="true" xil_pn:valueState="default"/> + <property xil_pn:name="Exclude Compilation of EDK Sub-Libraries" xil_pn:value="false" xil_pn:valueState="default"/> + <property xil_pn:name="Extra Cost Tables Map" xil_pn:value="0" xil_pn:valueState="default"/> + <property xil_pn:name="Extra Effort (Highest PAR level only)" xil_pn:value="None" xil_pn:valueState="default"/> + <property xil_pn:name="FPGA Start-Up Clock" xil_pn:value="CCLK" xil_pn:valueState="default"/> + <property xil_pn:name="FSM Encoding Algorithm" xil_pn:value="Auto" xil_pn:valueState="default"/> + <property xil_pn:name="FSM Style" xil_pn:value="LUT" xil_pn:valueState="default"/> + <property xil_pn:name="Filter Files From Compile Order" xil_pn:value="true" xil_pn:valueState="default"/> + <property xil_pn:name="Flatten Output Netlist" xil_pn:value="false" xil_pn:valueState="default"/> + <property xil_pn:name="Functional Model Target Language ArchWiz" xil_pn:value="Verilog" xil_pn:valueState="default"/> + <property xil_pn:name="Functional Model Target Language Coregen" xil_pn:value="Verilog" xil_pn:valueState="default"/> + <property xil_pn:name="Functional Model Target Language Schematic" xil_pn:value="Verilog" xil_pn:valueState="default"/> + <property xil_pn:name="GTS Cycle During Suspend/Wakeup Sequence spartan6" xil_pn:value="4" xil_pn:valueState="default"/> + <property xil_pn:name="GWE Cycle During Suspend/Wakeup Sequence spartan6" xil_pn:value="5" xil_pn:valueState="default"/> + <property xil_pn:name="Generate Architecture Only (No Entity Declaration)" xil_pn:value="false" xil_pn:valueState="default"/> + <property xil_pn:name="Generate Asynchronous Delay Report" xil_pn:value="false" xil_pn:valueState="default"/> + <property xil_pn:name="Generate Clock Region Report" xil_pn:value="false" xil_pn:valueState="default"/> + <property xil_pn:name="Generate Constraints Interaction Report" xil_pn:value="false" xil_pn:valueState="default"/> + <property xil_pn:name="Generate Constraints Interaction Report Post Trace" xil_pn:value="false" xil_pn:valueState="default"/> + <property xil_pn:name="Generate Datasheet Section" xil_pn:value="true" xil_pn:valueState="default"/> + <property xil_pn:name="Generate Datasheet Section Post Trace" xil_pn:value="true" xil_pn:valueState="default"/> + <property xil_pn:name="Generate Detailed MAP Report" xil_pn:value="false" xil_pn:valueState="default"/> + <property xil_pn:name="Generate Multiple Hierarchical Netlist Files" xil_pn:value="false" xil_pn:valueState="default"/> + <property xil_pn:name="Generate Post-Place & Route Power Report" xil_pn:value="false" xil_pn:valueState="default"/> + <property xil_pn:name="Generate Post-Place & Route Simulation Model" xil_pn:value="false" xil_pn:valueState="default"/> + <property xil_pn:name="Generate RTL Schematic" xil_pn:value="Yes" xil_pn:valueState="default"/> + <property xil_pn:name="Generate SAIF File for Power Optimization/Estimation Par" xil_pn:value="false" xil_pn:valueState="default"/> + <property xil_pn:name="Generate Testbench File" xil_pn:value="false" xil_pn:valueState="default"/> + <property xil_pn:name="Generate Timegroups Section" xil_pn:value="false" xil_pn:valueState="default"/> + <property xil_pn:name="Generate Timegroups Section Post Trace" xil_pn:value="false" xil_pn:valueState="default"/> + <property xil_pn:name="Generics, Parameters" xil_pn:value="" xil_pn:valueState="default"/> + <property xil_pn:name="Global Optimization Goal" xil_pn:value="AllClockNets" xil_pn:valueState="default"/> + <property xil_pn:name="Global Optimization map" xil_pn:value="Off" xil_pn:valueState="default"/> + <property xil_pn:name="Global Set/Reset Port Name" xil_pn:value="GSR_PORT" xil_pn:valueState="default"/> + <property xil_pn:name="Global Tristate Port Name" xil_pn:value="GTS_PORT" xil_pn:valueState="default"/> + <property xil_pn:name="Hierarchy Separator" xil_pn:value="/" xil_pn:valueState="default"/> + <property xil_pn:name="ISim UUT Instance Name" xil_pn:value="UUT" xil_pn:valueState="default"/> + <property xil_pn:name="Ignore User Timing Constraints Map" xil_pn:value="false" xil_pn:valueState="default"/> + <property xil_pn:name="Ignore User Timing Constraints Par" xil_pn:value="false" xil_pn:valueState="default"/> + <property xil_pn:name="Implementation Top" xil_pn:value="Architecture|crc_gen" xil_pn:valueState="non-default"/> + <property xil_pn:name="Implementation Top Instance Path" xil_pn:value="/crc_gen" xil_pn:valueState="non-default"/> + <property xil_pn:name="Include 'uselib Directive in Verilog File" xil_pn:value="false" xil_pn:valueState="default"/> + <property xil_pn:name="Include SIMPRIM Models in Verilog File" xil_pn:value="false" xil_pn:valueState="default"/> + <property xil_pn:name="Include UNISIM Models in Verilog File" xil_pn:value="false" xil_pn:valueState="default"/> + <property xil_pn:name="Include sdf_annotate task in Verilog File" xil_pn:value="true" xil_pn:valueState="default"/> + <property xil_pn:name="Incremental Compilation" xil_pn:value="true" xil_pn:valueState="default"/> + <property xil_pn:name="Insert Buffers to Prevent Pulse Swallowing" xil_pn:value="true" xil_pn:valueState="default"/> + <property xil_pn:name="Instantiation Template Target Language Xps" xil_pn:value="Verilog" xil_pn:valueState="default"/> + <property xil_pn:name="JTAG Pin TCK" xil_pn:value="Pull Up" xil_pn:valueState="default"/> + <property xil_pn:name="JTAG Pin TDI" xil_pn:value="Pull Up" xil_pn:valueState="default"/> + <property xil_pn:name="JTAG Pin TDO" xil_pn:value="Pull Up" xil_pn:valueState="default"/> + <property xil_pn:name="JTAG Pin TMS" xil_pn:value="Pull Up" xil_pn:valueState="default"/> + <property xil_pn:name="Keep Hierarchy" xil_pn:value="No" xil_pn:valueState="default"/> + <property xil_pn:name="LUT Combining Map" xil_pn:value="Off" xil_pn:valueState="default"/> + <property xil_pn:name="LUT Combining Xst" xil_pn:value="Auto" xil_pn:valueState="default"/> + <property xil_pn:name="Language" xil_pn:value="VHDL" xil_pn:valueState="default"/> + <property xil_pn:name="Last Applied Goal" xil_pn:value="Balanced" xil_pn:valueState="default"/> + <property xil_pn:name="Last Applied Strategy" xil_pn:value="Xilinx Default (unlocked)" xil_pn:valueState="default"/> + <property xil_pn:name="Last Unlock Status" xil_pn:value="false" xil_pn:valueState="default"/> + <property xil_pn:name="Launch SDK after Export" xil_pn:value="true" xil_pn:valueState="default"/> + <property xil_pn:name="Library for Verilog Sources" xil_pn:value="" xil_pn:valueState="default"/> + <property xil_pn:name="Load glbl" xil_pn:value="true" xil_pn:valueState="default"/> + <property xil_pn:name="Manual Implementation Compile Order" xil_pn:value="true" xil_pn:valueState="non-default"/> + <property xil_pn:name="Map Slice Logic into Unused Block RAMs" xil_pn:value="false" xil_pn:valueState="default"/> + <property xil_pn:name="Mask Pins for Multi-Pin Wake-Up Suspend Mode spartan6" xil_pn:value="0x00" xil_pn:valueState="default"/> + <property xil_pn:name="Max Fanout" xil_pn:value="100000" xil_pn:valueState="default"/> + <property xil_pn:name="Maximum Compression" xil_pn:value="false" xil_pn:valueState="default"/> + <property xil_pn:name="Maximum Number of Lines in Report" xil_pn:value="1000" xil_pn:valueState="default"/> + <property xil_pn:name="Maximum Signal Name Length" xil_pn:value="20" xil_pn:valueState="default"/> + <property xil_pn:name="Move First Flip-Flop Stage" xil_pn:value="true" xil_pn:valueState="default"/> + <property xil_pn:name="Move Last Flip-Flop Stage" xil_pn:value="true" xil_pn:valueState="default"/> + <property xil_pn:name="MultiBoot: Next Configuration Mode spartan6" xil_pn:value="001" xil_pn:valueState="default"/> + <property xil_pn:name="MultiBoot: Starting Address for Golden Configuration spartan6" xil_pn:value="0x00000000" xil_pn:valueState="default"/> + <property xil_pn:name="MultiBoot: Starting Address for Next Configuration spartan6" xil_pn:value="0x00000000" xil_pn:valueState="default"/> + <property xil_pn:name="MultiBoot: Use New Mode for Next Configuration spartan6" xil_pn:value="true" xil_pn:valueState="default"/> + <property xil_pn:name="MultiBoot: User-Defined Register for Failsafe Scheme spartan6" xil_pn:value="0x0000" xil_pn:valueState="default"/> + <property xil_pn:name="Netlist Hierarchy" xil_pn:value="As Optimized" xil_pn:valueState="default"/> + <property xil_pn:name="Netlist Translation Type" xil_pn:value="Timestamp" xil_pn:valueState="default"/> + <property xil_pn:name="Number of Clock Buffers" xil_pn:value="16" xil_pn:valueState="default"/> + <property xil_pn:name="Number of Paths in Error/Verbose Report" xil_pn:value="3" xil_pn:valueState="default"/> + <property xil_pn:name="Number of Paths in Error/Verbose Report Post Trace" xil_pn:value="3" xil_pn:valueState="default"/> + <property xil_pn:name="Optimization Effort spartan6" xil_pn:value="Normal" xil_pn:valueState="default"/> + <property xil_pn:name="Optimization Goal" xil_pn:value="Speed" xil_pn:valueState="default"/> + <property xil_pn:name="Optimize Instantiated Primitives" xil_pn:value="false" xil_pn:valueState="default"/> + <property xil_pn:name="Other Bitgen Command Line Options spartan6" xil_pn:value="" xil_pn:valueState="default"/> + <property xil_pn:name="Other Compiler Options" xil_pn:value="" xil_pn:valueState="default"/> + <property xil_pn:name="Other Compiler Options Map" xil_pn:value="" xil_pn:valueState="default"/> + <property xil_pn:name="Other Compiler Options Par" xil_pn:value="" xil_pn:valueState="default"/> + <property xil_pn:name="Other Compiler Options Translate" xil_pn:value="" xil_pn:valueState="default"/> + <property xil_pn:name="Other Compxlib Command Line Options" xil_pn:value="" xil_pn:valueState="default"/> + <property xil_pn:name="Other Map Command Line Options" xil_pn:value="" xil_pn:valueState="default"/> + <property xil_pn:name="Other NETGEN Command Line Options" xil_pn:value="" xil_pn:valueState="default"/> + <property xil_pn:name="Other Ngdbuild Command Line Options" xil_pn:value="" xil_pn:valueState="default"/> + <property xil_pn:name="Other Place & Route Command Line Options" xil_pn:value="" xil_pn:valueState="default"/> + <property xil_pn:name="Other Simulator Commands Behavioral" xil_pn:value="" xil_pn:valueState="default"/> + <property xil_pn:name="Other Simulator Commands Post-Map" xil_pn:value="" xil_pn:valueState="default"/> + <property xil_pn:name="Other Simulator Commands Post-Route" xil_pn:value="" xil_pn:valueState="default"/> + <property xil_pn:name="Other Simulator Commands Post-Translate" xil_pn:value="" xil_pn:valueState="default"/> + <property xil_pn:name="Other XPWR Command Line Options" xil_pn:value="" xil_pn:valueState="default"/> + <property xil_pn:name="Other XST Command Line Options" xil_pn:value="" xil_pn:valueState="default"/> + <property xil_pn:name="Output Extended Identifiers" xil_pn:value="false" xil_pn:valueState="default"/> + <property xil_pn:name="Output File Name" xil_pn:value="crc_gen" xil_pn:valueState="default"/> + <property xil_pn:name="Overwrite Compiled Libraries" xil_pn:value="false" xil_pn:valueState="default"/> + <property xil_pn:name="Pack I/O Registers into IOBs" xil_pn:value="Auto" xil_pn:valueState="default"/> + <property xil_pn:name="Pack I/O Registers/Latches into IOBs" xil_pn:value="Off" xil_pn:valueState="default"/> + <property xil_pn:name="Package" xil_pn:value="csg225" xil_pn:valueState="non-default"/> + <property xil_pn:name="Perform Advanced Analysis" xil_pn:value="false" xil_pn:valueState="default"/> + <property xil_pn:name="Perform Advanced Analysis Post Trace" xil_pn:value="false" xil_pn:valueState="default"/> + <property xil_pn:name="Perform Timing-Driven Packing and Placement" xil_pn:value="false" xil_pn:valueState="default"/> + <property xil_pn:name="Place & Route Effort Level (Overall)" xil_pn:value="High" xil_pn:valueState="default"/> + <property xil_pn:name="Place And Route Mode" xil_pn:value="Normal Place and Route" xil_pn:valueState="default"/> + <property xil_pn:name="Place MultiBoot Settings into Bitstream spartan6" xil_pn:value="false" xil_pn:valueState="default"/> + <property xil_pn:name="Placer Effort Level Map" xil_pn:value="High" xil_pn:valueState="default"/> + <property xil_pn:name="Placer Extra Effort Map" xil_pn:value="None" xil_pn:valueState="default"/> + <property xil_pn:name="Port to be used" xil_pn:value="Auto - default" xil_pn:valueState="default"/> + <property xil_pn:name="Post Map Simulation Model Name" xil_pn:value="crc_gen_map.v" xil_pn:valueState="default"/> + <property xil_pn:name="Post Place & Route Simulation Model Name" xil_pn:value="crc_gen_timesim.v" xil_pn:valueState="default"/> + <property xil_pn:name="Post Synthesis Simulation Model Name" xil_pn:value="crc_gen_synthesis.v" xil_pn:valueState="default"/> + <property xil_pn:name="Post Translate Simulation Model Name" xil_pn:value="crc_gen_translate.v" xil_pn:valueState="default"/> + <property xil_pn:name="Power Reduction Map spartan6" xil_pn:value="Off" xil_pn:valueState="default"/> + <property xil_pn:name="Power Reduction Par" xil_pn:value="false" xil_pn:valueState="default"/> + <property xil_pn:name="Power Reduction Xst" xil_pn:value="false" xil_pn:valueState="default"/> + <property xil_pn:name="Preferred Language" xil_pn:value="Verilog" xil_pn:valueState="default"/> + <property xil_pn:name="Produce Verbose Report" xil_pn:value="false" xil_pn:valueState="default"/> + <property xil_pn:name="Property Specification in Project File" xil_pn:value="Store all values" xil_pn:valueState="default"/> + <property xil_pn:name="RAM Extraction" xil_pn:value="true" xil_pn:valueState="default"/> + <property xil_pn:name="RAM Style" xil_pn:value="Auto" xil_pn:valueState="default"/> + <property xil_pn:name="ROM Extraction" xil_pn:value="true" xil_pn:valueState="default"/> + <property xil_pn:name="ROM Style" xil_pn:value="Auto" xil_pn:valueState="default"/> + <property xil_pn:name="Read Cores" xil_pn:value="true" xil_pn:valueState="default"/> + <property xil_pn:name="Reduce Control Sets" xil_pn:value="Auto" xil_pn:valueState="default"/> + <property xil_pn:name="Regenerate Core" xil_pn:value="Under Current Project Setting" xil_pn:valueState="default"/> + <property xil_pn:name="Register Balancing" xil_pn:value="No" xil_pn:valueState="default"/> + <property xil_pn:name="Register Duplication Map" xil_pn:value="Off" xil_pn:valueState="default"/> + <property xil_pn:name="Register Duplication Xst" xil_pn:value="true" xil_pn:valueState="default"/> + <property xil_pn:name="Register Ordering spartan6" xil_pn:value="4" xil_pn:valueState="default"/> + <property xil_pn:name="Release Write Enable (Output Events)" xil_pn:value="Default (6)" xil_pn:valueState="default"/> + <property xil_pn:name="Rename Design Instance in Testbench File to" xil_pn:value="UUT" xil_pn:valueState="default"/> + <property xil_pn:name="Rename Top Level Architecture To" xil_pn:value="Structure" xil_pn:valueState="default"/> + <property xil_pn:name="Rename Top Level Entity to" xil_pn:value="" xil_pn:valueState="default"/> + <property xil_pn:name="Rename Top Level Module To" xil_pn:value="" xil_pn:valueState="default"/> + <property xil_pn:name="Report Fastest Path(s) in Each Constraint" xil_pn:value="true" xil_pn:valueState="default"/> + <property xil_pn:name="Report Fastest Path(s) in Each Constraint Post Trace" xil_pn:value="true" xil_pn:valueState="default"/> + <property xil_pn:name="Report Paths by Endpoint" xil_pn:value="3" xil_pn:valueState="default"/> + <property xil_pn:name="Report Paths by Endpoint Post Trace" xil_pn:value="3" xil_pn:valueState="default"/> + <property xil_pn:name="Report Type" xil_pn:value="Verbose Report" xil_pn:valueState="default"/> + <property xil_pn:name="Report Type Post Trace" xil_pn:value="Verbose Report" xil_pn:valueState="default"/> + <property xil_pn:name="Report Unconstrained Paths" xil_pn:value="" xil_pn:valueState="default"/> + <property xil_pn:name="Report Unconstrained Paths Post Trace" xil_pn:value="" xil_pn:valueState="default"/> + <property xil_pn:name="Reset On Configuration Pulse Width" xil_pn:value="100" xil_pn:valueState="default"/> + <property xil_pn:name="Resource Sharing" xil_pn:value="true" xil_pn:valueState="default"/> + <property xil_pn:name="Retain Hierarchy" xil_pn:value="true" xil_pn:valueState="default"/> + <property xil_pn:name="Retiming Map" xil_pn:value="false" xil_pn:valueState="default"/> + <property xil_pn:name="Retry Configuration if CRC Error Occurs spartan6" xil_pn:value="false" xil_pn:valueState="default"/> + <property xil_pn:name="Run Design Rules Checker (DRC)" xil_pn:value="true" xil_pn:valueState="default"/> + <property xil_pn:name="Run for Specified Time" xil_pn:value="true" xil_pn:valueState="default"/> + <property xil_pn:name="Run for Specified Time Map" xil_pn:value="true" xil_pn:valueState="default"/> + <property xil_pn:name="Run for Specified Time Par" xil_pn:value="true" xil_pn:valueState="default"/> + <property xil_pn:name="Run for Specified Time Translate" xil_pn:value="true" xil_pn:valueState="default"/> + <property xil_pn:name="Safe Implementation" xil_pn:value="No" xil_pn:valueState="default"/> + <property xil_pn:name="Security" xil_pn:value="Enable Readback and Reconfiguration" xil_pn:valueState="default"/> + <property xil_pn:name="Selected Simulation Root Source Node Behavioral" xil_pn:value="" xil_pn:valueState="default"/> + <property xil_pn:name="Selected Simulation Root Source Node Post-Map" xil_pn:value="" xil_pn:valueState="default"/> + <property xil_pn:name="Selected Simulation Root Source Node Post-Route" xil_pn:value="" xil_pn:valueState="default"/> + <property xil_pn:name="Selected Simulation Root Source Node Post-Translate" xil_pn:value="" xil_pn:valueState="default"/> + <property xil_pn:name="Selected Simulation Source Node" xil_pn:value="UUT" xil_pn:valueState="default"/> + <property xil_pn:name="Set SPI Configuration Bus Width spartan6" xil_pn:value="1" xil_pn:valueState="default"/> + <property xil_pn:name="Setup External Master Clock Division spartan6" xil_pn:value="1" xil_pn:valueState="default"/> + <property xil_pn:name="Shift Register Extraction" xil_pn:value="true" xil_pn:valueState="default"/> + <property xil_pn:name="Shift Register Minimum Size spartan6" xil_pn:value="2" xil_pn:valueState="default"/> + <property xil_pn:name="Show All Models" xil_pn:value="false" xil_pn:valueState="default"/> + <property xil_pn:name="Simulation Model Target" xil_pn:value="Verilog" xil_pn:valueState="default"/> + <property xil_pn:name="Simulation Run Time ISim" xil_pn:value="1000 ns" xil_pn:valueState="default"/> + <property xil_pn:name="Simulation Run Time Map" xil_pn:value="1000 ns" xil_pn:valueState="default"/> + <property xil_pn:name="Simulation Run Time Par" xil_pn:value="1000 ns" xil_pn:valueState="default"/> + <property xil_pn:name="Simulation Run Time Translate" xil_pn:value="1000 ns" xil_pn:valueState="default"/> + <property xil_pn:name="Simulator" xil_pn:value="ISim (VHDL/Verilog)" xil_pn:valueState="default"/> + <property xil_pn:name="Slice Utilization Ratio" xil_pn:value="100" xil_pn:valueState="default"/> + <property xil_pn:name="Specify 'define Macro Name and Value" xil_pn:value="" xil_pn:valueState="default"/> + <property xil_pn:name="Specify Top Level Instance Names Behavioral" xil_pn:value="Default" xil_pn:valueState="default"/> + <property xil_pn:name="Specify Top Level Instance Names Post-Map" xil_pn:value="Default" xil_pn:valueState="default"/> + <property xil_pn:name="Specify Top Level Instance Names Post-Route" xil_pn:value="Default" xil_pn:valueState="default"/> + <property xil_pn:name="Specify Top Level Instance Names Post-Translate" xil_pn:value="Default" xil_pn:valueState="default"/> + <property xil_pn:name="Speed Grade" xil_pn:value="-2" xil_pn:valueState="non-default"/> + <property xil_pn:name="Starting Placer Cost Table (1-100) Map spartan6" xil_pn:value="1" xil_pn:valueState="default"/> + <property xil_pn:name="Synthesis Tool" xil_pn:value="XST (VHDL/Verilog)" xil_pn:valueState="default"/> + <property xil_pn:name="Target Simulator" xil_pn:value="Please Specify" xil_pn:valueState="default"/> + <property xil_pn:name="Timing Mode Map" xil_pn:value="Performance Evaluation" xil_pn:valueState="default"/> + <property xil_pn:name="Timing Mode Par" xil_pn:value="Performance Evaluation" xil_pn:valueState="default"/> + <property xil_pn:name="Top-Level Module Name in Output Netlist" xil_pn:value="" xil_pn:valueState="default"/> + <property xil_pn:name="Top-Level Source Type" xil_pn:value="HDL" xil_pn:valueState="default"/> + <property xil_pn:name="Trim Unconnected Signals" xil_pn:value="true" xil_pn:valueState="default"/> + <property xil_pn:name="Tristate On Configuration Pulse Width" xil_pn:value="0" xil_pn:valueState="default"/> + <property xil_pn:name="Unused IOB Pins" xil_pn:value="Pull Down" xil_pn:valueState="default"/> + <property xil_pn:name="Use 64-bit PlanAhead on 64-bit Systems" xil_pn:value="true" xil_pn:valueState="default"/> + <property xil_pn:name="Use Clock Enable" xil_pn:value="Auto" xil_pn:valueState="default"/> + <property xil_pn:name="Use Custom Project File Behavioral" xil_pn:value="false" xil_pn:valueState="default"/> + <property xil_pn:name="Use Custom Project File Post-Map" xil_pn:value="false" xil_pn:valueState="default"/> + <property xil_pn:name="Use Custom Project File Post-Route" xil_pn:value="false" xil_pn:valueState="default"/> + <property xil_pn:name="Use Custom Project File Post-Translate" xil_pn:value="false" xil_pn:valueState="default"/> + <property xil_pn:name="Use Custom Simulation Command File Behavioral" xil_pn:value="false" xil_pn:valueState="default"/> + <property xil_pn:name="Use Custom Simulation Command File Map" xil_pn:value="false" xil_pn:valueState="default"/> + <property xil_pn:name="Use Custom Simulation Command File Par" xil_pn:value="false" xil_pn:valueState="default"/> + <property xil_pn:name="Use Custom Simulation Command File Translate" xil_pn:value="false" xil_pn:valueState="default"/> + <property xil_pn:name="Use Custom Waveform Configuration File Behav" xil_pn:value="false" xil_pn:valueState="default"/> + <property xil_pn:name="Use Custom Waveform Configuration File Map" xil_pn:value="false" xil_pn:valueState="default"/> + <property xil_pn:name="Use Custom Waveform Configuration File Par" xil_pn:value="false" xil_pn:valueState="default"/> + <property xil_pn:name="Use Custom Waveform Configuration File Translate" xil_pn:value="false" xil_pn:valueState="default"/> + <property xil_pn:name="Use DSP Block spartan6" xil_pn:value="Auto" xil_pn:valueState="default"/> + <property xil_pn:name="Use LOC Constraints" xil_pn:value="true" xil_pn:valueState="default"/> + <property xil_pn:name="Use RLOC Constraints" xil_pn:value="Yes" xil_pn:valueState="default"/> + <property xil_pn:name="Use Smart Guide" xil_pn:value="false" xil_pn:valueState="default"/> + <property xil_pn:name="Use Synchronous Reset" xil_pn:value="Auto" xil_pn:valueState="default"/> + <property xil_pn:name="Use Synchronous Set" xil_pn:value="Auto" xil_pn:valueState="default"/> + <property xil_pn:name="Use Synthesis Constraints File" xil_pn:value="true" xil_pn:valueState="default"/> + <property xil_pn:name="User Browsed Strategy Files" xil_pn:value="" xil_pn:valueState="default"/> + <property xil_pn:name="UserID Code (8 Digit Hexadecimal)" xil_pn:value="0xFFFFFFFF" xil_pn:valueState="default"/> + <property xil_pn:name="VCCAUX Voltage Level spartan6" xil_pn:value="2.5V" xil_pn:valueState="default"/> + <property xil_pn:name="VHDL Source Analysis Standard" xil_pn:value="VHDL-93" xil_pn:valueState="default"/> + <property xil_pn:name="Value Range Check" xil_pn:value="false" xil_pn:valueState="default"/> + <property xil_pn:name="Verilog Macros" xil_pn:value="" xil_pn:valueState="default"/> + <property xil_pn:name="Wait for DCM and PLL Lock (Output Events) spartan6" xil_pn:value="Default (NoWait)" xil_pn:valueState="default"/> + <property xil_pn:name="Wakeup Clock spartan6" xil_pn:value="Startup Clock" xil_pn:valueState="default"/> + <property xil_pn:name="Watchdog Timer Value spartan6" xil_pn:value="0xFFFF" xil_pn:valueState="default"/> + <property xil_pn:name="Working Directory" xil_pn:value="." xil_pn:valueState="non-default"/> + <property xil_pn:name="Write Timing Constraints" xil_pn:value="false" xil_pn:valueState="default"/> + <!-- --> + <!-- The following properties are for internal use only. These should not be modified.--> + <!-- --> + <property xil_pn:name="PROP_BehavioralSimTop" xil_pn:value="" xil_pn:valueState="default"/> + <property xil_pn:name="PROP_DesignName" xil_pn:value="test" xil_pn:valueState="non-default"/> + <property xil_pn:name="PROP_DevFamilyPMName" xil_pn:value="spartan6" xil_pn:valueState="default"/> + <property xil_pn:name="PROP_FPGAConfiguration" xil_pn:value="FPGAConfiguration" xil_pn:valueState="default"/> + <property xil_pn:name="PROP_PostMapSimTop" xil_pn:value="" xil_pn:valueState="default"/> + <property xil_pn:name="PROP_PostParSimTop" xil_pn:value="" xil_pn:valueState="default"/> + <property xil_pn:name="PROP_PostSynthSimTop" xil_pn:value="" xil_pn:valueState="default"/> + <property xil_pn:name="PROP_PostXlateSimTop" xil_pn:value="" xil_pn:valueState="default"/> + <property xil_pn:name="PROP_PreSynthesis" xil_pn:value="PreSynthesis" xil_pn:valueState="default"/> + <property xil_pn:name="PROP_intProjectCreationTimestamp" xil_pn:value="2011-06-08T15:03:09" xil_pn:valueState="non-default"/> + <property xil_pn:name="PROP_intWbtProjectID" xil_pn:value="54450DDEAEB9E0C5648D96C35DA90DAB" xil_pn:valueState="non-default"/> + <property xil_pn:name="PROP_intWorkingDirLocWRTProjDir" xil_pn:value="Same" xil_pn:valueState="non-default"/> + <property xil_pn:name="PROP_intWorkingDirUsed" xil_pn:value="No" xil_pn:valueState="non-default"/> + </properties> + + <libraries/> + + <autoManagedFiles> + <!-- The following files are identified by `include statements in verilog --> + <!-- source files and are automatically managed by Project Navigator. --> + <!-- --> + <!-- Do not hand-edit this section, as it will be overwritten when the --> + <!-- project is analyzed based on files automatically identified as --> + <!-- include files. --> + </autoManagedFiles> + + <bindings/> + +</project> diff --git a/testbench/wishbone/wb_xilinx_fpga_loader/wave.do b/testbench/wishbone/wb_xilinx_fpga_loader/wave.do new file mode 100644 index 0000000000000000000000000000000000000000..dbff420fc19fdf790d5c1b094cf2ca12c973f0ed --- /dev/null +++ b/testbench/wishbone/wb_xilinx_fpga_loader/wave.do @@ -0,0 +1,53 @@ +onerror {resume} +quietly WaveActivateNextPane {} 0 +add wave -noupdate /main/DUT/g_interface_mode +add wave -noupdate /main/DUT/g_address_granularity +add wave -noupdate /main/DUT/clk_sys_i +add wave -noupdate /main/DUT/rst_n_i +add wave -noupdate /main/DUT/wb_cyc_i +add wave -noupdate /main/DUT/wb_stb_i +add wave -noupdate /main/DUT/wb_we_i +add wave -noupdate /main/DUT/wb_adr_i +add wave -noupdate /main/DUT/wb_sel_i +add wave -noupdate /main/DUT/wb_dat_i +add wave -noupdate /main/DUT/wb_dat_o +add wave -noupdate /main/DUT/wb_ack_o +add wave -noupdate /main/DUT/wb_stall_o +add wave -noupdate /main/DUT/xlx_cclk_o +add wave -noupdate /main/DUT/xlx_din_o +add wave -noupdate /main/DUT/xlx_program_b_o +add wave -noupdate /main/DUT/xlx_init_b_i +add wave -noupdate /main/DUT/xlx_done_i +add wave -noupdate /main/DUT/xlx_suspend_o +add wave -noupdate /main/DUT/xlx_m_o +add wave -noupdate /main/DUT/state +add wave -noupdate /main/DUT/clk_div +add wave -noupdate /main/DUT/tick +add wave -noupdate /main/DUT/init_b_synced +add wave -noupdate /main/DUT/done_synced +add wave -noupdate /main/DUT/timeout_counter +add wave -noupdate /main/DUT/wb_in +add wave -noupdate /main/DUT/wb_out +add wave -noupdate /main/DUT/regs_in +add wave -noupdate /main/DUT/regs_out +add wave -noupdate /main/DUT/d_data +add wave -noupdate /main/DUT/d_size +add wave -noupdate /main/DUT/d_last +add wave -noupdate /main/DUT/bit_counter +TreeUpdate [SetDefaultTree] +WaveRestoreCursors {{Cursor 1} {211850000 ps} 0} +configure wave -namecolwidth 226 +configure wave -valuecolwidth 100 +configure wave -justifyvalue left +configure wave -signalnamewidth 1 +configure wave -snapdistance 10 +configure wave -datasetprefix 0 +configure wave -rowmargin 4 +configure wave -childrowmargin 2 +configure wave -gridoffset 0 +configure wave -gridperiod 1 +configure wave -griddelta 40 +configure wave -timeline 0 +configure wave -timelineunits ns +update +WaveRestoreZoom {0 ps} {3937501184 ps}