OpenCores
URL https://opencores.org/ocsvn/potato/potato/trunk

Subversion Repositories potato

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /potato/branches
    from Rev 44 to Rev 46
    Reverse comparison

Rev 44 → Rev 46

cache-playground/scripts/extract_hex.sh Property changes : Deleted: svn:executable ## -1 +0,0 ## -* \ No newline at end of property Index: cache-playground/testbenches/tb_soc_gpio.vhd =================================================================== --- cache-playground/testbenches/tb_soc_gpio.vhd (revision 44) +++ cache-playground/testbenches/tb_soc_gpio.vhd (nonexistent) @@ -1,91 +0,0 @@ --- The Potato Processor - A simple processor for FPGAs --- (c) Kristian Klomsten Skordal 2014 - 2015 --- Report bugs and issues on - -library ieee; -use ieee.std_logic_1164.all; - -entity tb_soc_gpio is -end entity tb_soc_gpio; - -architecture testbench of tb_soc_gpio is - - -- Clock signal: - signal clk : std_logic := '0'; - constant clk_period : time := 10 ns; - - -- Reset signal: - signal reset : std_logic := '1'; - - -- GPIOs: - signal gpio : std_logic_vector(31 downto 0); - - -- Wishbone bus: - signal wb_adr_in : std_logic_vector( 1 downto 0) := (others => '0'); - signal wb_dat_in : std_logic_vector(31 downto 0) := (others => '0'); - signal wb_dat_out : std_logic_vector(31 downto 0); - signal wb_cyc_in : std_logic := '0'; - signal wb_stb_in : std_logic := '0'; - signal wb_we_in : std_logic := '0'; - signal wb_ack_out : std_logic; -begin - - uut: entity work.pp_soc_gpio - generic map( - NUM_GPIOS => 32 - ) port map( - clk => clk, - reset => reset, - gpio => gpio, - wb_adr_in => wb_adr_in, - wb_dat_in => wb_dat_in, - wb_dat_out => wb_dat_out, - wb_cyc_in => wb_cyc_in, - wb_stb_in => wb_stb_in, - wb_we_in => wb_we_in, - wb_ack_out => wb_ack_out - ); - - clock: process - begin - clk <= '1'; - wait for clk_period / 2; - clk <= '0'; - wait for clk_period / 2; - end process clock; - - stimulus: process - begin - wait for clk_period * 2; - reset <= '0'; - - -- Set the upper half of the GPIOs as inputs, the rest as outputs: - wb_dat_in <= x"0000ffff"; - wb_adr_in <= b"10"; - wb_we_in <= '1'; - wb_cyc_in <= '1'; - wb_stb_in <= '1'; - wait until wb_ack_out = '1'; - wait for clk_period; - wb_stb_in <= '0'; - wb_cyc_in <= '0'; - wb_we_in <= '0'; - wait for clk_period; - - -- Set the outputs to aa, see if the upper half gets ignored correctly: - wb_dat_in <= x"aaaaaaaa"; - wb_adr_in <= b"01"; - wb_we_in <= '1'; - wb_cyc_in <= '1'; - wb_stb_in <= '1'; - wait until wb_ack_out = '1'; - wait for clk_period; - wb_stb_in <= '0'; - wb_cyc_in <= '0'; - wb_we_in <= '0'; - wait for clk_period; - - wait; - end process stimulus; - -end architecture testbench; Index: cache-playground/testbenches/tb_soc.vhd =================================================================== --- cache-playground/testbenches/tb_soc.vhd (revision 44) +++ cache-playground/testbenches/tb_soc.vhd (nonexistent) @@ -1,296 +0,0 @@ --- The Potato Processor - A simple processor for FPGAs --- (c) Kristian Klomsten Skordal 2014 --- Report bugs and issues on - -library ieee; -use ieee.std_logic_1164.all; -use ieee.numeric_std.all; -use ieee.std_logic_textio.all; -use std.textio.all; - -use work.pp_constants.all; -use work.pp_utilities.all; - ---! @brief Testbench providing a full SoC architecture connected with a Wishbone bus. -entity tb_soc is - generic( - IMEM_SIZE : natural := 2048; --! Size of the instruction memory in bytes. - DMEM_SIZE : natural := 2048; --! Size of the data memory in bytes. - IMEM_FILENAME : string := "imem_testfile.hex"; --! File containing the contents of instruction memory. - DMEM_FILENAME : string := "dmem_testfile.hex" --! File containing the contents of data memory. - ); -end entity tb_soc; - -architecture testbench of tb_soc is - - -- Clock signals: - signal clk : std_logic; - constant clk_period : time := 10 ns; - - -- Reset: - signal reset : std_logic := '1'; - - -- Interrupts: - signal irq : std_logic_vector(7 downto 0) := (others => '0'); - - -- HTIF: - signal fromhost_data, tohost_data : std_logic_vector(31 downto 0); - signal fromhost_updated : std_logic := '0'; - signal tohost_updated : std_logic; - - -- Instruction memory signals: - signal imem_adr_in : std_logic_vector(log2(IMEM_SIZE) - 1 downto 0); - signal imem_dat_in : std_logic_vector(31 downto 0); - signal imem_dat_out : std_logic_vector(31 downto 0); - signal imem_cyc_in : std_logic; - signal imem_stb_in : std_logic; - signal imem_sel_in : std_logic_vector(3 downto 0); - signal imem_we_in : std_logic; - signal imem_ack_out : std_logic; - - -- Data memory signals: - signal dmem_adr_in : std_logic_vector(log2(DMEM_SIZE) - 1 downto 0); - signal dmem_dat_in : std_logic_vector(31 downto 0); - signal dmem_dat_out : std_logic_vector(31 downto 0); - signal dmem_cyc_in : std_logic; - signal dmem_stb_in : std_logic; - signal dmem_sel_in : std_logic_vector(3 downto 0); - signal dmem_we_in : std_logic; - signal dmem_ack_out : std_logic; - - -- Processor signals: - signal p_adr_out : std_logic_vector(31 downto 0); - signal p_dat_out : std_logic_vector(31 downto 0); - signal p_dat_in : std_logic_vector(31 downto 0); - signal p_cyc_out : std_logic; - signal p_stb_out : std_logic; - signal p_sel_out : std_logic_vector(3 downto 0); - signal p_we_out : std_logic; - signal p_ack_in : std_logic; - - -- Arbitrated wishbone signals: - signal wb_adr : std_logic_vector(31 downto 0); - signal wb_dat : std_logic_vector(31 downto 0); - signal wb_sel : std_logic_vector( 3 downto 0); - signal wb_cyc : std_logic; - signal wb_stb : std_logic; - signal wb_we : std_logic; - - -- Initialization "module" signals: - signal init_adr_out : std_logic_vector(31 downto 0) := (others => '0'); - signal init_dat_out : std_logic_vector(31 downto 0) := (others => '0'); - signal init_cyc_out : std_logic := '0'; - signal init_stb_out : std_logic := '0'; - signal init_we_out : std_logic := '1'; - - -- Processor reset signals: - signal processor_reset : std_logic := '1'; - - -- Simulation control: - signal initialized : boolean := false; - signal simulation_finished : boolean := false; - -begin - - processor: entity work.pp_potato - port map( - clk => clk, - reset => processor_reset, - irq => irq, - fromhost_data => fromhost_data, - fromhost_updated => fromhost_updated, - tohost_data => tohost_data, - tohost_updated => tohost_updated, - wb_adr_out => p_adr_out, - wb_sel_out => p_sel_out, - wb_cyc_out => p_cyc_out, - wb_stb_out => p_stb_out, - wb_we_out => p_we_out, - wb_dat_out => p_dat_out, - wb_dat_in => p_dat_in, - wb_ack_in => p_ack_in - ); - - imem: entity work.pp_soc_memory - generic map( - MEMORY_SIZE => IMEM_SIZE - ) port map( - clk => clk, - reset => reset, - wb_adr_in => imem_adr_in, - wb_dat_in => imem_dat_in, - wb_dat_out => imem_dat_out, - wb_cyc_in => imem_cyc_in, - wb_stb_in => imem_stb_in, - wb_sel_in => imem_sel_in, - wb_we_in => imem_we_in, - wb_ack_out => imem_ack_out - ); - - dmem: entity work.pp_soc_memory - generic map( - MEMORY_SIZE => DMEM_SIZE - ) port map( - clk => clk, - reset => reset, - wb_adr_in => dmem_adr_in, - wb_dat_in => dmem_dat_in, - wb_dat_out => dmem_dat_out, - wb_cyc_in => dmem_cyc_in, - wb_stb_in => dmem_stb_in, - wb_sel_in => dmem_sel_in, - wb_we_in => dmem_we_in, - wb_ack_out => dmem_ack_out - ); - - imem_adr_in <= wb_adr(imem_adr_in'range); - imem_dat_in <= wb_dat; - imem_we_in <= wb_we; - imem_sel_in <= wb_sel; - dmem_adr_in <= wb_adr(dmem_adr_in'range); - dmem_dat_in <= wb_dat; - dmem_we_in <= wb_we; - dmem_sel_in <= wb_sel; - - address_decoder: process(wb_adr, imem_dat_out, imem_ack_out, dmem_dat_out, dmem_ack_out, - wb_cyc, wb_stb) - begin - if to_integer(unsigned(wb_adr)) < IMEM_SIZE then - p_dat_in <= imem_dat_out; - p_ack_in <= imem_ack_out; - imem_cyc_in <= wb_cyc; - imem_stb_in <= wb_stb; - dmem_cyc_in <= '0'; - dmem_stb_in <= '0'; - else - p_dat_in <= dmem_dat_out; - p_ack_in <= dmem_ack_out; - dmem_cyc_in <= wb_cyc; - dmem_stb_in <= wb_stb; - imem_cyc_in <= '0'; - imem_stb_in <= '0'; - end if; - end process address_decoder; - - arbiter: process(initialized, init_adr_out, init_dat_out, init_cyc_out, init_stb_out, init_we_out, - p_adr_out, p_dat_out, p_cyc_out, p_stb_out, p_we_out, p_sel_out) - begin - if not initialized then - wb_adr <= init_adr_out; - wb_dat <= init_dat_out; - wb_cyc <= init_cyc_out; - wb_stb <= init_stb_out; - wb_we <= init_we_out; - wb_sel <= x"f"; - else - wb_adr <= p_adr_out; - wb_dat <= p_dat_out; - wb_cyc <= p_cyc_out; - wb_stb <= p_stb_out; - wb_we <= p_we_out; - wb_sel <= p_sel_out; - end if; - end process arbiter; - - initializer: process - file imem_file : text open READ_MODE is IMEM_FILENAME; - file dmem_file : text open READ_MODE is DMEM_FILENAME; - variable input_line : line; - variable input_index : natural; - variable input_value : std_logic_vector(31 downto 0); - variable temp : std_logic_vector(31 downto 0); - - constant DMEM_START : natural := IMEM_SIZE; - begin - if not initialized then - -- Read the instruction memory file: - for i in 0 to IMEM_SIZE loop - exit when endfile(imem_file); - - readline(imem_file, input_line); - hread(input_line, input_value); - - init_adr_out <= std_logic_vector(to_unsigned(i * 4, init_adr_out'length)); - init_dat_out <= input_value; - init_cyc_out <= '1'; - init_stb_out <= '1'; - wait until imem_ack_out = '1'; - wait for clk_period; - init_stb_out <= '0'; - wait until imem_ack_out = '0'; - wait for clk_period; - end loop; - - init_cyc_out <= '0'; - init_stb_out <= '0'; - wait for clk_period; - - -- Read the data memory file: - for i in 0 to DMEM_SIZE loop - exit when endfile(dmem_file); - - readline(dmem_file, input_line); - hread(input_line, input_value); - - - -- Swap endianness, TODO: prevent this, fix scripts/extract_hex.sh - temp(7 downto 0) := input_value(31 downto 24); - temp(15 downto 8) := input_value(23 downto 16); - temp(23 downto 16) := input_value(15 downto 8); - temp(31 downto 24) := input_value(7 downto 0); - - input_value := temp; - - init_adr_out <= std_logic_vector(to_unsigned(DMEM_START + (i * 4), init_adr_out'length)); - init_dat_out <= input_value; - init_cyc_out <= '1'; - init_stb_out <= '1'; - wait until dmem_ack_out = '1'; - wait for clk_period; - init_stb_out <= '0'; - wait until dmem_ack_out = '0'; - wait for clk_period; - end loop; - - init_cyc_out <= '0'; - init_stb_out <= '0'; - wait for clk_period; - - initialized <= true; - wait; - end if; - end process initializer; - - clock: process - begin - clk <= '1'; - wait for clk_period / 2; - clk <= '0'; - wait for clk_period / 2; - - if simulation_finished then - wait; - end if; - end process clock; - - stimulus: process - begin - wait for clk_period * 2; - reset <= '0'; - - wait until initialized; - processor_reset <= '0'; - - wait until tohost_updated = '1'; - wait for clk_period; -- Let the signal "settle", because of stupid clock edges - if tohost_data = x"00000001" then - report "Success!" severity NOTE; - else - report "Failure in test " & integer'image(to_integer(shift_right(unsigned(tohost_data), 1))) & "!" severity NOTE; - end if; - - simulation_finished <= true; - wait; - end process stimulus; - -end architecture testbench; Index: cache-playground/testbenches/tb_soc_timer.vhd =================================================================== --- cache-playground/testbenches/tb_soc_timer.vhd (revision 44) +++ cache-playground/testbenches/tb_soc_timer.vhd (nonexistent) @@ -1,108 +0,0 @@ --- The Potato Processor - A simple processor for FPGAs --- (c) Kristian Klomsten Skordal 2014 - 2015 --- Report bugs and issues on - -library ieee; -use ieee.std_logic_1164.all; - -entity tb_soc_timer is -end entity tb_soc_timer; - -architecture behaviour of tb_soc_timer is - - -- Clock signal: - signal clk : std_logic := '0'; - constant clk_period : time := 10 ns; - - -- Reset signal: - signal reset : std_logic := '1'; - - -- IRQ signal: - signal irq : std_logic; - - -- Wishbone interface: - signal wb_adr_in : std_logic_vector(1 downto 0) := (others => '0'); - signal wb_dat_in : std_logic_vector(31 downto 0) := (others => '0'); - signal wb_dat_out : std_logic_vector(31 downto 0); - signal wb_cyc_in : std_logic := '0'; - signal wb_stb_in : std_logic := '0'; - signal wb_we_in : std_logic := '0'; - signal wb_ack_out : std_logic; - -begin - - uut: entity work.pp_soc_timer - port map( - clk => clk, - reset => reset, - irq => irq, - wb_adr_in => wb_adr_in, - wb_dat_in => wb_dat_in, - wb_dat_out => wb_dat_out, - wb_cyc_in => wb_cyc_in, - wb_stb_in => wb_stb_in, - wb_we_in => wb_we_in, - wb_ack_out => wb_ack_out - ); - - clock: process - begin - clk <= '1'; - wait for clk_period / 2; - clk <= '0'; - wait for clk_period / 2; - end process clock; - - stimulus: process - begin - wait for clk_period * 2; - reset <= '0'; - - wait for clk_period; - - -- Set the compare register to 50: - wb_cyc_in <= '1'; - wb_stb_in <= '1'; - wb_adr_in <= b"01"; - wb_dat_in <= x"00000032"; - wb_we_in <= '1'; - wait until wb_ack_out = '1'; - wait for clk_period; - - wb_stb_in <= '0'; - wait for clk_period; - - -- Start the timer: - wb_stb_in <= '1'; - wb_adr_in <= b"00"; - wb_dat_in <= x"00000003"; - wait until wb_ack_out = '1'; - wait for clk_period; - - wb_stb_in <= '0'; - wb_cyc_in <= '0'; - wb_we_in <= '0'; - wait for clk_period; - - -- Wait for the interrupt: - wait until irq = '1'; - wait for clk_period; - - -- Reset the interrupt: - wb_cyc_in <= '1'; - wb_stb_in <= '1'; - wb_we_in <= '1'; - wb_adr_in <= b"00"; - wb_dat_in <= x"00000003"; - wait until wb_ack_out = '1'; - wait for clk_period; - - wb_stb_in <= '0'; - wb_cyc_in <= '0'; - wb_we_in <= '0'; - wait for clk_period; - - wait; - end process stimulus; - -end architecture behaviour; Index: cache-playground/testbenches/tb_soc_memory.vhd =================================================================== --- cache-playground/testbenches/tb_soc_memory.vhd (revision 44) +++ cache-playground/testbenches/tb_soc_memory.vhd (nonexistent) @@ -1,99 +0,0 @@ --- The Potato Processor - A simple processor for FPGAs --- (c) Kristian Klomsten Skordal 2014 - 2015 --- Report bugs and issues on - -library ieee; -use ieee.std_logic_1164.all; -use ieee.numeric_std.all; - -entity tb_soc_memory is -end entity tb_soc_memory; - -architecture testbench of tb_soc_memory is - - -- Clock signal: - signal clk : std_logic; - constant clk_period : time := 10 ns; - - -- Reset signal: - signal reset : std_logic := '1'; - - -- Wishbone signals: - signal wb_adr_in : std_logic_vector(31 downto 0); - signal wb_dat_in : std_logic_vector(31 downto 0); - signal wb_dat_out : std_logic_vector(31 downto 0); - signal wb_cyc_in : std_logic := '0'; - signal wb_stb_in : std_logic := '0'; - signal wb_sel_in : std_logic_vector(3 downto 0) := (others => '1'); - signal wb_we_in : std_logic := '0'; - signal wb_ack_out : std_logic; - -begin - - uut: entity work.pp_soc_memory - port map( - clk => clk, - reset => reset, - wb_adr_in => wb_adr_in, - wb_dat_in => wb_dat_in, - wb_dat_out => wb_dat_out, - wb_cyc_in => wb_cyc_in, - wb_stb_in => wb_stb_in, - wb_sel_in => wb_sel_in, - wb_we_in => wb_we_in, - wb_ack_out => wb_ack_out - ); - - clock: process - begin - clk <= '1'; - wait for clk_period / 2; - clk <= '0'; - wait for clk_period / 2; - end process clock; - - stimulus: process - begin - wait for clk_period; - reset <= '0'; - - -- Write 32 bit of data to address 0: - wb_adr_in <= x"00000000"; - wb_dat_in <= x"deadbeef"; - wb_cyc_in <= '1'; - wb_stb_in <= '1'; - wb_we_in <= '1'; - wait for clk_period; - wb_stb_in <= '0'; - wb_cyc_in <= '0'; - wait for clk_period; - - -- Write a block write of two 32-bit words at address 0 and 1: - wb_adr_in <= x"00000000"; - wb_dat_in <= x"feedbeef"; - wb_cyc_in <= '1'; - wb_stb_in <= '1'; - wait for clk_period; - wb_stb_in <= '0'; - wb_adr_in <= x"00000004"; - wb_dat_in <= x"f00dd00d"; - wait for clk_period; - wb_stb_in <= '1'; - wait for clk_period; - wb_stb_in <= '0'; - wb_cyc_in <= '0'; - - -- Read address 4: - wait for clk_period; - wb_we_in <= '0'; - wb_adr_in <= x"00000000"; - wb_cyc_in <= '1'; - wb_stb_in <= '1'; - wait for clk_period; - - -- TODO: Make this testbench automatic. - - wait; - end process stimulus; - -end architecture testbench; Index: cache-playground/testbenches/tb_processor.vhd =================================================================== --- cache-playground/testbenches/tb_processor.vhd (revision 44) +++ cache-playground/testbenches/tb_processor.vhd (nonexistent) @@ -1,291 +0,0 @@ --- The Potato Processor - A simple processor for FPGAs --- (c) Kristian Klomsten Skordal 2014 --- Report bugs and issues on - -library ieee; -use ieee.std_logic_1164.all; -use ieee.numeric_std.all; -use ieee.std_logic_textio.all; -use std.textio.all; - -use work.pp_constants.all; - -entity tb_processor is - generic( - IMEM_SIZE : natural := 2048; --! Size of the instruction memory in bytes. - DMEM_SIZE : natural := 2048; --! Size of the data memory in bytes. - IMEM_FILENAME : string := "imem_testfile.hex"; --! File containing the contents of instruction memory. - DMEM_FILENAME : string := "dmem_testfile.hex" --! File containing the contents of data memory. - ); -end entity tb_processor; - -architecture testbench of tb_processor is - - -- Processor component prototype: - component pp_core is - port( - -- Common inputs: - clk : in std_logic; --! Processor clock - reset : in std_logic; --! Reset signal - timer_clk : in std_logic; --! Timer clock input - - -- Instruction memory interface: - imem_address : out std_logic_vector(31 downto 0); --! Address of the next instruction - imem_data_in : in std_logic_vector(31 downto 0); --! Instruction input - imem_req : out std_logic; - imem_ack : in std_logic; - - -- Data memory interface: - dmem_address : out std_logic_vector(31 downto 0); --! Data address - dmem_data_in : in std_logic_vector(31 downto 0); --! Input from the data memory - dmem_data_out : out std_logic_vector(31 downto 0); --! Ouptut to the data memory - dmem_data_size : out std_logic_vector( 1 downto 0); --! Size of the data, 1 = 8 bits, 2 = 16 bits, 0 = 32 bits. - dmem_read_req : out std_logic; --! Data memory read request - dmem_read_ack : in std_logic; --! Data memory read acknowledge - dmem_write_req : out std_logic; --! Data memory write request - dmem_write_ack : in std_logic; --! Data memory write acknowledge - - -- Tohost/fromhost interface: - fromhost_data : in std_logic_vector(31 downto 0); --! Data from the host/simulator. - fromhost_write_en : in std_logic; --! Write enable signal from the host/simulator. - tohost_data : out std_logic_vector(31 downto 0); --! Data to the host/simulator. - tohost_write_en : out std_logic; --! Write enable signal to the host/simulator. - - -- External interrupt input: - irq : in std_logic_vector(7 downto 0) --! IRQ input - ); - end component pp_core; - - -- Clock signal: - signal clk : std_logic := '0'; - constant clk_period : time := 10 ns; - - -- Common inputs: - signal reset : std_logic := '1'; - - -- Instruction memory interface: - signal imem_address : std_logic_vector(31 downto 0); - signal imem_data_in : std_logic_vector(31 downto 0) := (others => '0'); - signal imem_req : std_logic; - signal imem_ack : std_logic := '0'; - - -- Data memory interface: - signal dmem_address : std_logic_vector(31 downto 0); - signal dmem_data_in : std_logic_vector(31 downto 0) := (others => '0'); - signal dmem_data_out : std_logic_vector(31 downto 0); - signal dmem_data_size : std_logic_vector( 1 downto 0); - signal dmem_read_req, dmem_write_req : std_logic; - signal dmem_read_ack, dmem_write_ack : std_logic := '1'; - - -- Tohost/Fromhost: - signal tohost_data : std_logic_vector(31 downto 0); - signal fromhost_data : std_logic_vectoR(31 downto 0) := (others => '0'); - signal tohost_write_en : std_logic; - signal fromhost_write_en : std_logic := '0'; - - -- External interrupt input: - signal irq : std_logic_vector(7 downto 0) := (others => '0'); - - -- Simulation initialized: - signal imem_initialized, dmem_initialized, initialized : boolean := false; - - -- Memory array type: - type memory_array is array(natural range <>) of std_logic_vector(7 downto 0); - constant IMEM_BASE : natural := 0; - constant IMEM_END : natural := IMEM_SIZE - 1; - constant DMEM_BASE : natural := IMEM_SIZE; - constant DMEM_END : natural := IMEM_SIZE + DMEM_SIZE - 1; - - -- Memories: - signal imem_memory : memory_array(IMEM_BASE to IMEM_END); - signal dmem_memory : memory_array(DMEM_BASE to DMEM_END); - - signal simulation_finished : boolean := false; - -begin - - uut: pp_core - port map( - clk => clk, - reset => reset, - timer_clk => clk, - imem_address => imem_address, - imem_data_in => imem_data_in, - imem_req => imem_req, - imem_ack => imem_ack, - dmem_address => dmem_address, - dmem_data_in => dmem_data_in, - dmem_data_out => dmem_data_out, - dmem_data_size => dmem_data_size, - dmem_read_req => dmem_read_req, - dmem_read_ack => dmem_read_ack, - dmem_write_req => dmem_write_req, - dmem_write_ack => dmem_write_ack, - tohost_data => tohost_data, - tohost_write_en => tohost_write_en, - fromhost_data => fromhost_data, - fromhost_write_en => fromhost_write_en, - irq => irq - ); - - clock: process - begin - clk <= '0'; - wait for clk_period / 2; - clk <= '1'; - wait for clk_period / 2; - - if simulation_finished then - wait; - end if; - end process clock; - - --! Initializes the instruction memory from file. - imem_init: process - file imem_file : text open READ_MODE is IMEM_FILENAME; - variable input_line : line; - variable input_index : natural; - variable input_value : std_logic_vector(31 downto 0); - begin - for i in IMEM_BASE / 4 to IMEM_END / 4 loop - if not endfile(imem_file) then - readline(imem_file, input_line); - hread(input_line, input_value); - imem_memory(i * 4 + 0) <= input_value( 7 downto 0); - imem_memory(i * 4 + 1) <= input_value(15 downto 8); - imem_memory(i * 4 + 2) <= input_value(23 downto 16); - imem_memory(i * 4 + 3) <= input_value(31 downto 24); - else - imem_memory(i * 4 + 0) <= RISCV_NOP( 7 downto 0); - imem_memory(i * 4 + 1) <= RISCV_NOP(15 downto 8); - imem_memory(i * 4 + 2) <= RISCV_NOP(23 downto 16); - imem_memory(i * 4 + 3) <= RISCV_NOP(31 downto 24); - end if; - end loop; - - imem_initialized <= true; - wait; - end process imem_init; - - --! Initializes and handles writes to the data memory. - dmem_init_and_write: process(clk) - file dmem_file : text open READ_MODE is DMEM_FILENAME; - variable input_line : line; - variable input_index : natural; - variable input_value : std_logic_vector(31 downto 0); - begin - if not dmem_initialized then - for i in DMEM_BASE / 4 to DMEM_END / 4 loop - if not endfile(dmem_file) then - readline(dmem_file, input_line); - hread(input_line, input_value); - - -- Read from a big-endian file: - dmem_memory(i * 4 + 3) <= input_value( 7 downto 0); - dmem_memory(i * 4 + 2) <= input_value(15 downto 8); - dmem_memory(i * 4 + 1) <= input_value(23 downto 16); - dmem_memory(i * 4 + 0) <= input_value(31 downto 24); - else - dmem_memory(i * 4 + 0) <= (others => '0'); - dmem_memory(i * 4 + 1) <= (others => '0'); - dmem_memory(i * 4 + 2) <= (others => '0'); - dmem_memory(i * 4 + 3) <= (others => '0'); - end if; - end loop; - - dmem_initialized <= true; - end if; - - if rising_edge(clk) then - if dmem_write_ack = '1' then - dmem_write_ack <= '0'; - elsif dmem_write_req = '1' then - case dmem_data_size is - when b"00" => -- 32 bits - dmem_memory(to_integer(unsigned(dmem_address)) + 0) <= dmem_data_out(7 downto 0); - dmem_memory(to_integer(unsigned(dmem_address)) + 1) <= dmem_data_out(15 downto 8); - dmem_memory(to_integer(unsigned(dmem_address)) + 2) <= dmem_data_out(23 downto 16); - dmem_memory(to_integer(unsigned(dmem_address)) + 3) <= dmem_data_out(31 downto 24); - when b"01" => -- 8 bits - dmem_memory(to_integer(unsigned(dmem_address))) <= dmem_data_out(7 downto 0); - when b"10" => -- 16 bits - dmem_memory(to_integer(unsigned(dmem_address)) + 0) <= dmem_data_out( 7 downto 0); - dmem_memory(to_integer(unsigned(dmem_address)) + 1) <= dmem_data_out(15 downto 8); - when others => -- Reserved for possible future 64 bit support - end case; - dmem_write_ack <= '1'; - end if; - end if; - end process dmem_init_and_write; - - initialized <= imem_initialized and dmem_initialized; - - --! Instruction memory read process. - imem_read: process(clk) - begin - if rising_edge(clk) then - if reset = '1' then - imem_ack <= '0'; - else - if to_integer(unsigned(imem_address)) > IMEM_END then - imem_data_in <= (others => 'X'); - else - imem_data_in <= imem_memory(to_integer(unsigned(imem_address)) + 3) - & imem_memory(to_integer(unsigned(imem_address)) + 2) - & imem_memory(to_integer(unsigned(imem_address)) + 1) - & imem_memory(to_integer(unsigned(imem_address)) + 0); - end if; - - imem_ack <= '1'; - end if; - end if; - end process imem_read; - - --! Data memory read process. - dmem_read: process(clk) - begin - if rising_edge(clk) then - if dmem_read_ack = '1' then - dmem_read_ack <= '0'; - elsif dmem_read_req = '1' then - case dmem_data_size is - when b"00" => -- 32 bits - dmem_data_in <= dmem_memory(to_integer(unsigned(dmem_address) + 3)) - & dmem_memory(to_integer(unsigned(dmem_address) + 2)) - & dmem_memory(to_integer(unsigned(dmem_address) + 1)) - & dmem_memory(to_integer(unsigned(dmem_address) + 0)); - when b"10" => -- 16 bits - dmem_data_in(15 downto 8) <= dmem_memory(to_integer(unsigned(dmem_address)) + 1); - dmem_data_in( 7 downto 0) <= dmem_memory(to_integer(unsigned(dmem_address)) + 0); - when b"01" => -- 8 bits - dmem_data_in(7 downto 0) <= dmem_memory(to_integer(unsigned(dmem_address))); - when others => -- Reserved for possible future 64 bit support - end case; - dmem_read_ack <= '1'; - end if; - end if; - end process dmem_read; - - stimulus: process - begin - wait until initialized = true; - report "Testbench initialized, starting behavioural simulation..." severity NOTE; - wait for clk_period * 2; - - -- Release the processor from reset: - reset <= '0'; - wait for clk_period; - - wait until tohost_write_en = '1'; - wait for clk_period; -- Let the signal "settle", because of clock edges - if tohost_data = x"00000001" then - report "Success!" severity NOTE; - else - report "Failure in test " & integer'image(to_integer(shift_right(unsigned(tohost_data), 1))) & "!" severity NOTE; - end if; - - simulation_finished <= true; - wait; - end process stimulus; - -end architecture testbench; Index: cache-playground/testbenches/tb_soc_uart.vhd =================================================================== --- cache-playground/testbenches/tb_soc_uart.vhd (revision 44) +++ cache-playground/testbenches/tb_soc_uart.vhd (nonexistent) @@ -1,95 +0,0 @@ --- The Potato Processor - A simple processor for FPGAs --- (c) Kristian Klomsten Skordal 2014 - 2015 --- Report bugs and issues on - -library ieee; -use ieee.std_logic_1164.all; - -entity tb_soc_uart is -end entity tb_soc_uart; - -architecture testbench of tb_soc_uart is - - -- Clock signal: - signal clk : std_logic := '0'; - constant clk_period : time := 10 ns; - - -- Reset signal: - signal reset : std_logic := '1'; - - -- UART ports: - signal txd : std_logic; - signal rxd : std_logic := '1'; - - -- interrupt signals: - signal irq_send_buffer_empty : std_logic; - signal irq_data_received : std_logic; - - -- Wishbone ports: - signal wb_adr_in : std_logic_vector(1 downto 0) := (others => '0'); - signal wb_dat_in : std_logic_vector(7 downto 0) := (others => '0'); - signal wb_dat_out : std_logic_vector(7 downto 0); - signal wb_we_in : std_logic := '0'; - signal wb_cyc_in : std_logic := '0'; - signal wb_stb_in : std_logic := '0'; - signal wb_ack_out : std_logic; - -begin - - uut: entity work.pp_soc_uart - port map( - clk => clk, - reset => reset, - txd => txd, - rxd => rxd, - irq_send_buffer_empty => irq_send_buffer_empty, - irq_data_received => irq_data_received, - wb_adr_in => wb_adr_in, - wb_dat_in => wb_dat_in, - wb_dat_out => wb_dat_out, - wb_we_in => wb_we_in, - wb_cyc_in => wb_cyc_in, - wb_stb_in => wb_stb_in, - wb_ack_out => wb_ack_out - ); - - -- Set up an internal loopback: - rxd <= txd; - - clock: process - begin - clk <= '1'; - wait for clk_period / 2; - clk <= '0'; - wait for clk_period / 2; - end process clock; - - stimulus: process - begin - wait for clk_period * 2; - reset <= '0'; - - -- Write a 'P' (for Potato the Processor) to the UART: - wb_adr_in <= b"00"; - wb_dat_in <= x"50"; - wb_we_in <= '1'; - wb_cyc_in <= '1'; - wb_stb_in <= '1'; - - wait until wb_ack_out = '1'; - wait for clk_period; - wb_stb_in <= '0'; - wait for clk_period; - - -- Write an 'o': - wb_dat_in <= x"6f"; - wb_stb_in <= '1'; - wait until wb_ack_out = '1'; - wait for clk_period; - wb_stb_in <= '0'; - wait for clk_period; - - wait; - end process stimulus; - -end architecture testbench; Index: cache-playground/src/pp_alu.vhd =================================================================== --- cache-playground/src/pp_alu.vhd (revision 44) +++ cache-playground/src/pp_alu.vhd (nonexistent) @@ -1,58 +0,0 @@ --- The Potato Processor - A simple processor for FPGAs --- (c) Kristian Klomsten Skordal 2014 --- Report bugs and issues on - -library ieee; -use ieee.std_logic_1164.all; -use ieee.numeric_std.all; - -use work.pp_types.all; - -entity pp_alu is - port( - x, y : in std_logic_vector(31 downto 0); - result : out std_logic_vector(31 downto 0); - operation : in alu_operation - ); -end entity pp_alu; - -architecture behaviour of pp_alu is -begin - - calculate: process(operation, x, y) - begin - case operation is - when ALU_AND => - result <= x and y; - when ALU_OR => - result <= x or y; - when ALU_XOR => - result <= x xor y; - when ALU_SLT => - if signed(x) < signed(y) then - result <= (0 => '1', others => '0'); - else - result <= (others => '0'); - end if; - when ALU_SLTU => - if unsigned(x) < unsigned(y) then - result <= (0 => '1', others => '0'); - else - result <= (others => '0'); - end if; - when ALU_ADD => - result <= std_logic_vector(unsigned(x) + unsigned(y)); - when ALU_SUB => - result <= std_logic_vector(unsigned(x) - unsigned(y)); - when ALU_SRL => - result <= std_logic_vector(shift_right(unsigned(x), to_integer(unsigned(y(4 downto 0))))); - when ALU_SLL => - result <= std_logic_vector(shift_left(unsigned(x), to_integer(unsigned(y(4 downto 0))))); - when ALU_SRA => - result <= std_logic_vector(shift_right(signed(x), to_integer(unsigned(y(4 downto 0))))); - when others => - result <= (others => '0'); - end case; - end process calculate; - -end architecture behaviour; Index: cache-playground/src/pp_register_file.vhd =================================================================== --- cache-playground/src/pp_register_file.vhd (revision 44) +++ cache-playground/src/pp_register_file.vhd (nonexistent) @@ -1,55 +0,0 @@ --- The Potato Processor - A simple processor for FPGAs --- (c) Kristian Klomsten Skordal 2014 --- Report bugs and issues on - -library ieee; -use ieee.std_logic_1164.all; -use ieee.numeric_std.all; - -use work.pp_types.all; -use work.pp_utilities.all; - ---! @brief 32-bit RISC-V register file. -entity pp_register_file is - port( - clk : in std_logic; - - -- Read port 1: - rs1_addr : in register_address; - rs1_data : out std_logic_vector(31 downto 0); - - -- Read port 2: - rs2_addr : in register_address; - rs2_data : out std_logic_vector(31 downto 0); - - -- Write port: - rd_addr : in register_address; - rd_data : in std_logic_vector(31 downto 0); - rd_write : in std_logic - ); -end entity pp_register_file; - -architecture behaviour of pp_register_file is - - --! Register array type. - type regfile_array is array(0 to 31) of std_logic_vector(31 downto 0); - - --! Register array. - --shared variable registers : regfile_array := (others => (others => '0')); -- Shared variable used to simulate write-first RAM - -begin - - regfile: process(clk) - variable registers : regfile_array := (others => (others => '0')); - begin - if rising_edge(clk) then - if rd_write = '1' and rd_addr /= b"00000" then - registers(to_integer(unsigned(rd_addr))) := rd_data; - end if; - - rs1_data <= registers(to_integer(unsigned(rs1_addr))); - rs2_data <= registers(to_integer(unsigned(rs2_addr))); - end if; - end process regfile; - -end architecture behaviour; Index: cache-playground/src/pp_fifo.vhd =================================================================== --- cache-playground/src/pp_fifo.vhd (revision 44) +++ cache-playground/src/pp_fifo.vhd (nonexistent) @@ -1,92 +0,0 @@ --- The Potato Processor - A simple processor for FPGAs --- (c) Kristian Klomsten Skordal 2014 - 2015 --- Report bugs and issues on - -library ieee; -use ieee.std_logic_1164.all; - ---! @brief A generic FIFO module. ---! Adopted from the FIFO module in . -entity pp_fifo is - generic( - DEPTH : natural := 64; - WIDTH : natural := 31 - ); - port( - -- Control lines: - clk : in std_logic; - reset : in std_logic; - - -- Status lines: - full : out std_logic; - empty : out std_logic; - - -- Data in: - data_in : in std_logic_vector(WIDTH - 1 downto 0); - data_out : out std_logic_vector(WIDTH - 1 downto 0); - push, pop : in std_logic - ); -end entity pp_fifo; - -architecture behaviour of pp_fifo is - - type memory_array is array(0 to DEPTH - 1) of std_logic_vector(WIDTH - 1 downto 0); - shared variable memory : memory_array := (others => (others => '0')); - - subtype index_type is integer range 0 to DEPTH - 1; - signal top, bottom : index_type; - - type fifo_op is (FIFO_POP, FIFO_PUSH); - signal prev_op : fifo_op := FIFO_POP; - -begin - - empty <= '1' when top = bottom and prev_op = FIFO_POP else '0'; - full <= '1' when top = bottom and prev_op = FIFO_PUSH else '0'; - - read: process(clk) - begin - if rising_edge(clk) then - if reset = '1' then - bottom <= 0; - else - if pop = '1' then - data_out <= memory(bottom); - bottom <= (bottom + 1) mod DEPTH; - end if; - end if; - end if; - end process read; - - write: process(clk) - begin - if rising_edge(clk) then - if reset = '1' then - top <= 0; - else - if push = '1' then - memory(top) := data_in; - top <= (top + 1) mod DEPTH; - end if; - end if; - end if; - end process write; - - set_prev_op: process(clk) - begin - if rising_edge(clk) then - if reset = '1' then - prev_op <= FIFO_POP; - else - if push = '1' and pop = '1' then - prev_op <= FIFO_POP; - elsif push = '1' then - prev_op <= FIFO_PUSH; - elsif pop = '1' then - prev_op <= FIFO_POP; - end if; - end if; - end if; - end process set_prev_op; - -end architecture behaviour; Index: cache-playground/src/pp_decode.vhd =================================================================== --- cache-playground/src/pp_decode.vhd (revision 44) +++ cache-playground/src/pp_decode.vhd (nonexistent) @@ -1,140 +0,0 @@ --- The Potato Processor - A simple processor for FPGAs --- (c) Kristian Klomsten Skordal 2014 - 2015 --- Report bugs and issues on - -library ieee; -use ieee.std_logic_1164.all; -use ieee.numeric_std.all; - -use work.pp_types.all; -use work.pp_constants.all; -use work.pp_csr.all; - ---! @brief Instruction decode unit. -entity pp_decode is - generic( - RESET_ADDRESS : std_logic_vector(31 downto 0); - PROCESSOR_ID : std_logic_vector(31 downto 0) - ); - port( - clk : in std_logic; - reset : in std_logic; - - flush : in std_logic; - stall : in std_logic; - - -- Instruction input: - instruction_data : in std_logic_vector(31 downto 0); - instruction_address : in std_logic_vector(31 downto 0); - instruction_ready : in std_logic; - instruction_count : in std_logic; - - -- Register addresses: - rs1_addr, rs2_addr, rd_addr : out register_address; - csr_addr : out csr_address; - - -- Shamt value for shift operations: - shamt : out std_logic_vector(4 downto 0); - funct3 : out std_logic_vector(2 downto 0); - - -- Immediate value for immediate instructions: - immediate : out std_logic_vector(31 downto 0); - - -- Control signals: - rd_write : out std_logic; - branch : out branch_type; - alu_x_src : out alu_operand_source; - alu_y_src : out alu_operand_source; - alu_op : out alu_operation; - mem_op : out memory_operation_type; - mem_size : out memory_operation_size; - count_instruction : out std_logic; - - -- Instruction address: - pc : out std_logic_vector(31 downto 0); - - -- CSR control signals: - csr_write : out csr_write_mode; - csr_use_imm : out std_logic; - - -- Exception output signals: - decode_exception : out std_logic; - decode_exception_cause : out csr_exception_cause - ); - -end entity pp_decode; - -architecture behaviour of pp_decode is - signal instruction : std_logic_vector(31 downto 0); - signal immediate_value : std_logic_vector(31 downto 0); -begin - - immediate <= immediate_value; - - get_instruction: process(clk) - begin - if rising_edge(clk) then - if reset = '1' then - instruction <= RISCV_NOP; - pc <= RESET_ADDRESS; - count_instruction <= '0'; - elsif stall = '1' then - count_instruction <= '0'; - elsif flush = '1' or instruction_ready = '0' then - instruction <= RISCV_NOP; - count_instruction <= '0'; - else - instruction <= instruction_data; - count_instruction <= instruction_count; - pc <= instruction_address; - end if; - end if; - end process get_instruction; - --- -- Extract register addresses from the instruction word: - rs1_addr <= instruction(19 downto 15); - rs2_addr <= instruction(24 downto 20); - rd_addr <= instruction(11 downto 7); - - -- Extract the shamt value from the instruction word: - shamt <= instruction(24 downto 20); - - -- Extract the value specifying which comparison to do in branch instructions: - funct3 <= instruction(14 downto 12); - - -- Extract the immediate value from the instruction word: - immediate_decoder: entity work.pp_imm_decoder - port map( - instruction => instruction(31 downto 2), - immediate => immediate_value - ); - - decode_csr_addr: process(immediate_value) - begin - if immediate_value(11 downto 0) = CSR_EPC_SRET then - csr_addr <= CSR_EPC; - else - csr_addr <= immediate_value(11 downto 0); - end if; - end process decode_csr_addr; - - control_unit: entity work.pp_control_unit - port map( - opcode => instruction(6 downto 2), - funct3 => instruction(14 downto 12), - funct7 => instruction(31 downto 25), - funct12 => instruction(31 downto 20), - rd_write => rd_write, - branch => branch, - alu_x_src => alu_x_src, - alu_y_src => alu_y_src, - alu_op => alu_op, - mem_op => mem_op, - mem_size => mem_size, - decode_exception => decode_exception, - decode_exception_cause => decode_exception_cause, - csr_write => csr_write, - csr_imm => csr_use_imm - ); - -end architecture behaviour; Index: cache-playground/src/pp_csr_unit.vhd =================================================================== --- cache-playground/src/pp_csr_unit.vhd (revision 44) +++ cache-playground/src/pp_csr_unit.vhd (nonexistent) @@ -1,223 +0,0 @@ --- The Potato Processor - A simple processor for FPGAs --- (c) Kristian Klomsten Skordal 2014 - 2015 --- Report bugs and issues on - -library ieee; -use ieee.std_logic_1164.all; -use ieee.numeric_std.all; - -use work.pp_csr.all; - -entity pp_csr_unit is - generic( - PROCESSOR_ID : std_logic_vector(31 downto 0) - ); - port( - clk, timer_clk : in std_logic; - reset : in std_logic; - - -- Count retired instruction: - count_instruction : in std_logic; - - -- HTIF interface: - fromhost_data : in std_logic_vector(31 downto 0); - fromhost_updated : in std_logic; - tohost_data : out std_logic_vector(31 downto 0); - tohost_updated : out std_logic; - - -- Read port: - read_address : in csr_address; - read_data_out : out std_logic_vector(31 downto 0); - read_writeable : out boolean; - - -- Write port: - write_address : in csr_address; - write_data_in : in std_logic_vector(31 downto 0); - write_mode : in csr_write_mode; - - -- Exception context write port: - exception_context : in csr_exception_context; - exception_context_write : in std_logic; - - -- Registers needed for exception handling, always read: - status_out : out csr_status_register; - evec_out : out std_logic_vector(31 downto 0) - ); -end entity pp_csr_unit; - -architecture behaviour of pp_csr_unit is - - -- Implemented counters: - signal counter_time : std_logic_vector(63 downto 0); - signal counter_cycle : std_logic_vector(63 downto 0); - signal counter_instret : std_logic_vector(63 downto 0); - - -- Implemented registers: - signal sup0, sup1 : std_logic_vector(31 downto 0) := (others => '0'); - signal epc, evec : std_logic_vector(31 downto 0) := (others => '0'); - signal badvaddr : std_logic_vector(31 downto 0) := (others => '0'); - signal cause : csr_exception_cause; - - -- HTIF FROMHOST register: - signal fromhost: std_logic_vector(31 downto 0); - - -- Status register: - signal status_register : csr_status_register; - -begin - - read_writeable <= csr_is_writeable(read_address); - - --! Updates the FROMHOST register when new data is available. - htif_fromhost: process(clk) - begin - if rising_edge(clk) then - if fromhost_updated = '1' then - fromhost <= fromhost_data; - end if; - end if; - end process htif_fromhost; - - --! Sends a word to the host over the HTIF interface. - htif_tohost: process(clk) - begin - if rising_edge(clk) then - if reset = '1' then - tohost_data <= (others => '0'); - tohost_updated <= '0'; - else - if write_mode /= CSR_WRITE_NONE and write_address = CSR_TOHOST then - tohost_data <= write_data_in; - tohost_updated <= '1'; - else - tohost_updated <= '0'; - end if; - end if; - end if; - end process htif_tohost; - - write: process(clk) - begin - if rising_edge(clk) then - if reset = '1' then - status_register <= CSR_SR_DEFAULT; - else - if exception_context_write = '1' then - status_register <= exception_context.status; - cause <= exception_context.cause; - badvaddr <= exception_context.badvaddr; - end if; - - if write_mode /= CSR_WRITE_NONE then - case write_address is - when CSR_STATUS => - if exception_context_write = '0' then - status_register <= to_csr_status_register(write_data_in); - end if; - when CSR_EPC => - epc <= write_data_in; - when CSR_EVEC => - evec <= write_data_in; - when CSR_SUP0 => - sup0 <= write_data_in; - when CSR_SUP1 => - sup1 <= write_data_in; - when others => - -- Ignore writes to invalid or read-only registers - end case; - end if; - end if; - end if; - end process write; - - status_out <= exception_context.status when exception_context_write = '1' else status_register; - - read: process(clk) - begin - if rising_edge(clk) then - --if exception_context_write = '1' then - -- status_out <= exception_context.status; - --else - -- status_out <= status_register; - --end if; - - if write_mode /= CSR_WRITE_NONE and write_address = CSR_EVEC then - evec_out <= write_data_in; - else - evec_out <= evec; - end if; - - if write_mode /= CSR_WRITE_NONE and write_address = read_address then - read_data_out <= write_data_in; - else - case read_address is - - -- Status and control registers: - when CSR_STATUS => -- Status register - read_data_out <= to_std_logic_vector(status_register); - when CSR_HARTID => -- Processor ID - read_data_out <= PROCESSOR_ID; - when CSR_FROMHOST => -- Fromhost data - read_data_out <= fromhost; - when CSR_EPC | CSR_EPC_SRET => -- Exception PC value - read_data_out <= epc; - when CSR_EVEC => -- Exception handler address - read_data_out <= evec; - when CSR_CAUSE => -- Exception cause - read_data_out <= to_std_logic_vector(cause); - when CSR_BADVADDR => -- Load/store address responsible for the exception - read_data_out <= badvaddr; - - -- Supporting registers: - when CSR_SUP0 => - read_data_out <= sup0; - when CSR_SUP1 => - read_data_out <= sup1; - - -- Timers and counters: - when CSR_TIME => - read_data_out <= counter_time(31 downto 0); - when CSR_TIMEH => - read_data_out <= counter_time(63 downto 32); - when CSR_CYCLE => - read_data_out <= counter_cycle(31 downto 0); - when CSR_CYCLEH => - read_data_out <= counter_cycle(63 downto 32); - when CSR_INSTRET => - read_data_out <= counter_instret(31 downto 0); - when CSR_INSTRETH => - read_data_out <= counter_instret(63 downto 32); - - -- Return zero from write-only registers and invalid register addresses: - when others => - read_data_out <= (others => '0'); - end case; - end if; - end if; - end process read; - - timer_counter: entity work.pp_counter - port map( - clk => timer_clk, - reset => reset, - count => counter_time, - increment => '1' - ); - - cycle_counter: entity work.pp_counter - port map( - clk => clk, - reset => reset, - count => counter_cycle, - increment => '1' - ); - - instret_counter: entity work.pp_counter - port map( - clk => clk, - reset => reset, - count => counter_instret, - increment => count_instruction - ); - -end architecture behaviour; Index: cache-playground/src/pp_csr.vhd =================================================================== --- cache-playground/src/pp_csr.vhd (revision 44) +++ cache-playground/src/pp_csr.vhd (nonexistent) @@ -1,144 +0,0 @@ --- The Potato Processor - A simple processor for FPGAs --- (c) Kristian Klomsten Skordal 2014 - 2015 --- Report bugs and issues on - -library ieee; -use ieee.std_logic_1164.all; - ---! @brief Package containing constants and utility functions relating to status and control registers. -package pp_csr is - - --! Type used for specifying control and status register addresses. - subtype csr_address is std_logic_vector(11 downto 0); - - --! Type used for exception cause values. - subtype csr_exception_cause is std_logic_vector(4 downto 0); - - function to_std_logic_vector(input : in csr_exception_cause) return std_logic_vector; - - --! Control/status register write mode: - type csr_write_mode is ( - CSR_WRITE_NONE, CSR_WRITE_SET, CSR_WRITE_CLEAR, CSR_WRITE_REPLACE - ); - - -- Exception cause values: - constant CSR_CAUSE_INSTR_MISALIGN : csr_exception_cause := b"00000"; - constant CSR_CAUSE_INSTR_FETCH : csr_exception_cause := b"00001"; - constant CSR_CAUSE_INVALID_INSTR : csr_exception_cause := b"00010"; - constant CSR_CAUSE_SYSCALL : csr_exception_cause := b"00110"; - constant CSR_CAUSE_BREAKPOINT : csr_exception_cause := b"00111"; - constant CSR_CAUSE_LOAD_MISALIGN : csr_exception_cause := b"01000"; - constant CSR_CAUSE_STORE_MISALIGN : csr_exception_cause := b"01001"; - constant CSR_CAUSE_LOAD_ERROR : csr_exception_cause := b"01010"; - constant CSR_CAUSE_STORE_ERROR : csr_exception_cause := b"01011"; - constant CSR_CAUSE_FROMHOST : csr_exception_cause := b"11110"; - constant CSR_CAUSE_NONE : csr_exception_cause := b"11111"; - - constant CSR_CAUSE_IRQ_BASE : csr_exception_cause := b"10000"; - - -- Control register IDs, specified in the immediate of csr* instructions: - constant CSR_STATUS : csr_address := x"50a"; - constant CSR_HARTID : csr_address := x"50b"; - constant CSR_SUP0 : csr_address := x"500"; - constant CSR_SUP1 : csr_address := x"501"; - constant CSR_BADVADDR : csr_address := x"503"; - constant CSR_TOHOST : csr_address := x"51e"; - constant CSR_FROMHOST : csr_address := x"51f"; - constant CSR_CYCLE : csr_address := x"c00"; - constant CSR_CYCLEH : csr_address := x"c80"; - constant CSR_TIME : csr_address := x"c01"; - constant CSR_TIMEH : csr_address := x"c81"; - constant CSR_INSTRET : csr_address := x"c02"; - constant CSR_INSTRETH : csr_address := x"c82"; - constant CSR_EPC : csr_address := x"502"; - constant CSR_EVEC : csr_address := x"508"; - constant CSR_CAUSE : csr_address := x"509"; - - -- Values used as control register IDs in SRET, SCALL and SBREAK: - constant CSR_EPC_SRET : csr_address := x"800"; - - -- Status register bit indices: - constant CSR_SR_S : natural := 0; - constant CSR_SR_PS : natural := 1; - constant CSR_SR_EI : natural := 2; - constant CSR_SR_PEI : natural := 3; - - -- Status register in Potato: - -- * Bit 0, S: Supervisor mode, always 1 - -- * Bit 1, PS: Previous supervisor mode bit, always 1 - -- * Bit 2, EI: Enable interrupts bit - -- * Bit 3, PEI: Previous enable interrupts bit - -- * Bits 23 downto 16, IM: Interrupt mask - -- * Bits 31 downto 24, PIM: Previous interrupt mask - - -- Status register record: - type csr_status_register is - record - ei, pei : std_logic; - im, pim : std_logic_vector(7 downto 0); - end record; - - -- Exception context; this record contains all state that is stored - -- when an exception is taken. - type csr_exception_context is - record - status : csr_status_register; - cause : csr_exception_cause; - badvaddr : std_logic_vector(31 downto 0); - end record; - - -- Reset value of the status register: - constant CSR_SR_DEFAULT : csr_status_register := (ei => '0', pei => '0', im => x"00", pim => x"00"); - - -- Converts a status register record into an std_logic_vector: - function to_std_logic_vector(input : in csr_status_register) - return std_logic_vector; - - -- Converts an std_logic_vector into a status register record: - function to_csr_status_register(input : in std_logic_vector(31 downto 0)) - return csr_status_register; - - --! Checks if a control register is writeable. - function csr_is_writeable(csr : in csr_address) return boolean; - -end package pp_csr; - -package body pp_csr is - - function to_std_logic_vector(input : in csr_exception_cause) - return std_logic_vector is - begin - return (31 downto 5 => '0') & input; - end function to_std_logic_vector; - - function to_std_logic_vector(input : in csr_status_register) - return std_logic_vector is - begin - return input.pim & input.im & (15 downto 4 => '0') & input.pei & input.ei & '1' & '1'; - end function to_std_logic_vector; - - function to_csr_status_register(input : in std_logic_vector(31 downto 0)) - return csr_status_register - is - variable retval : csr_status_register; - begin - retval.ei := input(CSR_SR_EI); - retval.pei := input(CSR_SR_PEI); - retval.im := input(23 downto 16); - retval.pim := input(31 downto 24); - return retval; - end function to_csr_status_register; - - function csr_is_writeable(csr : in csr_address) return boolean is - begin - case csr is - when CSR_FROMHOST | CSR_CYCLE | CSR_CYCLEH | CSR_HARTID - | CSR_TIME | CSR_TIMEH | CSR_INSTRET | CSR_INSTRETH - | CSR_CAUSE | CSR_BADVADDR => - return false; - when others => - return true; - end case; - end function csr_is_writeable; - -end package body pp_csr; Index: cache-playground/src/pp_csr_alu.vhd =================================================================== --- cache-playground/src/pp_csr_alu.vhd (revision 44) +++ cache-playground/src/pp_csr_alu.vhd (nonexistent) @@ -1,43 +0,0 @@ --- The Potato Processor - A simple processor for FPGAs --- (c) Kristian Klomsten Skordal 2014 --- Report bugs and issues on - -library ieee; -use ieee.std_logic_1164.all; -use ieee.numeric_std.all; - -use work.pp_csr.all; - ---! @brief ALU used for calculating new values of control and status registers. -entity pp_csr_alu is - port( - x, y : in std_logic_vector(31 downto 0); - result : out std_logic_vector(31 downto 0); - immediate : in std_logic_vector(4 downto 0); - use_immediate : in std_logic; - write_mode : in csr_write_mode - ); -end entity pp_csr_alu; - -architecture behaviour of pp_csr_alu is - signal a, b : std_logic_vector(31 downto 0); -begin - - a <= x; - b <= y when use_immediate = '0' else std_logic_vector(resize(unsigned(immediate), b'length)); - - calculate: process(a, b, write_mode) - begin - case write_mode is - when CSR_WRITE_NONE => - result <= a; - when CSR_WRITE_SET => - result <= a or b; - when CSR_WRITE_CLEAR => - result <= a and (not b); - when CSR_WRITE_REPLACE => - result <= b; - end case; - end process calculate; - -end architecture behaviour; Index: cache-playground/src/pp_core.vhd =================================================================== --- cache-playground/src/pp_core.vhd (revision 44) +++ cache-playground/src/pp_core.vhd (nonexistent) @@ -1,446 +0,0 @@ --- The Potato Processor - A simple processor for FPGAs --- (c) Kristian Klomsten Skordal 2014 - 2015 --- Report bugs and issues on - -library ieee; -use ieee.std_logic_1164.all; -use ieee.numeric_std.all; - -use work.pp_types.all; -use work.pp_constants.all; -use work.pp_utilities.all; -use work.pp_csr.all; - ---! @brief The Potato Processor is a simple processor core for use in FPGAs. ---! @details ---! It implements the RV32I (RISC-V base integer subset) ISA with additional ---! instructions for manipulation of control and status registers from the ---! currently unpublished supervisor extension. -entity pp_core is - generic( - PROCESSOR_ID : std_logic_vector(31 downto 0) := x"00000000"; --! Processor ID. - RESET_ADDRESS : std_logic_vector(31 downto 0) := x"00000000" --! Address of the first instruction to execute. - ); - port( - -- Control inputs: - clk : in std_logic; --! Processor clock - reset : in std_logic; --! Reset signal - - timer_clk : in std_logic; --! Clock used for the timer/counter - - -- Instruction memory interface: - imem_address : out std_logic_vector(31 downto 0); --! Address of the next instruction - imem_data_in : in std_logic_vector(31 downto 0); --! Instruction input - imem_req : out std_logic; - imem_ack : in std_logic; - - -- Data memory interface: - dmem_address : out std_logic_vector(31 downto 0); --! Data address - dmem_data_in : in std_logic_vector(31 downto 0); --! Input from the data memory - dmem_data_out : out std_logic_vector(31 downto 0); --! Ouptut to the data memory - dmem_data_size : out std_logic_vector( 1 downto 0); --! Size of the data, 1 = 8 bits, 2 = 16 bits, 0 = 32 bits. - dmem_read_req : out std_logic; --! Data memory read request - dmem_read_ack : in std_logic; --! Data memory read acknowledge - dmem_write_req : out std_logic; --! Data memory write request - dmem_write_ack : in std_logic; --! Data memory write acknowledge - - -- Tohost/fromhost interface: - fromhost_data : in std_logic_vector(31 downto 0); --! Data from the host/simulator. - fromhost_write_en : in std_logic; --! Write enable signal from the host/simulator. - tohost_data : out std_logic_vector(31 downto 0); --! Data to the host/simulator. - tohost_write_en : out std_logic; --! Write enable signal to the host/simulator. - - -- External interrupt input: - irq : in std_logic_vector(7 downto 0) --! IRQ inputs. - ); -end entity pp_core; - -architecture behaviour of pp_core is - - ------- Flush signals ------- - signal flush_if, flush_id, flush_ex : std_logic; - - ------- Stall signals ------- - signal stall_if, stall_id, stall_ex, stall_mem : std_logic; - - -- Signals used to determine if an instruction should be counted - -- by the instret counter: - signal if_count_instruction, id_count_instruction : std_logic; - signal ex_count_instruction, mem_count_instruction : std_logic; - signal wb_count_instruction : std_logic; - - -- CSR read port signals: - signal csr_read_data : std_logic_vector(31 downto 0); - signal csr_read_writeable : boolean; - signal csr_read_address, csr_read_address_p : csr_address; - - -- Status register outputs: - signal status : csr_status_register; - signal evec : std_logic_vector(31 downto 0); - - -- Load hazard detected in the execute stage: - signal load_hazard_detected : std_logic; - - -- Branch targets: - signal exception_target, branch_target : std_logic_vector(31 downto 0); - signal branch_taken, exception_taken : std_logic; - - -- Register file read ports: - signal rs1_address_p, rs2_address_p : register_address; - signal rs1_address, rs2_address : register_address; - signal rs1_data, rs2_data : std_logic_vector(31 downto 0); - - -- Data memory signals: - signal dmem_address_p : std_logic_vector(31 downto 0); - signal dmem_data_size_p : std_logic_vector(1 downto 0); - signal dmem_data_out_p : std_logic_vector(31 downto 0); - signal dmem_read_req_p : std_logic; - signal dmem_write_req_p : std_logic; - - -- Fetch stage signals: - signal if_instruction, if_pc : std_logic_vector(31 downto 0); - signal if_instruction_ready : std_logic; - - -- Decode stage signals: - signal id_funct3 : std_logic_vector(2 downto 0); - signal id_rd_address : register_address; - signal id_rd_write : std_logic; - signal id_rs1_address : register_address; - signal id_rs2_address : register_address; - signal id_csr_address : csr_address; - signal id_csr_write : csr_write_mode; - signal id_csr_use_immediate : std_logic; - signal id_shamt : std_logic_vector(4 downto 0); - signal id_immediate : std_logic_vector(31 downto 0); - signal id_branch : branch_type; - signal id_alu_x_src, id_alu_y_src : alu_operand_source; - signal id_alu_op : alu_operation; - signal id_mem_op : memory_operation_type; - signal id_mem_size : memory_operation_size; - signal id_pc : std_logic_vector(31 downto 0); - signal id_exception : std_logic; - signal id_exception_cause : csr_exception_cause; - - -- Execute stage signals: - signal ex_dmem_address : std_logic_vector(31 downto 0); - signal ex_dmem_data_size : std_logic_vector(1 downto 0); - signal ex_dmem_data_out : std_logic_vector(31 downto 0); - signal ex_dmem_read_req : std_logic; - signal ex_dmem_write_req : std_logic; - signal ex_rd_address : register_address; - signal ex_rd_data : std_logic_vector(31 downto 0); - signal ex_rd_write : std_logic; - signal ex_pc : std_logic_vector(31 downto 0); - signal ex_csr_address : csr_address; - signal ex_csr_write : csr_write_mode; - signal ex_csr_data : std_logic_vector(31 downto 0); - signal ex_branch : branch_type; - signal ex_mem_op : memory_operation_type; - signal ex_mem_size : memory_operation_size; - signal ex_exception_context : csr_exception_context; - - -- Memory stage signals: - signal mem_rd_write : std_logic; - signal mem_rd_address : register_address; - signal mem_rd_data : std_logic_vector(31 downto 0); - signal mem_csr_address : csr_address; - signal mem_csr_write : csr_write_mode; - signal mem_csr_data : std_logic_vector(31 downto 0); - signal mem_mem_op : memory_operation_type; - - signal mem_exception : std_logic; - signal mem_exception_context : csr_exception_context; - - -- Writeback signals: - signal wb_rd_address : register_address; - signal wb_rd_data : std_logic_vector(31 downto 0); - signal wb_rd_write : std_logic; - signal wb_csr_address : csr_address; - signal wb_csr_write : csr_write_mode; - signal wb_csr_data : std_logic_vector(31 downto 0); - - signal wb_exception : std_logic; - signal wb_exception_context : csr_exception_context; - -begin - - stall_if <= stall_id; - stall_id <= stall_ex; - stall_ex <= load_hazard_detected or stall_mem; - stall_mem <= to_std_logic(memop_is_load(mem_mem_op) and dmem_read_ack = '0') - or to_std_logic(mem_mem_op = MEMOP_TYPE_STORE and dmem_write_ack = '0'); - - flush_if <= (branch_taken or exception_taken) and not stall_if; - flush_id <= (branch_taken or exception_taken) and not stall_id; - flush_ex <= (branch_taken or exception_taken) and not stall_ex; - - ------- Control and status module ------- - csr_unit: entity work.pp_csr_unit - generic map( - PROCESSOR_ID => PROCESSOR_ID - ) port map( - clk => clk, - reset => reset, - timer_clk => timer_clk, - count_instruction => wb_count_instruction, - fromhost_data => fromhost_data, - fromhost_updated => fromhost_write_en, - tohost_data => tohost_data, - tohost_updated => tohost_write_en, - read_address => csr_read_address, - read_data_out => csr_read_data, - read_writeable => csr_read_writeable, - write_address => wb_csr_address, - write_data_in => wb_csr_data, - write_mode => wb_csr_write, - exception_context => wb_exception_context, - exception_context_write => wb_exception, - status_out => status, - evec_out => evec - ); - - csr_read_address <= id_csr_address when stall_ex = '0' else csr_read_address_p; - - store_previous_csr_addr: process(clk, stall_ex) - begin - if rising_edge(clk) and stall_ex = '0' then - csr_read_address_p <= id_csr_address; - end if; - end process store_previous_csr_addr; - - ------- Register file ------- - regfile: entity work.pp_register_file - port map( - clk => clk, - rs1_addr => rs1_address, - rs2_addr => rs2_address, - rs1_data => rs1_data, - rs2_data => rs2_data, - rd_addr => wb_rd_address, - rd_data => wb_rd_data, - rd_write => wb_rd_write - ); - - rs1_address <= id_rs1_address when stall_ex = '0' else rs1_address_p; - rs2_address <= id_rs2_address when stall_ex = '0' else rs2_address_p; - - store_previous_rsaddr: process(clk, stall_ex) - begin - if rising_edge(clk) and stall_ex = '0' then - rs1_address_p <= id_rs1_address; - rs2_address_p <= id_rs2_address; - end if; - end process store_previous_rsaddr; - - ------- Instruction Fetch (IF) Stage ------- - fetch: entity work.pp_fetch - generic map( - RESET_ADDRESS => RESET_ADDRESS - ) port map( - clk => clk, - reset => reset, - imem_address => imem_address, - imem_data_in => imem_data_in, - imem_req => imem_req, - imem_ack => imem_ack, - stall => stall_if, - flush => flush_if, - branch => branch_taken, - exception => exception_taken, - branch_target => branch_target, - evec => exception_target, - instruction_data => if_instruction, - instruction_address => if_pc, - instruction_ready => if_instruction_ready - ); - if_count_instruction <= if_instruction_ready; - - ------- Instruction Decode (ID) Stage ------- - decode: entity work.pp_decode - generic map( - RESET_ADDRESS => RESET_ADDRESS, - PROCESSOR_ID => PROCESSOR_ID - ) port map( - clk => clk, - reset => reset, - flush => flush_id, - stall => stall_id, - instruction_data => if_instruction, - instruction_address => if_pc, - instruction_ready => if_instruction_ready, - instruction_count => if_count_instruction, - funct3 => id_funct3, - rs1_addr => id_rs1_address, - rs2_addr => id_rs2_address, - rd_addr => id_rd_address, - csr_addr => id_csr_address, - shamt => id_shamt, - immediate => id_immediate, - rd_write => id_rd_write, - branch => id_branch, - alu_x_src => id_alu_x_src, - alu_y_src => id_alu_y_src, - alu_op => id_alu_op, - mem_op => id_mem_op, - mem_size => id_mem_size, - count_instruction => id_count_instruction, - pc => id_pc, - csr_write => id_csr_write, - csr_use_imm => id_csr_use_immediate, - decode_exception => id_exception, - decode_exception_cause => id_exception_cause - ); - - ------- Execute (EX) Stage ------- - execute: entity work.pp_execute - port map( - clk => clk, - reset => reset, - stall => stall_ex, - flush => flush_ex, - irq => irq, - dmem_address => ex_dmem_address, - dmem_data_size => ex_dmem_data_size, - dmem_data_out => ex_dmem_data_out, - dmem_read_req => ex_dmem_read_req, - dmem_write_req => ex_dmem_write_req, - rs1_addr_in => rs1_address, - rs2_addr_in => rs2_address, - rd_addr_in => id_rd_address, - rd_addr_out => ex_rd_address, - rs1_data_in => rs1_data, - rs2_data_in => rs2_data, - shamt_in => id_shamt, - immediate_in => id_immediate, - funct3_in => id_funct3, - pc_in => id_pc, - pc_out => ex_pc, - csr_addr_in => csr_read_address, - csr_addr_out => ex_csr_address, - csr_write_in => id_csr_write, - csr_write_out => ex_csr_write, - csr_value_in => csr_read_data, - csr_value_out => ex_csr_data, - csr_writeable_in => csr_read_writeable, - csr_use_immediate_in => id_csr_use_immediate, - alu_op_in => id_alu_op, - alu_x_src_in => id_alu_x_src, - alu_y_src_in => id_alu_y_src, - rd_write_in => id_rd_write, - rd_write_out => ex_rd_write, - rd_data_out => ex_rd_data, - branch_in => id_branch, - branch_out => ex_branch, - mem_op_in => id_mem_op, - mem_op_out => ex_mem_op, - mem_size_in => id_mem_size, - mem_size_out => ex_mem_size, - count_instruction_in => id_count_instruction, - count_instruction_out => ex_count_instruction, - status_in => status, - evec_in => evec, - evec_out => exception_target, - decode_exception_in => id_exception, - decode_exception_cause_in => id_exception_cause, - exception_out => exception_taken, - exception_context_out => ex_exception_context, - jump_out => branch_taken, - jump_target_out => branch_target, - mem_rd_write => mem_rd_write, - mem_rd_addr => mem_rd_address, - mem_rd_value => mem_rd_data, - mem_csr_addr => mem_csr_address, - mem_csr_value => mem_csr_data, - mem_csr_write => mem_csr_write, - mem_exception => mem_exception, - mem_exception_context => mem_exception_context, - wb_rd_write => wb_rd_write, - wb_rd_addr => wb_rd_address, - wb_rd_value => wb_rd_data, - wb_csr_addr => wb_csr_address, - wb_csr_value => wb_csr_data, - wb_csr_write => wb_csr_write, - wb_exception => wb_exception, - wb_exception_context => wb_exception_context, - mem_mem_op => mem_mem_op, - hazard_detected => load_hazard_detected - ); - - dmem_address <= ex_dmem_address when stall_mem = '0' else dmem_address_p; - dmem_data_size <= ex_dmem_data_size when stall_mem = '0' else dmem_data_size_p; - dmem_data_out <= ex_dmem_data_out when stall_mem = '0' else dmem_data_out_p; - dmem_read_req <= ex_dmem_read_req when stall_mem = '0' else dmem_read_req_p; - dmem_write_req <= ex_dmem_write_req when stall_mem = '0' else dmem_write_req_p; - - store_previous_dmem_address: process(clk, stall_mem) - begin - if rising_edge(clk) and stall_mem = '0' then - dmem_address_p <= ex_dmem_address; - dmem_data_size_p <= ex_dmem_data_size; - dmem_data_out_p <= ex_dmem_data_out; - dmem_read_req_p <= ex_dmem_read_req; - dmem_write_req_p <= ex_dmem_write_req; - end if; - end process store_previous_dmem_address; - - ------- Memory (MEM) Stage ------- - memory: entity work.pp_memory - port map( - clk => clk, - reset => reset, - stall => stall_mem, - dmem_data_in => dmem_data_in, - dmem_read_ack => dmem_read_ack, - dmem_write_ack => dmem_write_ack, - pc => ex_pc, - rd_write_in => ex_rd_write, - rd_write_out => mem_rd_write, - rd_data_in => ex_rd_data, - rd_data_out => mem_rd_data, - rd_addr_in => ex_rd_address, - rd_addr_out => mem_rd_address, - branch => ex_branch, - mem_op_in => ex_mem_op, - mem_op_out => mem_mem_op, - mem_size_in => ex_mem_size, - count_instr_in => ex_count_instruction, - count_instr_out => mem_count_instruction, - exception_in => exception_taken, - exception_out => mem_exception, - exception_context_in => ex_exception_context, - exception_context_out => mem_exception_context, - csr_addr_in => ex_csr_address, - csr_addr_out => mem_csr_address, - csr_write_in => ex_csr_write, - csr_write_out => mem_csr_write, - csr_data_in => ex_csr_data, - csr_data_out => mem_csr_data - ); - - ------- Writeback (WB) Stage ------- - writeback: entity work.pp_writeback - port map( - clk => clk, - reset => reset, - count_instr_in => mem_count_instruction, - count_instr_out => wb_count_instruction, - exception_ctx_in => mem_exception_context, - exception_ctx_out => wb_exception_context, - exception_in => mem_exception, - exception_out => wb_exception, - csr_write_in => mem_csr_write, - csr_write_out => wb_csr_write, - csr_data_in => mem_csr_data, - csr_data_out => wb_csr_data, - csr_addr_in => mem_csr_address, - csr_addr_out => wb_csr_address, - rd_addr_in => mem_rd_address, - rd_addr_out => wb_rd_address, - rd_write_in => mem_rd_write, - rd_write_out => wb_rd_write, - rd_data_in => mem_rd_data, - rd_data_out => wb_rd_data - ); - -end architecture behaviour; - Index: cache-playground/src/pp_fetch.vhd =================================================================== --- cache-playground/src/pp_fetch.vhd (revision 44) +++ cache-playground/src/pp_fetch.vhd (nonexistent) @@ -1,89 +0,0 @@ --- The Potato Processor - A simple processor for FPGAs --- (c) Kristian Klomsten Skordal 2014 - 2015 --- Report bugs and issues on - -library ieee; -use ieee.std_logic_1164.all; -use ieee.numeric_std.all; - -use work.pp_constants.all; - ---! @brief Instruction fetch unit. -entity pp_fetch is - generic( - RESET_ADDRESS : std_logic_vector(31 downto 0) := x"00000000" - ); - port( - clk : in std_logic; - reset : in std_logic; - - -- Instruction memory connections: - imem_address : out std_logic_vector(31 downto 0); - imem_data_in : in std_logic_vector(31 downto 0); - imem_req : out std_logic; - imem_ack : in std_logic; - - -- Control inputs: - stall : in std_logic; - flush : in std_logic; - branch : in std_logic; - exception : in std_logic; - - branch_target : in std_logic_vector(31 downto 0); - evec : in std_logic_vector(31 downto 0); - - -- Outputs to the instruction decode unit: - instruction_data : out std_logic_vector(31 downto 0); - instruction_address : out std_logic_vector(31 downto 0); - instruction_ready : out std_logic - ); -end entity pp_fetch; - -architecture behaviour of pp_fetch is - signal pc : std_logic_vector(31 downto 0); - signal pc_next : std_logic_vector(31 downto 0); - signal cancel_fetch : std_logic; -begin - - imem_address <= pc_next when cancel_fetch = '0' else pc; - - instruction_data <= imem_data_in; - instruction_ready <= imem_ack and (not stall) and (not cancel_fetch); - instruction_address <= pc; - - imem_req <= '1'; - - set_pc: process(clk) - begin - if rising_edge(clk) then - if reset = '1' then - pc <= RESET_ADDRESS; - cancel_fetch <= '0'; - else - if (exception = '1' or branch = '1') and imem_ack = '0' then - cancel_fetch <= '1'; - pc <= pc_next; - elsif cancel_fetch = '1' and imem_ack = '1' then - --pc <= pc_next; - cancel_fetch <= '0'; - else - pc <= pc_next; - end if; - end if; - end if; - end process set_pc; - - calc_next_pc: process(reset, stall, branch, exception, imem_ack, branch_target, evec, pc, cancel_fetch) - begin - if exception = '1' then - pc_next <= evec; - elsif branch = '1' then - pc_next <= branch_target; - elsif imem_ack = '1' and stall = '0' and cancel_fetch = '0' then - pc_next <= std_logic_vector(unsigned(pc) + 4); - else - pc_next <= pc; - end if; - end process calc_next_pc; - -end architecture behaviour; Index: cache-playground/src/pp_execute.vhd =================================================================== --- cache-playground/src/pp_execute.vhd (revision 44) +++ cache-playground/src/pp_execute.vhd (nonexistent) @@ -1,519 +0,0 @@ --- The Potato Processor - A simple processor for FPGAs --- (c) Kristian Klomsten Skordal 2014 - 2015 --- Report bugs and issues on - -library ieee; -use ieee.std_logic_1164.all; -use ieee.numeric_std.all; - -use work.pp_types.all; -use work.pp_csr.all; -use work.pp_utilities.all; - -entity pp_execute is - port( - clk : in std_logic; - reset : in std_logic; - - stall, flush : in std_logic; - - -- IRQ input: - irq : in std_logic_vector(7 downto 0); - - -- Data memory outputs: - dmem_address : out std_logic_vector(31 downto 0); - dmem_data_out : out std_logic_vector(31 downto 0); - dmem_data_size : out std_logic_vector( 1 downto 0); - dmem_read_req : out std_logic; - dmem_write_req : out std_logic; - - -- Register addresses: - rs1_addr_in, rs2_addr_in, rd_addr_in : in register_address; - rd_addr_out : out register_address; - - -- Register values: - rs1_data_in, rs2_data_in : in std_logic_vector(31 downto 0); - rd_data_out : out std_logic_vector(31 downto 0); - - -- Constant values: - shamt_in : in std_logic_vector(4 downto 0); - immediate_in : in std_logic_vector(31 downto 0); - - -- Instruction address: - pc_in : in std_logic_vector(31 downto 0); - pc_out : out std_logic_vector(31 downto 0); - - -- Funct3 value from the instruction, used to choose which comparison - -- is used when branching: - funct3_in : in std_logic_vector(2 downto 0); - - -- CSR signals: - csr_addr_in : in csr_address; - csr_addr_out : out csr_address; - csr_write_in : in csr_write_mode; - csr_write_out : out csr_write_mode; - csr_value_in : in std_logic_vector(31 downto 0); - csr_value_out : out std_logic_vector(31 downto 0); - csr_writeable_in : in boolean; - csr_use_immediate_in : in std_logic; - - -- Control signals: - alu_op_in : in alu_operation; - alu_x_src_in : in alu_operand_source; - alu_y_src_in : in alu_operand_source; - rd_write_in : in std_logic; - rd_write_out : out std_logic; - branch_in : in branch_type; - branch_out : out branch_type; - - -- Memory control signals: - mem_op_in : in memory_operation_type; - mem_op_out : out memory_operation_type; - mem_size_in : in memory_operation_size; - mem_size_out : out memory_operation_size; - - -- Whether the instruction should be counted: - count_instruction_in : in std_logic; - count_instruction_out : out std_logic; - - -- Exception control registers: - status_in : in csr_status_register; - evec_in : in std_logic_vector(31 downto 0); - evec_out : out std_logic_vector(31 downto 0); - - -- Exception signals: - decode_exception_in : in std_logic; - decode_exception_cause_in : in csr_exception_cause; - - -- Exception outputs: - exception_out : out std_logic; - exception_context_out : out csr_exception_context; - - -- Control outputs: - jump_out : out std_logic; - jump_target_out : out std_logic_vector(31 downto 0); - - -- Inputs to the forwarding logic from the MEM stage: - mem_rd_write : in std_logic; - mem_rd_addr : in register_address; - mem_rd_value : in std_logic_vector(31 downto 0); - mem_csr_addr : in csr_address; - mem_csr_write : in csr_write_mode; - mem_csr_value : in std_logic_vector(31 downto 0); - mem_exception : in std_logic; - mem_exception_context : in csr_exception_context; - - -- Inputs to the forwarding logic from the WB stage: - wb_rd_write : in std_logic; - wb_rd_addr : in register_address; - wb_rd_value : in std_logic_vector(31 downto 0); - wb_csr_addr : in csr_address; - wb_csr_write : in csr_write_mode; - wb_csr_value : in std_logic_vector(31 downto 0); - wb_exception : in std_logic; - wb_exception_context : in csr_exception_context; - - -- Hazard detection unit signals: - mem_mem_op : in memory_operation_type; - hazard_detected : out std_logic - ); -end entity pp_execute; - -architecture behaviour of pp_execute is - signal alu_op : alu_operation; - signal alu_x_src, alu_y_src : alu_operand_source; - - signal alu_x, alu_y, alu_result : std_logic_vector(31 downto 0); - - signal rs1_addr, rs2_addr : register_address; - signal rs1_data, rs2_data : std_logic_vector(31 downto 0); - - signal mem_op : memory_operation_type; - signal mem_size : memory_operation_size; - - signal pc : std_logic_vector(31 downto 0); - signal immediate : std_logic_vector(31 downto 0); - signal shamt : std_logic_vector( 4 downto 0); - signal funct3 : std_logic_vector( 2 downto 0); - - signal rs1_forwarded, rs2_forwarded : std_logic_vector(31 downto 0); - - signal branch : branch_type; - signal branch_condition : std_logic; - signal do_jump : std_logic; - signal jump_target : std_logic_vector(31 downto 0); - - signal sr : csr_status_register; - signal evec, evec_forwarded : std_logic_vector(31 downto 0); - - signal csr_write : csr_write_mode; - signal csr_addr : csr_address; - signal csr_use_immediate : std_logic; - signal csr_writeable : boolean; - - signal csr_value, csr_value_forwarded : std_logic_vector(31 downto 0); - - signal decode_exception : std_logic; - signal decode_exception_cause : csr_exception_cause; - - signal exception_taken : std_logic; - signal exception_cause : csr_exception_cause; - signal exception_vaddr : std_logic_vector(31 downto 0); - - signal exception_context_forwarded : csr_exception_context; - - signal data_misaligned, instr_misaligned : std_logic; - - signal irq_asserted : std_logic; - signal irq_asserted_num : std_logic_vector(3 downto 0); -begin - - -- Register values should not be latched in by a clocked process, - -- this is already done in the register files. - csr_value <= csr_value_in; - rd_data_out <= alu_result; - - branch_out <= branch; - - mem_op_out <= mem_op; - mem_size_out <= mem_size; - - csr_write_out <= csr_write; - csr_addr_out <= csr_addr; - - pc_out <= pc; - - exception_out <= exception_taken; - exception_context_out <= ( - status => exception_context_forwarded.status, - cause => exception_cause, - badvaddr => exception_vaddr - ) when exception_taken = '1' else exception_context_forwarded; - - do_jump <= (to_std_logic(branch = BRANCH_JUMP or branch = BRANCH_JUMP_INDIRECT) - or (to_std_logic(branch = BRANCH_CONDITIONAL) and branch_condition) - or to_std_logic(branch = BRANCH_SRET)) and not stall; - jump_out <= do_jump; - jump_target_out <= jump_target; - - evec_out <= evec_forwarded; - exception_taken <= (decode_exception or to_std_logic(exception_cause /= CSR_CAUSE_NONE) or irq_asserted) and not stall; - - irq_asserted <= to_std_logic(exception_context_forwarded.status.ei = '1' and - (irq and exception_context_forwarded.status.im) /= x"00"); - - rs1_data <= rs1_data_in; - rs2_data <= rs2_data_in; - - dmem_address <= alu_result; - dmem_data_out <= rs2_forwarded; - dmem_write_req <= '1' when mem_op = MEMOP_TYPE_STORE else '0'; - dmem_read_req <= '1' when memop_is_load(mem_op) else '0'; - - pipeline_register: process(clk) - begin - if rising_edge(clk) then - if reset = '1' or flush = '1' then - rd_write_out <= '0'; - branch <= BRANCH_NONE; - csr_write <= CSR_WRITE_NONE; - mem_op <= MEMOP_TYPE_NONE; - decode_exception <= '0'; - count_instruction_out <= '0'; - elsif stall = '0' then - pc <= pc_in; - count_instruction_out <= count_instruction_in; - - -- Register signals: - rd_write_out <= rd_write_in; - rd_addr_out <= rd_addr_in; - rs1_addr <= rs1_addr_in; - rs2_addr <= rs2_addr_in; - - -- ALU signals: - alu_op <= alu_op_in; - alu_x_src <= alu_x_src_in; - alu_y_src <= alu_y_src_in; - - -- Control signals: - branch <= branch_in; - mem_op <= mem_op_in; - mem_size <= mem_size_in; - - -- Constant values: - immediate <= immediate_in; - shamt <= shamt_in; - funct3 <= funct3_in; - - -- CSR signals: - csr_write <= csr_write_in; - csr_addr <= csr_addr_in; - csr_use_immediate <= csr_use_immediate_in; - csr_writeable <= csr_writeable_in; - - -- Status register; - sr <= status_in; - - -- Exception vector base: - evec <= evec_in; - - -- Instruction decoder exceptions: - decode_exception <= decode_exception_in; - decode_exception_cause <= decode_exception_cause_in; - end if; - end if; - end process pipeline_register; - - set_data_size: process(mem_size) - begin - case mem_size is - when MEMOP_SIZE_BYTE => - dmem_data_size <= b"01"; - when MEMOP_SIZE_HALFWORD => - dmem_data_size <= b"10"; - when MEMOP_SIZE_WORD => - dmem_data_size <= b"00"; - when others => - dmem_data_size <= b"11"; - end case; - end process set_data_size; - - get_irq_num: process(irq, exception_context_forwarded) - variable temp : std_logic_vector(3 downto 0); - begin - temp := (others => '0'); - - for i in 0 to 7 loop - if irq(i) = '1' and exception_context_forwarded.status.im(i) = '1' then - temp := std_logic_vector(to_unsigned(i, temp'length)); - exit; - end if; - end loop; - - irq_asserted_num <= temp; - end process get_irq_num; - - data_misalign_check: process(mem_size, alu_result) - begin - case mem_size is - when MEMOP_SIZE_HALFWORD => - if alu_result(0) /= '0' then - data_misaligned <= '1'; - else - data_misaligned <= '0'; - end if; - when MEMOP_SIZE_WORD => - if alu_result(1 downto 0) /= b"00" then - data_misaligned <= '1'; - else - data_misaligned <= '0'; - end if; - when others => - data_misaligned <= '0'; - end case; - end process data_misalign_check; - - instr_misalign_check: process(jump_target, branch, branch_condition, do_jump) - begin - if jump_target(1 downto 0) /= b"00" and do_jump = '1' then - instr_misaligned <= '1'; - else - instr_misaligned <= '0'; - end if; - end process instr_misalign_check; - - find_exception_cause: process(decode_exception, decode_exception_cause, mem_op, - data_misaligned, instr_misaligned, irq_asserted, irq_asserted_num) - begin - if irq_asserted = '1' then - exception_cause <= std_logic_vector(unsigned(CSR_CAUSE_IRQ_BASE) + unsigned(irq_asserted_num)); - elsif decode_exception = '1' then - exception_cause <= decode_exception_cause; - elsif mem_op = MEMOP_TYPE_INVALID then - exception_cause <= CSR_CAUSE_INVALID_INSTR; - elsif instr_misaligned = '1' then - exception_cause <= CSR_CAUSE_INSTR_MISALIGN; - elsif data_misaligned = '1' and mem_op = MEMOP_TYPE_STORE then - exception_cause <= CSR_CAUSE_STORE_MISALIGN; - elsif data_misaligned = '1' and memop_is_load(mem_op) then - exception_cause <= CSR_CAUSE_LOAD_MISALIGN; - else - exception_cause <= CSR_CAUSE_NONE; - end if; - end process find_exception_cause; - - find_exception_vaddr: process(instr_misaligned, data_misaligned, jump_target, alu_result) - begin - if instr_misaligned = '1' then - exception_vaddr <= jump_target; - elsif data_misaligned = '1' then - exception_vaddr <= alu_result; - else - exception_vaddr <= (others => '0'); - end if; - end process find_exception_vaddr; - - calc_jump_tgt: process(branch, pc, rs1_forwarded, immediate, csr_value_forwarded) - begin - case branch is - when BRANCH_JUMP | BRANCH_CONDITIONAL => - jump_target <= std_logic_vector(unsigned(pc) + unsigned(immediate)); - when BRANCH_JUMP_INDIRECT => - jump_target <= std_logic_vector(unsigned(rs1_forwarded) + unsigned(immediate)); - when BRANCH_SRET => - jump_target <= csr_value_forwarded; -- Will be the EPC value in the case of SRET - when others => - jump_target <= (others => '0'); - end case; - end process calc_jump_tgt; - - alu_x_mux: entity work.pp_alu_mux - port map( - source => alu_x_src, - register_value => rs1_forwarded, - immediate_value => immediate, - shamt_value => shamt, - pc_value => pc, - csr_value => csr_value_forwarded, - output => alu_x - ); - - alu_y_mux: entity work.pp_alu_mux - port map( - source => alu_y_src, - register_value => rs2_forwarded, - immediate_value => immediate, - shamt_value => shamt, - pc_value => pc, - csr_value => csr_value_forwarded, - output => alu_y - ); - - alu_x_forward: process(mem_rd_write, mem_rd_value, mem_rd_addr, rs1_addr, - rs1_data, wb_rd_write, wb_rd_addr, wb_rd_value) - begin - if mem_rd_write = '1' and mem_rd_addr = rs1_addr and mem_rd_addr /= b"00000" then - rs1_forwarded <= mem_rd_value; - elsif wb_rd_write = '1' and wb_rd_addr = rs1_addr and wb_rd_addr /= b"00000" then - rs1_forwarded <= wb_rd_value; - else - rs1_forwarded <= rs1_data; - end if; - end process alu_x_forward; - - alu_y_forward: process(mem_rd_write, mem_rd_value, mem_rd_addr, rs2_addr, - rs2_data, wb_rd_write, wb_rd_addr, wb_rd_value) - begin - if mem_rd_write = '1' and mem_rd_addr = rs2_addr and mem_rd_addr /= b"00000" then - rs2_forwarded <= mem_rd_value; - elsif wb_rd_write = '1' and wb_rd_addr = rs2_addr and wb_rd_addr /= b"00000" then - rs2_forwarded <= wb_rd_value; - else - rs2_forwarded <= rs2_data; - end if; - end process alu_y_forward; - - csr_forward: process(mem_csr_write, wb_csr_write, csr_addr, mem_csr_addr, wb_csr_addr, - csr_value, mem_csr_value, wb_csr_value, csr_writeable, mem_exception, wb_exception, - mem_exception_context, wb_exception_context) - begin - if csr_addr = CSR_CAUSE and mem_exception = '1' then - csr_value_forwarded <= to_std_logic_vector(mem_exception_context.cause); - elsif csr_addr = CSR_STATUS and mem_exception = '1' then - csr_value_forwarded <= to_std_logic_vector(mem_exception_context.status); - elsif csr_addr = CSR_BADVADDR and mem_exception = '1' then - csr_value_forwarded <= mem_exception_context.badvaddr; - elsif mem_csr_write /= CSR_WRITE_NONE and mem_csr_addr = csr_addr and csr_writeable then - csr_value_forwarded <= mem_csr_value; - elsif csr_addr = CSR_CAUSE and wb_exception = '1' then - csr_value_forwarded <= to_std_logic_vector(wb_exception_context.cause); - elsif csr_addr = CSR_STATUS and wb_exception = '1' then - csr_value_forwarded <= to_std_logic_vector(wb_exception_context.status); - elsif csr_addr = CSR_BADVADDR and wb_exception = '1' then - csr_value_forwarded <= wb_exception_context.badvaddr; - elsif wb_csr_write /= CSR_WRITE_NONE and wb_csr_addr = csr_addr and csr_writeable then - csr_value_forwarded <= wb_csr_value; - else - csr_value_forwarded <= csr_value; - end if; - end process csr_forward; - - evec_forward: process(mem_csr_write, mem_csr_addr, mem_csr_value, - wb_csr_write, wb_csr_addr, wb_csr_value, evec) - begin - if mem_csr_write /= CSR_WRITE_NONE and mem_csr_addr = CSR_EVEC then - evec_forwarded <= mem_csr_value; - elsif wb_csr_write /= CSR_WRITE_NONE and wb_csr_addr = CSR_EVEC then - evec_forwarded <= wb_csr_value; - else - evec_forwarded <= evec; - end if; - end process evec_forward; - - exception_ctx_forward: process(mem_exception, wb_exception, mem_exception_context, wb_exception_context, - exception_cause, exception_vaddr, mem_csr_write, mem_csr_addr, mem_csr_value, - wb_csr_write, wb_csr_addr, wb_csr_value, sr) - begin - if mem_exception = '1' then - exception_context_forwarded <= mem_exception_context; - elsif mem_csr_write /= CSR_WRITE_NONE and mem_csr_addr = CSR_STATUS then - exception_context_forwarded <= ( - status => to_csr_status_register(mem_csr_value), - cause => mem_exception_context.cause, - badvaddr => mem_exception_context.badvaddr); - elsif wb_exception = '1' then - exception_context_forwarded <= wb_exception_context; - elsif wb_csr_write /= CSR_WRITE_NONE and wb_csr_addr = CSR_STATUS then - exception_context_forwarded <= ( - status => to_csr_status_register(wb_csr_value), - cause => wb_exception_context.cause, - badvaddr => wb_exception_context.badvaddr); - else - exception_context_forwarded.status <= sr; - exception_context_forwarded.cause <= exception_cause; - exception_context_forwarded.badvaddr <= exception_vaddr; - end if; - end process exception_ctx_forward; - - detect_load_hazard: process(mem_mem_op, mem_rd_addr, rs1_addr, rs2_addr, - alu_x_src, alu_y_src) - begin - if (mem_mem_op = MEMOP_TYPE_LOAD or mem_mem_op = MEMOP_TYPE_LOAD_UNSIGNED) and - ((alu_x_src = ALU_SRC_REG and mem_rd_addr = rs1_addr and rs1_addr /= b"00000") - or - (alu_y_src = ALU_SRC_REG and mem_rd_addr = rs2_addr and rs2_addr /= b"00000")) - then - hazard_detected <= '1'; - else - hazard_detected <= '0'; - end if; - end process detect_load_hazard; - - branch_comparator: entity work.pp_comparator - port map( - funct3 => funct3, - rs1 => rs1_forwarded, - rs2 => rs2_forwarded, - result => branch_condition - ); - - alu_instance: entity work.pp_alu - port map( - result => alu_result, - x => alu_x, - y => alu_y, - operation => alu_op - ); - - csr_alu_instance: entity work.pp_csr_alu - port map( - x => csr_value_forwarded, - y => rs1_forwarded, - result => csr_value_out, - immediate => rs1_addr, - use_immediate => csr_use_immediate, - write_mode => csr_write - ); - - -end architecture behaviour; Index: cache-playground/src/pp_types.vhd =================================================================== --- cache-playground/src/pp_types.vhd (revision 44) +++ cache-playground/src/pp_types.vhd (nonexistent) @@ -1,70 +0,0 @@ --- The Potato Processor - A simple processor for FPGAs --- (c) Kristian Klomsten Skordal 2014 - 2015 --- Report bugs and issues on - -library ieee; -use ieee.std_logic_1164.all; - -package pp_types is - - --! Type used for register addresses. - subtype register_address is std_logic_vector(4 downto 0); - - --! The available ALU operations. - type alu_operation is ( - ALU_AND, ALU_OR, ALU_XOR, - ALU_SLT, ALU_SLTU, - ALU_ADD, ALU_SUB, - ALU_SRL, ALU_SLL, ALU_SRA, - ALU_NOP, ALU_INVALID - ); - - --! Types of branches. - type branch_type is ( - BRANCH_NONE, BRANCH_JUMP, BRANCH_JUMP_INDIRECT, BRANCH_CONDITIONAL, BRANCH_SRET - ); - - --! Source of an ALU operand. - type alu_operand_source is ( - ALU_SRC_REG, ALU_SRC_IMM, ALU_SRC_SHAMT, ALU_SRC_PC, ALU_SRC_PC_NEXT, ALU_SRC_NULL, ALU_SRC_CSR - ); - - --! Type of memory operation: - type memory_operation_type is ( - MEMOP_TYPE_NONE, MEMOP_TYPE_INVALID, MEMOP_TYPE_LOAD, MEMOP_TYPE_LOAD_UNSIGNED, MEMOP_TYPE_STORE - ); - - -- Determines if a memory operation is a load: - function memop_is_load(input : in memory_operation_type) return boolean; - - --! Size of a memory operation: - type memory_operation_size is ( - MEMOP_SIZE_BYTE, MEMOP_SIZE_HALFWORD, MEMOP_SIZE_WORD - ); - - --! Wishbone master output signals: - type wishbone_master_outputs is record - adr : std_logic_vector(31 downto 0); - sel : std_logic_vector( 3 downto 0); - cyc : std_logic; - stb : std_logic; - we : std_logic; - dat : std_logic_vector(31 downto 0); - end record; - - --! Wishbone master input signals: - type wishbone_master_inputs is record - dat : std_logic_vector(31 downto 0); - ack : std_logic; - end record; - -end package pp_types; - -package body pp_types is - - function memop_is_load(input : in memory_operation_type) return boolean is - begin - return (input = MEMOP_TYPE_LOAD or input = MEMOP_TYPE_LOAD_UNSIGNED); - end function memop_is_load; - -end package body pp_types; Index: cache-playground/src/pp_potato.vhd =================================================================== --- cache-playground/src/pp_potato.vhd (revision 44) +++ cache-playground/src/pp_potato.vhd (nonexistent) @@ -1,149 +0,0 @@ --- The Potato Processor - A simple processor for FPGAs --- (c) Kristian Klomsten Skordal 2014 - 2015 --- Report bugs and issues on - -library ieee; -use ieee.std_logic_1164.all; - -use work.pp_types.all; - ---! @brief The Potato Processor. ---! This file provides a Wishbone-compatible interface to the Potato processor. -entity pp_potato is - generic( - PROCESSOR_ID : std_logic_vector(31 downto 0) := x"00000000"; --! Processor ID. - RESET_ADDRESS : std_logic_vector(31 downto 0) := x"00000000" --! Address of the first instruction to execute. - ); - port( - clk : in std_logic; - reset : in std_logic; - - -- Interrupts: - irq : in std_logic_vector(7 downto 0); - - -- Host/Target interface: - fromhost_data : in std_logic_vector(31 downto 0); - fromhost_updated : in std_logic; - tohost_data : out std_logic_vector(31 downto 0); - tohost_updated : out std_logic; - - -- Wishbone interface: - wb_adr_out : out std_logic_vector(31 downto 0); - wb_sel_out : out std_logic_vector( 3 downto 0); - wb_cyc_out : out std_logic; - wb_stb_out : out std_logic; - wb_we_out : out std_logic; - wb_dat_out : out std_logic_vector(31 downto 0); - wb_dat_in : in std_logic_vector(31 downto 0); - wb_ack_in : in std_logic - ); -end entity pp_potato; - -architecture behaviour of pp_potato is - - -- Instruction memory signals: - signal imem_address : std_logic_vector(31 downto 0); - signal imem_data : std_logic_vector(31 downto 0); - signal imem_req, imem_ack : std_logic; - - -- Data memory signals: - signal dmem_address : std_logic_vector(31 downto 0); - signal dmem_data_in : std_logic_vector(31 downto 0); - signal dmem_data_out : std_logic_vector(31 downto 0); - signal dmem_data_size : std_logic_vector( 1 downto 0); - signal dmem_read_req : std_logic; - signal dmem_read_ack : std_logic; - signal dmem_write_req : std_logic; - signal dmem_write_ack : std_logic; - - -- Wishbone signals: - signal icache_inputs, dmem_if_inputs : wishbone_master_inputs; - signal icache_outputs, dmem_if_outputs : wishbone_master_outputs; - -begin - processor: entity work.pp_core - generic map( - PROCESSOR_ID => PROCESSOR_ID, - RESET_ADDRESS => RESET_ADDRESS - ) port map( - clk => clk, - reset => reset, - timer_clk => clk, - imem_address => imem_address, - imem_data_in => imem_data, - imem_req => imem_req, - imem_ack => imem_ack, - dmem_address => dmem_address, - dmem_data_in => dmem_data_in, - dmem_data_out => dmem_data_out, - dmem_data_size => dmem_data_size, - dmem_read_req => dmem_read_req, - dmem_read_ack => dmem_read_ack, - dmem_write_req => dmem_write_req, - dmem_write_ack => dmem_write_ack, - fromhost_data => fromhost_data, - fromhost_write_en => fromhost_updated, - tohost_data => tohost_data, - tohost_write_en => tohost_updated, - irq => irq - ); - - icache: entity work.pp_icache - generic map( - LINE_SIZE => 4, - NUM_LINES => 128 - ) port map( - clk => clk, - reset => reset, - cache_enable => '1', - cache_flush => '0', - cached_areas => (others => '1'), - mem_address_in => imem_address, - mem_data_out => imem_data, - mem_data_in => (others => '0'), - mem_data_size => b"00", - mem_read_req => imem_req, - mem_read_ack => imem_ack, - mem_write_req => '0', - mem_write_ack => open, - wb_inputs => icache_inputs, - wb_outputs => icache_outputs - ); - - dmem_if: entity work.pp_wb_adapter - port map( - clk => clk, - reset => reset, - dmem_address => dmem_address, - dmem_data_in => dmem_data_out, - dmem_data_out => dmem_data_in, - dmem_data_size => dmem_data_size, - dmem_read_req => dmem_read_req, - dmem_read_ack => dmem_read_ack, - dmem_write_req => dmem_write_req, - dmem_write_ack => dmem_write_ack, - wb_inputs => dmem_if_inputs, - wb_outputs => dmem_if_outputs - ); - - arbiter: entity work.pp_wb_arbiter - port map( - clk => clk, - reset => reset, - --m1_inputs => dmem_if_inputs, - --m1_outputs => dmem_if_outputs, - m1_inputs => icache_inputs, - m1_outputs => icache_outputs, - m2_inputs => dmem_if_inputs, - m2_outputs => dmem_if_outputs, - wb_adr_out => wb_adr_out, - wb_sel_out => wb_sel_out, - wb_cyc_out => wb_cyc_out, - wb_stb_out => wb_stb_out, - wb_we_out => wb_we_out, - wb_dat_out => wb_dat_out, - wb_dat_in => wb_dat_in, - wb_ack_in => wb_ack_in - ); - -end architecture behaviour; Index: cache-playground/src/pp_comparator.vhd =================================================================== --- cache-playground/src/pp_comparator.vhd (revision 44) +++ cache-playground/src/pp_comparator.vhd (nonexistent) @@ -1,43 +0,0 @@ --- The Potato Processor - A simple processor for FPGAs --- (c) Kristian Klomsten Skordal 2014 --- Report bugs and issues on - -library ieee; -use ieee.std_logic_1164.all; -use ieee.numeric_std.all; - -use work.pp_utilities.all; - ---! @brief Component for comparing two registers in the ID stage whens branching. -entity pp_comparator is - port( - funct3 : in std_logic_vector(14 downto 12); - rs1, rs2 : in std_logic_vector(31 downto 0); - result : out std_logic --! Result of the comparison. - ); -end entity pp_comparator; - -architecture behaviour of pp_comparator is -begin - - compare: process(funct3, rs1, rs2) - begin - case funct3 is - when b"000" => -- EQ - result <= to_std_logic(rs1 = rs2); - when b"001" => -- NE - result <= to_std_logic(rs1 /= rs2); - when b"100" => -- LT - result <= to_std_logic(signed(rs1) < signed(rs2)); - when b"101" => -- GE - result <= to_std_logic(signed(rs1) >= signed(rs2)); - when b"110" => -- LTU - result <= to_std_logic(unsigned(rs1) < unsigned(rs2)); - when b"111" => -- GEU - result <= to_std_logic(unsigned(rs1) >= unsigned(rs2)); - when others => - result <= '0'; - end case; - end process compare; - -end architecture behaviour; Index: cache-playground/src/pp_imm_decoder.vhd =================================================================== --- cache-playground/src/pp_imm_decoder.vhd (revision 44) +++ cache-playground/src/pp_imm_decoder.vhd (nonexistent) @@ -1,35 +0,0 @@ --- The Potato Processor - A simple processor for FPGAs --- (c) Kristian Klomsten Skordal 2014 --- Report bugs and issues on - -library ieee; -use ieee.std_logic_1164.all; - ---! @brief Module decoding immediate values from instruction words. -entity pp_imm_decoder is - port( - instruction : in std_logic_vector(31 downto 2); - immediate : out std_logic_vector(31 downto 0) - ); -end entity pp_imm_decoder; - -architecture behaviour of pp_imm_decoder is -begin - decode: process(instruction) - begin - case instruction(6 downto 2) is - when b"01101" | b"00101" => -- U type - immediate <= instruction(31 downto 12) & (11 downto 0 => '0'); - when b"11011" => -- UJ type - immediate <= (31 downto 20 => instruction(31)) & instruction(19 downto 12) & instruction(20) & instruction(30 downto 21) & '0'; - when b"11001" | b"00000" | b"00100" | b"11100"=> -- I type - immediate <= (31 downto 11 => instruction(31)) & instruction(30 downto 20); - when b"11000" => -- SB type - immediate <= (31 downto 12 => instruction(31)) & instruction(7) & instruction(30 downto 25) & instruction(11 downto 8) & '0'; - when b"01000" => -- S type - immediate <= (31 downto 11 => instruction(31)) & instruction(30 downto 25) & instruction(11 downto 7); - when others => - immediate <= (others => '0'); - end case; - end process decode; -end architecture behaviour; Index: cache-playground/src/pp_memory.vhd =================================================================== --- cache-playground/src/pp_memory.vhd (revision 44) +++ cache-playground/src/pp_memory.vhd (nonexistent) @@ -1,161 +0,0 @@ --- The Potato Processor - A simple processor for FPGAs --- (c) Kristian Klomsten Skordal 2014 - 2015 --- Report bugs and issues on - -library ieee; -use ieee.std_logic_1164.all; -use ieee.numeric_std.all; - -use work.pp_types.all; -use work.pp_csr.all; -use work.pp_utilities.all; - -entity pp_memory is - port( - clk : in std_logic; - reset : in std_logic; - stall : in std_logic; - - -- Data memory inputs: - dmem_read_ack : in std_logic; - dmem_write_ack : in std_logic; - dmem_data_in : in std_logic_vector(31 downto 0); - - -- Current PC value: - pc : in std_logic_vector(31 downto 0); - - -- Destination register signals: - rd_write_in : in std_logic; - rd_write_out : out std_logic; - rd_data_in : in std_logic_vector(31 downto 0); - rd_data_out : out std_logic_vector(31 downto 0); - rd_addr_in : in register_address; - rd_addr_out : out register_address; - - -- Control signals: - branch : in branch_type; - mem_op_in : in memory_operation_type; - mem_size_in : in memory_operation_size; - mem_op_out : out memory_operation_type; - - -- Whether the instruction should be counted: - count_instr_in : in std_logic; - count_instr_out : out std_logic; - - -- Exception signals: - exception_in : in std_logic; - exception_out : out std_logic; - exception_context_in : in csr_exception_context; - exception_context_out : out csr_exception_context; - - -- CSR signals: - csr_addr_in : in csr_address; - csr_addr_out : out csr_address; - csr_write_in : in csr_write_mode; - csr_write_out : out csr_write_mode; - csr_data_in : in std_logic_vector(31 downto 0); - csr_data_out : out std_logic_vector(31 downto 0) - ); -end entity pp_memory; - -architecture behaviour of pp_memory is - signal mem_op : memory_operation_type; - signal mem_size : memory_operation_size; - - signal rd_data : std_logic_vector(31 downto 0); -begin - - mem_op_out <= mem_op; - - pipeline_register: process(clk) - begin - if rising_edge(clk) then - if reset = '1' then - rd_write_out <= '0'; - csr_write_out <= CSR_WRITE_NONE; - count_instr_out <= '0'; - mem_op <= MEMOP_TYPE_NONE; - elsif stall = '0' then - mem_size <= mem_size_in; - rd_data <= rd_data_in; - rd_addr_out <= rd_addr_in; - - if exception_in = '1' then - mem_op <= MEMOP_TYPE_NONE; - rd_write_out <= '0'; - csr_write_out <= CSR_WRITE_REPLACE; - csr_addr_out <= CSR_EPC; - csr_data_out <= pc; - count_instr_out <= '0'; - else - mem_op <= mem_op_in; - rd_write_out <= rd_write_in; - csr_write_out <= csr_write_in; - csr_addr_out <= csr_addr_in; - csr_data_out <= csr_data_in; - count_instr_out <= count_instr_in; - end if; - end if; - end if; - end process pipeline_register; - - update_exception_context: process(clk) - begin - if rising_edge(clk) then - if reset = '1' then - exception_out <= '0'; - else - exception_out <= exception_in or to_std_logic(branch = BRANCH_SRET); - - if exception_in = '1' then - exception_context_out.status <= ( - pim => exception_context_in.status.im, - im => (others => '0'), - pei => exception_context_in.status.ei, - ei => '0' - ); - exception_context_out.cause <= exception_context_in.cause; - exception_context_out.badvaddr <= exception_context_in.badvaddr; - elsif branch = BRANCH_SRET then - exception_context_out.status <= ( - pim => exception_context_in.status.pim, - im => exception_context_in.status.pim, - pei => exception_context_in.status.pei, - ei => exception_context_in.status.pei - ); - exception_context_out.cause <= CSR_CAUSE_NONE; - exception_context_out.badvaddr <= (others => '0'); - else - exception_context_out.status <= exception_context_in.status; - exception_context_out.cause <= CSR_CAUSE_NONE; - exception_context_out.badvaddr <= (others => '0'); - end if; - end if; - end if; - end process update_exception_context; - - rd_data_mux: process(rd_data, dmem_data_in, mem_op, mem_size) - begin - if mem_op = MEMOP_TYPE_LOAD or mem_op = MEMOP_TYPE_LOAD_UNSIGNED then - case mem_size is - when MEMOP_SIZE_BYTE => - if mem_op = MEMOP_TYPE_LOAD_UNSIGNED then - rd_data_out <= std_logic_vector(resize(unsigned(dmem_data_in(7 downto 0)), rd_data_out'length)); - else - rd_data_out <= std_logic_vector(resize(signed(dmem_data_in(7 downto 0)), rd_data_out'length)); - end if; - when MEMOP_SIZE_HALFWORD => - if mem_op = MEMOP_TYPE_LOAD_UNSIGNED then - rd_data_out <= std_logic_vector(resize(unsigned(dmem_data_in(15 downto 0)), rd_data_out'length)); - else - rd_data_out <= std_logic_vector(resize(signed(dmem_data_in(15 downto 0)), rd_data_out'length)); - end if; - when MEMOP_SIZE_WORD => - rd_data_out <= dmem_data_in; - end case; - else - rd_data_out <= rd_data; - end if; - end process rd_data_mux; - -end architecture behaviour; Index: cache-playground/src/pp_wb_adapter.vhd =================================================================== --- cache-playground/src/pp_wb_adapter.vhd (revision 44) +++ cache-playground/src/pp_wb_adapter.vhd (nonexistent) @@ -1,126 +0,0 @@ --- The Potato Processor - A simple processor for FPGAs --- (c) Kristian Klomsten Skordal 2014 - 2015 --- Report bugs and issues on - -library ieee; -use ieee.std_logic_1164.all; -use ieee.numeric_std.all; - -use work.pp_types.all; -use work.pp_utilities.all; - ---! @brief Wishbone adapter, for connecting the processor to a Wishbone bus when not using caches. -entity pp_wb_adapter is - port( - clk : in std_logic; - reset : in std_logic; - - -- Processor data memory signals: - signal dmem_address : in std_logic_vector(31 downto 0); - signal dmem_data_in : in std_logic_vector(31 downto 0); -- Data in to the bus - signal dmem_data_out : out std_logic_vector(31 downto 0); -- Data out to the bus - signal dmem_data_size : in std_logic_vector( 1 downto 0); - signal dmem_read_req : in std_logic; - signal dmem_read_ack : out std_logic; - signal dmem_write_req : in std_logic; - signal dmem_write_ack : out std_logic; - - -- Wishbone interface: - wb_inputs : in wishbone_master_inputs; - wb_outputs : out wishbone_master_outputs - ); -end entity pp_wb_adapter; - -architecture behaviour of pp_wb_adapter is - - type states is (IDLE, READ_WAIT_ACK, WRITE_WAIT_ACK); - signal state : states; - - signal dmem_r_ack : std_logic; - - function get_data_shift(size : in std_logic_vector(1 downto 0); address : in std_logic_vector) - return natural is - begin - case size is - when b"01" => - case address(1 downto 0) is - when b"00" => - return 0; - when b"01" => - return 8; - when b"10" => - return 16; - when b"11" => - return 24; - when others => - return 0; - end case; - when b"10" => - if address(1) = '0' then - return 0; - else - return 16; - end if; - when others => - return 0; - end case; - end function get_data_shift; - -begin - - dmem_write_ack <= '1' when state = WRITE_WAIT_ACK and wb_inputs.ack = '1' else '0'; - dmem_read_ack <= dmem_r_ack; - - wishbone: process(clk) - begin - if rising_edge(clk) then - if reset = '1' then - state <= IDLE; - wb_outputs.cyc <= '0'; - wb_outputs.stb <= '0'; - dmem_r_ack <= '0'; - else - case state is - when IDLE => - dmem_r_ack <= '0'; - - -- Prioritize requests from the data memory: - if dmem_write_req = '1' then - wb_outputs.adr <= dmem_address; - wb_outputs.dat <= std_logic_vector(shift_left(unsigned(dmem_data_in), - get_data_shift(dmem_data_size, dmem_address))); - wb_outputs.sel <= wb_get_data_sel(dmem_data_size, dmem_address); - wb_outputs.cyc <= '1'; - wb_outputs.stb <= '1'; - wb_outputs.we <= '1'; - state <= WRITE_WAIT_ACK; - elsif dmem_read_req = '1' then - wb_outputs.adr <= dmem_address; - wb_outputs.sel <= wb_get_data_sel(dmem_data_size, dmem_address); - wb_outputs.cyc <= '1'; - wb_outputs.stb <= '1'; - wb_outputs.we <= '0'; - state <= READ_WAIT_ACK; - end if; - when READ_WAIT_ACK => - if wb_inputs.ack = '1' then - dmem_data_out <= std_logic_vector(shift_right(unsigned(wb_inputs.dat), - get_data_shift(dmem_data_size, dmem_address))); - wb_outputs.cyc <= '0'; - wb_outputs.stb <= '0'; - dmem_r_ack <= '1'; - state <= IDLE; - end if; - when WRITE_WAIT_ACK => - if wb_inputs.ack = '1' then - wb_outputs.cyc <= '0'; - wb_outputs.stb <= '0'; - wb_outputs.we <= '0'; - state <= IDLE; - end if; - end case; - end if; - end if; - end process wishbone; - -end architecture behaviour;
cache-playground/src/pp_wb_adapter.vhd Property changes : Deleted: svn:mergeinfo ## -0,1 +0,0 ## Reverse-merged /potato/branches/cache-playground/src/pp_wb_adapter.vhd:r31-33 Index: cache-playground/src/pp_alu_mux.vhd =================================================================== --- cache-playground/src/pp_alu_mux.vhd (revision 44) +++ cache-playground/src/pp_alu_mux.vhd (nonexistent) @@ -1,49 +0,0 @@ --- The Potato Processor - A simple processor for FPGAs --- (c) Kristian Klomsten Skordal 2014 --- Report bugs and issues on - -library ieee; -use ieee.std_logic_1164.all; -use ieee.numeric_std.all; - -use work.pp_types.all; - ---! @brief Multiplexer used to choose between ALU inputs. -entity pp_alu_mux is - port( - source : in alu_operand_source; - - register_value : in std_logic_vector(31 downto 0); - immediate_value : in std_logic_vector(31 downto 0); - shamt_value : in std_logic_vector( 4 downto 0); - pc_value : in std_logic_vector(31 downto 0); - csr_value : in std_logic_vector(31 downto 0); - - output : out std_logic_vector(31 downto 0) - ); -end entity pp_alu_mux; - -architecture behaviour of pp_alu_mux is -begin - - mux: process(source, register_value, immediate_value, shamt_value, pc_value, csr_value) - begin - case source is - when ALU_SRC_REG => - output <= register_value; - when ALU_SRC_IMM => - output <= immediate_value; - when ALU_SRC_PC => - output <= pc_value; - when ALU_SRC_PC_NEXT => - output <= std_logic_vector(unsigned(pc_value) + 4); - when ALU_SRC_CSR => - output <= csr_value; - when ALU_SRC_SHAMT => - output <= (31 downto 5 => '0') & shamt_value; - when ALU_SRC_NULL => - output <= (others => '0'); - end case; - end process mux; - -end architecture behaviour; Index: cache-playground/src/pp_utilities.vhd =================================================================== --- cache-playground/src/pp_utilities.vhd (revision 44) +++ cache-playground/src/pp_utilities.vhd (nonexistent) @@ -1,94 +0,0 @@ --- The Potato Processor - A simple processor for FPGAs --- (c) Kristian Klomsten Skordal 2014 --- Report bugs and issues on - -library ieee; -use ieee.std_logic_1164.all; - -use work.pp_types.all; -use work.pp_constants.all; - -package pp_utilities is - - --! Converts a boolean to an std_logic. - function to_std_logic(input : in boolean) return std_logic; - - -- Checks if a number is 2^n: - function is_pow2(input : in natural) return boolean; - - --! Calculates log2 with integers. - function log2(input : in natural) return natural; - - -- Gets the value of the sel signals to the wishbone interconnect for the specified - -- operand size and address. - function wb_get_data_sel(size : in std_logic_vector(1 downto 0); address : in std_logic_vector) - return std_logic_vector; - -end package pp_utilities; - -package body pp_utilities is - - function to_std_logic(input : in boolean) return std_logic is - begin - if input then - return '1'; - else - return '0'; - end if; - end function to_std_logic; - - function is_pow2(input : in natural) return boolean is - variable c : natural := 1; - begin - for i in 0 to 30 loop -- FIXME: Simulator complains about 2^31 being out of range! - if input = i then - return true; - end if; - - c := c * 2; - end loop; - - return false; - end function is_pow2; - - function log2(input : in natural) return natural is - variable retval : natural := 0; - variable temp : natural := input; - begin - while temp > 1 loop - retval := retval + 1; - temp := temp / 2; - end loop; - - return retval; - end function log2; - - function wb_get_data_sel(size : in std_logic_vector(1 downto 0); address : in std_logic_vector) - return std_logic_vector is - begin - case size is - when b"01" => - case address(1 downto 0) is - when b"00" => - return b"0001"; - when b"01" => - return b"0010"; - when b"10" => - return b"0100"; - when b"11" => - return b"1000"; - when others => - return b"0001"; - end case; - when b"10" => - if address(1) = '0' then - return b"0011"; - else - return b"1100"; - end if; - when others => - return b"1111"; - end case; - end function wb_get_data_sel; - -end package body pp_utilities; Index: cache-playground/src/pp_writeback.vhd =================================================================== --- cache-playground/src/pp_writeback.vhd (revision 44) +++ cache-playground/src/pp_writeback.vhd (nonexistent) @@ -1,71 +0,0 @@ --- The Potato Processor - A simple processor for FPGAs --- (c) Kristian Klomsten Skordal 2014 - 2015 --- Report bugs and issues on - -library ieee; -use ieee.std_logic_1164.all; -use ieee.numeric_std.all; - -use work.pp_types.all; -use work.pp_csr.all; - -entity pp_writeback is - port( - clk : in std_logic; - reset : in std_logic; - - -- Count instruction: - count_instr_in : in std_logic; - count_instr_out : out std_logic; - - -- Exception signals: - exception_ctx_in : in csr_exception_context; - exception_in : in std_logic; - exception_ctx_out : out csr_exception_context; - exception_out : out std_logic; - - -- CSR signals: - csr_write_in : in csr_write_mode; - csr_write_out : out csr_write_mode; - csr_data_in : in std_logic_vector(31 downto 0); - csr_data_out : out std_logic_vector(31 downto 0); - csr_addr_in : in csr_address; - csr_addr_out : out csr_address; - - -- Destination register interface: - rd_addr_in : in register_address; - rd_addr_out : out register_address; - rd_write_in : in std_logic; - rd_write_out : out std_logic; - rd_data_in : in std_logic_vector(31 downto 0); - rd_data_out : out std_logic_vector(31 downto 0) - ); -end entity pp_writeback; - -architecture behaviour of pp_writeback is -begin - - pipeline_register: process(clk) - begin - if rising_edge(clk) then - if reset = '1' then - rd_write_out <= '0'; - exception_out <= '0'; - count_instr_out <= '0'; - else - count_instr_out <= count_instr_in; - rd_data_out <= rd_data_in; - rd_write_out <= rd_write_in; - rd_addr_out <= rd_addr_in; - - exception_out <= exception_in; - exception_ctx_out <= exception_ctx_in; - - csr_write_out <= csr_write_in; - csr_data_out <= csr_data_in; - csr_addr_out <= csr_addr_in; - end if; - end if; - end process pipeline_register; - -end architecture behaviour; Index: cache-playground/src/pp_constants.vhd =================================================================== --- cache-playground/src/pp_constants.vhd (revision 44) +++ cache-playground/src/pp_constants.vhd (nonexistent) @@ -1,15 +0,0 @@ --- The Potato Processor - A simple processor for FPGAs --- (c) Kristian Klomsten Skordal 2014 --- Report bugs and issues on - -library ieee; -use ieee.std_logic_1164.all; - -use work.pp_types.all; - -package pp_constants is - - --! No-operation instruction, addi x0, x0, 0. - constant RISCV_NOP : std_logic_vector(31 downto 0) := (31 downto 5 => '0') & b"10011"; --! ADDI x0, x0, 0. - -end package pp_constants; Index: cache-playground/src/pp_icache.vhd =================================================================== --- cache-playground/src/pp_icache.vhd (revision 44) +++ cache-playground/src/pp_icache.vhd (nonexistent) @@ -1,293 +0,0 @@ --- The Potato Processor - A simple processor for FPGAs --- (c) Kristian Klomsten Skordal 2014 - 2015 --- Report bugs and issues on - -library ieee; -use ieee.std_logic_1164.all; -use ieee.numeric_std.all; - -use work.pp_types.all; -use work.pp_utilities.all; - ---! @brief Simple read-only direct-mapped instruction cache. -entity pp_icache is - generic( - LINE_SIZE : natural := 4; --! Number of words per cache line - NUM_LINES : natural := 128 --! Number of lines in the cache - ); - port( - clk : in std_logic; - reset : in std_logic; - - -- Control interface: - cache_enable : in std_logic; - cache_flush : in std_logic; - cached_areas : in std_logic_vector(31 downto 0); - - -- Memory interface: - mem_address_in : in std_logic_vector(31 downto 0); - mem_data_in : in std_logic_vector(31 downto 0); - mem_data_out : out std_logic_vector(31 downto 0); - mem_data_size : in std_logic_vector( 1 downto 0); - mem_read_req : in std_logic; - mem_read_ack : out std_logic; - mem_write_req : in std_logic; - mem_write_ack : out std_logic; - - -- Wishbone interface: - wb_inputs : in wishbone_master_inputs; - wb_outputs : out wishbone_master_outputs - ); -end entity pp_icache; - -architecture behaviour of pp_icache is - - -- Counter types: - subtype line_counter_type is natural range 0 to NUM_LINES; - subtype word_counter_type is natural range 0 to LINE_SIZE; - - -- Cache line types: - subtype cache_line_type is std_logic_vector((LINE_SIZE * 32) - 1 downto 0); - type cache_line_word_array is array(0 to LINE_SIZE - 1) of std_logic_vector(31 downto 0); - type cache_line_array is array(0 to NUM_LINES - 1) of cache_line_type; - - -- Cache tag type: - subtype cache_tag_type is std_logic_vector(31 - log2(LINE_SIZE * 4) - log2(NUM_LINES) downto 0); - type cache_tag_array is array(0 to NUM_LINES - 1) of cache_tag_type; - - -- Cache memories: - signal cache_memory : cache_line_array; - signal tag_memory : cache_tag_array; - signal valid : std_logic_vector(NUM_LINES - 1 downto 0) := (others => '0'); - - attribute ram_style : string; - attribute ram_style of cache_memory: signal is "block"; - --attribute ram_style of tag_memory: signal is "block"; - - -- Cache controller signals: - type state_type is (IDLE, CACHE_READ_STALL, SINGLE_READ, SINGLE_WRITE, - LOAD_CACHELINE_START, LOAD_CACHELINE_WAIT_ACK, LOAD_CACHELINE_FINISH); - signal state : state_type := IDLE; - - -- Is the current input address in the cache? - signal input_address_cached : boolean; - - -- Input address components: - signal input_address_line : std_logic_vector(log2(NUM_LINES) - 1 downto 0); - signal input_address_word : std_logic_vector(log2(LINE_SIZE) - 1 downto 0); - signal input_address_tag : std_logic_vector(31 - log2(LINE_SIZE * 4) - log2(NUM_LINES) downto 0); - - -- Cacheline matching the current input address: - signal current_cache_line, cache_lookup : cache_line_type; - signal current_cache_line_words : cache_line_word_array; - signal current_tag : cache_tag_type; - - -- Base address to store a cacheline to: - signal cl_store_address : std_logic_vector(31 downto log2(LINE_SIZE * 4)); - -- Base address to load a cacheline from: - signal cl_load_address : std_logic_vector(31 downto log2(LINE_SIZE * 4)); - -- Cache line to load: - signal cl_current_line : line_counter_type; - -- Current word being loaded/stored: - signal cl_current_word : word_counter_type; - - -- Buffer for holding a cache line while loading: - signal load_buffer : cache_line_type; - signal load_buffer_tag : cache_tag_type; - - -- Causes a cache line to be stored in the cache memory: - signal store_cache_line : std_logic; - - -- Set when the current input address matches a cache line: - signal cache_hit : std_logic; - - -- For regular reads: - signal read_ack : std_logic; - signal read_data_out : std_logic_vector(31 downto 0); - - -- For regular writes: - signal write_ack : std_logic; - - -- Gets the amount to shift output data to the processor with for requests of size != 32 bits: - function get_data_shift(size : in std_logic_vector(1 downto 0); address : in std_logic_vector) - return natural is - begin - case size is - when b"01" => - case address(1 downto 0) is - when b"00" => - return 0; - when b"01" => - return 8; - when b"10" => - return 16; - when b"11" => - return 24; - when others => - return 0; - end case; - when b"10" => - if address(1) = '0' then - return 0; - else - return 16; - end if; - when others => - return 0; - end case; - end function get_data_shift; - -begin - - --assert is_pow2(LINE_SIZE) report "Cache line size must be a power of 2!" severity FAILURE; - --assert is_pow2(NUM_LINES) report "Number of cache lines must be a power of 2!" severity FAILURE; - - -- Check if the current input address should be/is in the cache: - input_address_cached <= cached_areas(to_integer(unsigned(mem_address_in(31 downto 27)))) = '1'; - - mem_data_out <= current_cache_line_words(to_integer(unsigned(input_address_word))) when - input_address_cached and cache_enable = '1' and cache_flush = '0' - else read_data_out; - mem_read_ack <= (cache_hit and mem_read_req) - when state = IDLE and input_address_cached and cache_enable = '1' and cache_flush = '0' - else read_ack; - write_ack <= wb_inputs.ack when state = SINGLE_WRITE else '0'; - mem_write_ack <= write_ack; - - input_address_line <= mem_address_in(log2(LINE_SIZE * 4) + log2(NUM_LINES) - 1 downto log2(LINE_SIZE * 4)); - input_address_tag <= mem_address_in(31 downto log2(LINE_SIZE * 4) + log2(NUM_LINES)); - - find_word: process(clk) - begin - if rising_edge(clk) then - input_address_word <= mem_address_in(log2(LINE_SIZE * 4) - 1 downto 2); - end if; - end process find_word; - - cacheline_lookup: process(clk) - begin - if rising_edge(clk) then - if store_cache_line = '1' then - cache_memory(cl_current_line) <= load_buffer; - end if; - - current_cache_line <= cache_memory(to_integer(unsigned(input_address_line))); - end if; - end process cacheline_lookup; - - decompose_cache_line: for i in 0 to LINE_SIZE - 1 generate - current_cache_line_words(i) <= current_cache_line(32 * i + 31 downto 32 * i); - end generate decompose_cache_line; - - tag_lookup: process(clk) - begin - if rising_edge(clk) then - if reset = '1' then - cache_hit <= '0'; - else - if store_cache_line = '1' then - tag_memory(cl_current_line) <= load_buffer_tag; - end if; - - current_tag <= tag_memory(to_integer(unsigned(input_address_line))); - cache_hit <= valid(to_integer(unsigned(input_address_line))) and to_std_logic(tag_memory(to_integer(unsigned(input_address_line))) = input_address_tag); - end if; - end if; - end process tag_lookup; - - controller: process(clk) - variable current_word : std_logic_vector(31 downto 0); - begin - if rising_edge(clk) then - if reset = '1' then - state <= IDLE; - wb_outputs.cyc <= '0'; - wb_outputs.stb <= '0'; - store_cache_line <= '0'; - read_ack <= '0'; - valid <= (others => '0'); - read_data_out <= (others => '0'); - else - case state is - when IDLE => - read_ack <= '0'; - if cache_flush = '1' then - valid <= (others => '0'); - elsif input_address_cached and cache_enable = '1' then - if (mem_read_req = '1' or mem_write_req = '1') and cache_hit = '0' then - wb_outputs.adr <= mem_address_in(31 downto log2(LINE_SIZE * 4)) & (log2(LINE_SIZE * 4) - 1 downto 0 => '0'); - wb_outputs.cyc <= '1'; - wb_outputs.we <= '0'; - wb_outputs.sel <= (others => '1'); - load_buffer_tag <= input_address_tag; - cl_load_address <= mem_address_in(31 downto log2(LINE_SIZE * 4)); - cl_store_address <= input_address_tag & input_address_line; - cl_current_line <= to_integer(unsigned(input_address_line)); - cl_current_word <= 0; - state <= LOAD_CACHELINE_START; - end if; - else - if mem_read_req = '1' and read_ack = '0' then -- Do an uncached read - wb_outputs.adr <= mem_address_in; - wb_outputs.sel <= wb_get_data_sel(mem_data_size, mem_address_in); - wb_outputs.cyc <= '1'; - wb_outputs.stb <= '1'; - wb_outputs.we <= '0'; - state <= SINGLE_READ; - elsif mem_write_req = '1' then -- Do an uncached write - wb_outputs.adr <= mem_address_in; - wb_outputs.dat <= std_logic_vector(shift_left(unsigned(mem_data_in), - get_data_shift(mem_data_size, mem_address_in))); - wb_outputs.sel <= wb_get_data_sel(mem_data_size, mem_address_in); - wb_outputs.cyc <= '1'; - wb_outputs.stb <= '1'; - wb_outputs.we <= '1'; - state <= SINGLE_WRITE; - end if; - end if; - when CACHE_READ_STALL => - state <= IDLE; - when SINGLE_READ => - if wb_inputs.ack = '1' then - read_data_out <= std_logic_vector(shift_right(unsigned(wb_inputs.dat), - get_data_shift(mem_data_size, mem_address_in))); - wb_outputs.cyc <= '0'; - wb_outputs.stb <= '0'; - read_ack <= '1'; - state <= IDLE; - end if; - when SINGLE_WRITE => - if wb_inputs.ack = '1' then - wb_outputs.cyc <= '0'; - wb_outputs.stb <= '0'; - wb_outputs.we <= '0'; - state <= IDLE; - end if; - when LOAD_CACHELINE_START => - wb_outputs.stb <= '1'; - wb_outputs.we <= '0'; - wb_outputs.adr <= cl_load_address & std_logic_vector(to_unsigned(cl_current_word, log2(LINE_SIZE))) & b"00"; - state <= LOAD_CACHELINE_WAIT_ACK; - when LOAD_CACHELINE_WAIT_ACK => - if wb_inputs.ack = '1' then - wb_outputs.stb <= '0'; - load_buffer(cl_current_word * 32 + 31 downto cl_current_word * 32) <= wb_inputs.dat; - if natural(cl_current_word) = LINE_SIZE - 1 then - wb_outputs.cyc <= '0'; - store_cache_line <= '1'; - state <= LOAD_CACHELINE_FINISH; - else - cl_current_word <= cl_current_word + 1; - state <= LOAD_CACHELINE_START; - end if; - end if; - when LOAD_CACHELINE_FINISH => - store_cache_line <= '0'; - valid(cl_current_line) <= '1'; - state <= CACHE_READ_STALL; - end case; - end if; - end if; - end process controller; - -end architecture behaviour; Index: cache-playground/src/pp_control_unit.vhd =================================================================== --- cache-playground/src/pp_control_unit.vhd (revision 44) +++ cache-playground/src/pp_control_unit.vhd (nonexistent) @@ -1,220 +0,0 @@ --- The Potato Processor - A simple processor for FPGAs --- (c) Kristian Klomsten Skordal 2014 - 2015 --- Report bugs and issues on - -library ieee; -use ieee.std_logic_1164.all; - -use work.pp_constants.all; -use work.pp_csr.all; -use work.pp_types.all; -use work.pp_utilities.all; - ---! @brief Unit decoding instructions and setting control signals apropriately. -entity pp_control_unit is - port( - -- Inputs, indices correspond to instruction word indices: - opcode : in std_logic_vector( 4 downto 0); - funct3 : in std_logic_vector( 2 downto 0); - funct7 : in std_logic_vector( 6 downto 0); - funct12 : in std_logic_vectoR(11 downto 0); - - -- Control signals: - rd_write : out std_logic; - branch : out branch_type; - - -- Exception signals: - decode_exception : out std_logic; - decode_exception_cause : out std_logic_vector(4 downto 0); - - -- Control register signals: - csr_write : out csr_write_mode; - csr_imm : out std_logic; --! Indicating an immediate variant of the csrr* instructions. - - -- Sources of operands to the ALU: - alu_x_src, alu_y_src : out alu_operand_source; - - -- ALU operation: - alu_op : out alu_operation; - - -- Memory transaction parameters: - mem_op : out memory_operation_type; - mem_size : out memory_operation_size - ); -end entity pp_control_unit; - -architecture behaviour of pp_control_unit is - signal exception : std_logic; - signal exception_cause : std_logic_vector(4 downto 0); - signal alu_op_temp : alu_operation; -begin - - csr_imm <= funct3(2); - alu_op <= alu_op_temp; - - decode_exception <= exception or to_std_logic(alu_op_temp = ALU_INVALID); - decode_exception_cause <= exception_cause when alu_op_temp /= ALU_INVALID - else CSR_CAUSE_INVALID_INSTR; - - alu_control: entity work.pp_alu_control_unit - port map( - opcode => opcode, - funct3 => funct3, - funct7 => funct7, - alu_x_src => alu_x_src, - alu_y_src => alu_y_src, - alu_op => alu_op_temp - ); - - decode_ctrl: process(opcode, funct3, funct12) - begin - case opcode is - when b"01101" => -- Load upper immediate - rd_write <= '1'; - exception <= '0'; - exception_cause <= CSR_CAUSE_NONE; - branch <= BRANCH_NONE; - when b"00101" => -- Add upper immediate to PC - rd_write <= '1'; - exception <= '0'; - exception_cause <= CSR_CAUSE_NONE; - branch <= BRANCH_NONE; - when b"11011" => -- Jump and link - rd_write <= '1'; - exception <= '0'; - exception_cause <= CSR_CAUSE_NONE; - branch <= BRANCH_JUMP; - when b"11001" => -- Jump and link register - rd_write <= '1'; - exception <= '0'; - exception_cause <= CSR_CAUSE_NONE; - branch <= BRANCH_JUMP_INDIRECT; - when b"11000" => -- Branch operations - rd_write <= '0'; - exception <= '0'; - exception_cause <= CSR_CAUSE_NONE; - branch <= BRANCH_CONDITIONAL; - when b"00000" => -- Load instructions - rd_write <= '1'; - exception <= '0'; - exception_cause <= CSR_CAUSE_NONE; - branch <= BRANCH_NONE; - when b"01000" => -- Store instructions - rd_write <= '0'; - exception <= '0'; - exception_cause <= CSR_CAUSE_NONE; - branch <= BRANCH_NONE; - when b"00100" => -- Register-immediate operations - rd_write <= '1'; - exception <= '0'; - exception_cause <= CSR_CAUSE_NONE; - branch <= BRANCH_NONE; - when b"01100" => -- Register-register operations - rd_write <= '1'; - exception <= '0'; - exception_cause <= CSR_CAUSE_NONE; - branch <= BRANCH_NONE; - when b"00011" => -- Fence instructions, ignored - rd_write <= '0'; - exception <= '0'; - exception_cause <= CSR_CAUSE_NONE; - branch <= BRANCH_NONE; - when b"11100" => -- System instructions - if funct3 = b"000" then - rd_write <= '0'; - - if funct12 = x"000" then - exception <= '1'; - exception_cause <= CSR_CAUSE_SYSCALL; - branch <= BRANCH_NONE; - elsif funct12 = x"001" then - exception <= '1'; - exception_cause <= CSR_CAUSE_BREAKPOINT; - branch <= BRANCH_NONE; - elsif funct12 = x"800" then - exception <= '0'; - exception_cause <= CSR_CAUSE_NONE; - branch <= BRANCH_SRET; - else - exception <= '1'; - exception_cause <= CSR_CAUSE_INVALID_INSTR; - branch <= BRANCH_NONE; - end if; - else - rd_write <= '1'; - exception <= '0'; - exception_cause <= CSR_CAUSE_NONE; - branch <= BRANCH_NONE; - end if; - when others => - rd_write <= '0'; - exception <= '1'; - exception_cause <= CSR_CAUSE_INVALID_INSTR; - branch <= BRANCH_NONE; - end case; - end process decode_ctrl; - - decode_csr: process(opcode, funct3) - begin - if opcode = b"11100" then - case funct3 is - when b"001" | b"101" => -- csrrw/i - csr_write <= CSR_WRITE_REPLACE; - when b"010" | b"110" => -- csrrs/i - csr_write <= CSR_WRITE_SET; - when b"011" | b"111" => -- csrrc/i - csr_write <= CSR_WRITE_CLEAR; - when others => - csr_write <= CSR_WRITE_NONE; - end case; - else - csr_write <= CSR_WRITE_NONE; - end if; - end process decode_csr; - - decode_mem: process(opcode, funct3) - begin - case opcode is - when b"00000" => -- Load instructions - case funct3 is - when b"000" => -- lw - mem_size <= MEMOP_SIZE_BYTE; - mem_op <= MEMOP_TYPE_LOAD; - when b"001" => -- lh - mem_size <= MEMOP_SIZE_HALFWORD; - mem_op <= MEMOP_TYPE_LOAD; - when b"010" | b"110" => -- lw - mem_size <= MEMOP_SIZE_WORD; - mem_op <= MEMOP_TYPE_LOAD; - when b"100" => -- lbu - mem_size <= MEMOP_SIZE_BYTE; - mem_op <= MEMOP_TYPE_LOAD_UNSIGNED; - when b"101" => -- lhu - mem_size <= MEMOP_SIZE_HALFWORD; - mem_op <= MEMOP_TYPE_LOAD_UNSIGNED; - when others => -- FIXME: Treat others as lw. - mem_size <= MEMOP_SIZE_WORD; - mem_op <= MEMOP_TYPE_INVALID; - end case; - when b"01000" => -- Store instructions - case funct3 is - when b"000" => - mem_op <= MEMOP_TYPE_STORE; - mem_size <= MEMOP_SIZE_BYTE; - when b"001" => - mem_op <= MEMOP_TYPE_STORE; - mem_size <= MEMOP_SIZE_HALFWORD; - when b"010" => - mem_op <= MEMOP_TYPE_STORE; - mem_size <= MEMOP_SIZE_WORD; - when others => - mem_op <= MEMOP_TYPE_INVALID; - mem_size <= MEMOP_SIZE_WORD; - end case; - when others => - mem_op <= MEMOP_TYPE_NONE; - mem_size <= MEMOP_SIZE_WORD; - end case; - end process decode_mem; - -end architecture behaviour; Index: cache-playground/src/pp_counter.vhd =================================================================== --- cache-playground/src/pp_counter.vhd (revision 44) +++ cache-playground/src/pp_counter.vhd (nonexistent) @@ -1,40 +0,0 @@ --- The Potato Processor - A simple processor for FPGAs --- (c) Kristian Klomsten Skordal 2014 -2015 --- Report bugs and issues on - -library ieee; -use ieee.std_logic_1164.all; -use ieee.numeric_std.all; - -entity pp_counter is - generic( - COUNTER_WIDTH : natural := 64; - COUNTER_STEP : natural := 1 - ); - port( - clk : in std_logic; - reset : in std_logic; - - count : out std_logic_vector(COUNTER_WIDTH - 1 downto 0); - increment : in std_logic - ); -end entity pp_counter; - -architecture behaviour of pp_counter is - signal current_count : std_logic_vector(COUNTER_WIDTH - 1 downto 0); -begin - - count <= current_count; - - counter: process(clk) - begin - if rising_edge(clk) then - if reset = '1' then - current_count <= (others => '0'); - elsif increment = '1' then - current_count <= std_logic_vector(unsigned(current_count) + COUNTER_STEP); - end if; - end if; - end process counter; - -end architecture behaviour; Index: cache-playground/src/pp_alu_control_unit.vhd =================================================================== --- cache-playground/src/pp_alu_control_unit.vhd (revision 44) +++ cache-playground/src/pp_alu_control_unit.vhd (nonexistent) @@ -1,141 +0,0 @@ --- The Potato Processor - A simple processor for FPGAs --- (c) Kristian Klomsten Skordal 2014 - 2015 --- Report bugs and issues on - -library ieee; -use ieee.std_logic_1164.all; - -use work.pp_types.all; -use work.pp_constants.all; - -entity pp_alu_control_unit is - port( - opcode : in std_logic_vector( 4 downto 0); - funct3 : in std_logic_vector( 2 downto 0); - funct7 : in std_logic_vector( 6 downto 0); - - -- Sources of ALU operands: - alu_x_src, alu_y_src : out alu_operand_source; - - -- ALU operation: - alu_op : out alu_operation - ); -end entity pp_alu_control_unit; - -architecture behaviour of pp_alu_control_unit is -begin - - decode_alu: process(opcode, funct3, funct7) - begin - case opcode is - when b"01101" => -- Load upper immediate - alu_x_src <= ALU_SRC_NULL; - alu_y_src <= ALU_SRC_IMM; - alu_op <= ALU_ADD; - when b"00101" => -- Add upper immediate to PC - alu_x_src <= ALU_SRC_PC; - alu_y_src <= ALU_SRC_IMM; - alu_op <= ALU_ADD; - when b"11011" => -- Jump and link - alu_x_src <= ALU_SRC_PC_NEXT; - alu_y_src <= ALU_SRC_NULL; - alu_op <= ALU_ADD; - when b"11001" => -- Jump and link register - alu_x_src <= ALU_SRC_PC_NEXT; - alu_y_src <= ALU_SRC_NULL; - alu_op <= ALU_ADD; - when b"11000" => -- Branch operations - -- The funct3 field decides which type of branch comparison is - -- done; this is decoded in the branch comparator module. - alu_x_src <= ALU_SRC_NULL; - alu_y_src <= ALU_SRC_NULL; - alu_op <= ALU_NOP; - when b"00000" => -- Load instruction - alu_x_src <= ALU_SRC_REG; - alu_y_src <= ALU_SRC_IMM; - alu_op <= ALU_ADD; - when b"01000" => -- Store instruction - alu_x_src <= ALU_SRC_REG; - alu_y_src <= ALU_SRC_IMM; - alu_op <= ALU_ADD; - when b"00100" => -- Register-immediate operations - alu_x_src <= ALU_SRC_REG; - - if funct3 = b"001" or funct3 = b"101" then - alu_y_src <= ALU_SRC_SHAMT; - else - alu_y_src <= ALU_SRC_IMM; - end if; - - case funct3 is - when b"000" => - alu_op <= ALU_ADD; - when b"001" => - alu_op <= ALU_SLL; - when b"010" => - alu_op <= ALU_SLT; - when b"011" => - alu_op <= ALU_SLTU; - when b"100" => - alu_op <= ALU_XOR; - when b"101" => - if funct7 = b"0000000" then - alu_op <= ALU_SRL; - else - alu_op <= ALU_SRA; - end if; - when b"110" => - alu_op <= ALU_OR; - when b"111" => - alu_op <= ALU_AND; - when others => - alu_op <= ALU_INVALID; - end case; - when b"01100" => -- Register-register operations - alu_x_src <= ALU_SRC_REG; - alu_y_src <= ALU_SRC_REG; - - case funct3 is - when b"000" => - if funct7 = b"0000000" then - alu_op <= ALU_ADD; - else - alu_op <= ALU_SUB; - end if; - when b"001" => - alu_op <= ALU_SLL; - when b"010" => - alu_op <= ALU_SLT; - when b"011" => - alu_op <= ALU_SLTU; - when b"100" => - alu_op <= ALU_XOR; - when b"101" => - if funct7 = b"0000000" then - alu_op <= ALU_SRL; - else - alu_op <= ALU_SRA; - end if; - when b"110" => - alu_op <= ALU_OR; - when b"111" => - alu_op <= ALU_AND; - when others => - alu_op <= ALU_INVALID; - end case; - when b"00011" => -- Fence instructions, ignored - alu_x_src <= ALU_SRC_REG; - alu_y_src <= ALU_SRC_REG; - alu_op <= ALU_NOP; - when b"11100" => -- System instructions - alu_x_src <= ALU_SRC_CSR; - alu_y_src <= ALU_SRC_NULL; - alu_op <= ALU_ADD; - when others => - alu_x_src <= ALU_SRC_REG; - alu_y_src <= ALU_SRC_REG; - alu_op <= ALU_INVALID; - end case; - end process decode_alu; - -end architecture behaviour; Index: cache-playground/src/pp_wb_arbiter.vhd =================================================================== --- cache-playground/src/pp_wb_arbiter.vhd (revision 44) +++ cache-playground/src/pp_wb_arbiter.vhd (nonexistent) @@ -1,100 +0,0 @@ --- The Potato Processor - A simple processor for FPGAs --- (c) Kristian Klomsten Skordal 2014 - 2015 --- Report bugs and issues on - -library ieee; -use ieee.std_logic_1164.all; - -use work.pp_types.all; - ---! @brief Simple priority-based wishbone arbiter. ---! This module is used as an arbiter between the instruction and data caches. -entity pp_wb_arbiter is - port( - clk : in std_logic; - reset : in std_logic; - - -- Wishbone input 1: - m1_inputs : out wishbone_master_inputs; - m1_outputs : in wishbone_master_outputs; - - -- Wishbone input 2: - m2_inputs : out wishbone_master_inputs; - m2_outputs : in wishbone_master_outputs; - - -- Wishbone interface: - wb_adr_out : out std_logic_vector(31 downto 0); - wb_sel_out : out std_logic_vector( 3 downto 0); - wb_cyc_out : out std_logic; - wb_stb_out : out std_logic; - wb_we_out : out std_logic; - wb_dat_out : out std_logic_vector(31 downto 0); - wb_dat_in : in std_logic_vector(31 downto 0); - wb_ack_in : in std_logic - ); -end entity pp_wb_arbiter; - -architecture behaviour of pp_wb_arbiter is - - type state_type is (IDLE, M1_BUSY, M2_BUSY); - signal state : state_type := IDLE; - -begin - - m1_inputs <= (ack => wb_ack_in, dat => wb_dat_in) when state = M1_BUSY else (ack => '0', dat => (others => '0')); - m2_inputs <= (ack => wb_ack_in, dat => wb_dat_in) when state = M2_BUSY else (ack => '0', dat => (others => '0')); - - output_mux: process(state, m1_outputs, m2_outputs) - begin - case state is - when IDLE => - wb_adr_out <= (others => '0'); - wb_sel_out <= (others => '0'); - wb_dat_out <= (others => '0'); - wb_cyc_out <= '0'; - wb_stb_out <= '0'; - wb_we_out <= '0'; - when M1_BUSY => - wb_adr_out <= m1_outputs.adr; - wb_sel_out <= m1_outputs.sel; - wb_dat_out <= m1_outputs.dat; - wb_cyc_out <= m1_outputs.cyc; - wb_stb_out <= m1_outputs.stb; - wb_we_out <= m1_outputs.we; - when M2_BUSY => - wb_adr_out <= m2_outputs.adr; - wb_sel_out <= m2_outputs.sel; - wb_dat_out <= m2_outputs.dat; - wb_cyc_out <= m2_outputs.cyc; - wb_stb_out <= m2_outputs.stb; - wb_we_out <= m2_outputs.we; - end case; - end process output_mux; - - controller: process(clk) - begin - if rising_edge(clk) then - if reset = '1' then - state <= IDLE; - else - case state is - when IDLE => - if m1_outputs.cyc = '1' then - state <= M1_BUSY; - elsif m2_outputs.cyc = '1' then - state <= M2_BUSY; - end if; - when M1_BUSY => - if m1_outputs.cyc = '0' then - state <= IDLE; - end if; - when M2_BUSY => - if m2_outputs.cyc = '0' then - state <= IDLE; - end if; - end case; - end if; - end if; - end process controller; - -end architecture behaviour; Index: cache-playground =================================================================== --- cache-playground (revision 44) +++ cache-playground (nonexistent)
cache-playground Property changes : Deleted: svn:mergeinfo ## -0,1 +0,0 ## Reverse-merged /potato/trunk:r26

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.