OpenCores
URL https://opencores.org/ocsvn/hf-risc/hf-risc/trunk

Subversion Repositories hf-risc

[/] [hf-risc/] [trunk/] [hf-riscv/] [core_rv32i/] [peripherals_busmux.vhd] - Diff between revs 17 and 18

Go to most recent revision | Show entire file | Details | Blame | View Log

Rev 17 Rev 18
Line 1... Line 1...
-- HF-RISCV v1.3
-- HF-RISCV v1.4
-- Sergio Johann Filho, 2015 - 2016
-- Sergio Johann Filho, 2015 - 2016
--
--
-- *This is a quick and dirty organization of a 3-stage pipelined RISC-V microprocessor. All registers / memory
-- *This is a quick and dirty organization of a 3-stage pipelined RISC-V microprocessor. All registers / memory
--  accesses are synchronized to the rising edge of clock. The same processor could be designed with only 2
--  accesses are synchronized to the rising edge of clock. The same processor could be designed with only 2
--  pipeline stages, but this would require memories to be either asynchronous (as presented on comp arq text
--  pipeline stages, but this would require memories to be either asynchronous (as presented on comp arq text
Line 16... Line 16...
-- *This design is a compromise between performance, area and complexity.
-- *This design is a compromise between performance, area and complexity.
-- *Only the RV32I base instruction set is implemented. FENCE and SYSTEM instructions are missing. SYSTEM
-- *Only the RV32I base instruction set is implemented. FENCE and SYSTEM instructions are missing. SYSTEM
--  instructions always trap the processor and can be handled in software.
--  instructions always trap the processor and can be handled in software.
-- *Memory is accessed in little endian mode.
-- *Memory is accessed in little endian mode.
-- *No co-processor is implemented and all peripherals are memory mapped.
-- *No co-processor is implemented and all peripherals are memory mapped.
-- *Loads and stores take 2/1 cycles with separated code/data memories and 3 cycles otherwise. This version is organized
-- *Loads and stores take 3 cycles. This version is organized as a Von Neumann machine, so there is only one
--  as a Von Neumann machine, so there is only one memory interface that is shared betweeen code and data accesses.
--  memory interface that is shared betweeen code and data accesses.
-- *Branches have a 1 cycle delay (not taken) or 3 cycle dalay (taken), including two branch delay slots.
-- *Branches have a 1 cycle delay (not taken) or 3 cycle dalay (taken), including two branch delay slots.
--  This is a side effect of the pipeline refill and memory access policy. All other instructions are single
--  This is a side effect of the pipeline refill and memory access policy. All other instructions are single
--  cycle. No branch predictor is implemented (default branch target is 'not taken').
--  cycle. No branch predictor is implemented (default branch target is 'not taken').
-- *Interrupts are handled using VECTOR, CAUSE, MASK, STATUS and EPC registers. The VECTOR register is used to hold
-- *Interrupts are handled using VECTOR, CAUSE, MASK, STATUS and EPC registers. The VECTOR register is used to hold
--  the address of the default (non-vectored) interrupt handler. The CAUSE register is read only and peripheral
--  the address of the default (non-vectored) interrupt handler. The CAUSE register is read only and peripheral
Line 97... Line 97...
                reset:          in std_logic;
                reset:          in std_logic;
 
 
                stall:          in std_logic;
                stall:          in std_logic;
 
 
                stall_cpu:      out std_logic;
                stall_cpu:      out std_logic;
                busy_cpu:       out std_logic;
 
                irq_vector_cpu: out std_logic_vector(31 downto 0);
                irq_vector_cpu: out std_logic_vector(31 downto 0);
                irq_cpu:        out std_logic;
                irq_cpu:        out std_logic;
                irq_ack_cpu:    in std_logic;
                irq_ack_cpu:    in std_logic;
                exception_cpu:  in std_logic;
                exception_cpu:  in std_logic;
                inst_addr_cpu:  in std_logic_vector(31 downto 0);
                address_cpu:    in std_logic_vector(31 downto 0);
                inst_in_cpu:    out std_logic_vector(31 downto 0);
 
                data_addr_cpu:  in std_logic_vector(31 downto 0);
 
                data_in_cpu:    out std_logic_vector(31 downto 0);
                data_in_cpu:    out std_logic_vector(31 downto 0);
                data_out_cpu:   in std_logic_vector(31 downto 0);
                data_out_cpu:   in std_logic_vector(31 downto 0);
                data_w_cpu:     in std_logic_vector(3 downto 0);
                data_w_cpu:     in std_logic_vector(3 downto 0);
                data_access_cpu:        in std_logic;
                data_access_cpu:        in std_logic;
 
 
Line 126... Line 123...
 
 
architecture arch of busmux is
architecture arch of busmux is
        signal write_enable: std_logic;
        signal write_enable: std_logic;
        signal irq_cause, irq_mask_reg, uart_divisor: std_logic_vector(15 downto 0);
        signal irq_cause, irq_mask_reg, uart_divisor: std_logic_vector(15 downto 0);
        signal irq_status_reg, extio_out_reg: std_logic_vector(7 downto 0);
        signal irq_status_reg, extio_out_reg: std_logic_vector(7 downto 0);
        signal irq_vector_reg, irq_epc_reg, compare_reg, counter_reg: std_logic_vector(31 downto 0);
        signal periph_data, irq_vector_reg, irq_epc_reg, compare_reg, counter_reg: std_logic_vector(31 downto 0);
        signal compare2_reg: std_logic_vector(23 downto 0);
        signal compare2_reg: std_logic_vector(23 downto 0);
        signal interrupt, irq, irq_counter, irq_counter_not, irq_counter2, irq_counter2_not, irq_compare, irq_compare2, compare_trig, compare2_trig: std_logic;
        signal interrupt, irq, irq_counter, irq_counter_not, irq_counter2, irq_counter2_not, irq_compare, irq_compare2, compare_trig, compare2_trig: std_logic;
        signal data_read_uart, data_write_uart: std_logic_vector(7 downto 0);
        signal data_read_uart, data_write_uart: std_logic_vector(7 downto 0);
        signal enable_uart, enable_uart_read, enable_uart_write, uart_write_busy, uart_data_avail: std_logic;
        signal enable_uart, enable_uart_read, enable_uart_write, uart_write_busy, uart_data_avail: std_logic;
 
 
        type pulse_state_type is (irq_idle, irq_int, irq_req, irq_ackn, irq_done);
        type pulse_state_type is (irq_idle, irq_int, irq_req, irq_ackn, irq_done);
        signal pulse_state: pulse_state_type;
        signal pulse_state: pulse_state_type;
        signal pulse_next_state: pulse_state_type;
        signal pulse_next_state: pulse_state_type;
 
 
        signal periph_access, periph_access_we, data_access_cpu_dly, data_access_cpu_dly2: std_logic;
        signal periph_access, periph_access_dly, periph_access_we: std_logic;
        signal data_we_mem_s: std_logic_vector(3 downto 0);
        signal data_we_mem_s: std_logic_vector(3 downto 0);
 
 
begin
begin
        -- address decoder, read from peripheral registers
        -- address decoder, read from peripheral registers
        process(data_addr_cpu, irq_vector_reg, irq_cause, irq_mask_reg, irq_status_reg, irq_epc_reg, compare_reg, compare2_reg, counter_reg, data_read_uart, uart_divisor, data_read_mem, extio_in, extio_out_reg)
        process(clock, reset, periph_access, address_cpu, irq_vector_reg, irq_cause, irq_mask_reg, irq_status_reg, irq_epc_reg, compare_reg, compare2_reg, counter_reg, data_read_uart, uart_divisor, data_read_mem, extio_in, extio_out_reg)
        begin
        begin
                case data_addr_cpu(31 downto 27) is
                if reset = '1' then
                        when "11110" =>                         -- Peripherals     (f000 0000 - f7ff ffff)
                        periph_data <= (others => '0');
                                case data_addr_cpu(7 downto 4) is
                elsif clock'event and clock = '1' then
 
                        if periph_access = '1' then
 
                                case address_cpu(7 downto 4) is
                                        when "0000" =>          -- IRQ_VECTOR           (RW)
                                        when "0000" =>          -- IRQ_VECTOR           (RW)
                                                data_in_cpu <= irq_vector_reg;
                                                periph_data <= irq_vector_reg;
                                        when "0001" =>          -- IRQ_CAUSE            (RO)
                                        when "0001" =>          -- IRQ_CAUSE            (RO)
                                                data_in_cpu <= irq_cause(7 downto 0) & irq_cause(15 downto 8) & x"0000";
                                                periph_data <= irq_cause(7 downto 0) & irq_cause(15 downto 8) & x"0000";
                                        when "0010" =>          -- IRQ_MASK             (RW)
                                        when "0010" =>          -- IRQ_MASK             (RW)
                                                data_in_cpu <= irq_mask_reg(7 downto 0) & irq_mask_reg(15 downto 8) & x"0000";
                                                periph_data <= irq_mask_reg(7 downto 0) & irq_mask_reg(15 downto 8) & x"0000";
                                        when "0011" =>          -- IRQ_STATUS           (RW)
                                        when "0011" =>          -- IRQ_STATUS           (RW)
                                                data_in_cpu <= irq_status_reg & x"000000";
                                                periph_data <= irq_status_reg & x"000000";
                                        when "0100" =>          -- IRQ_EPC              (RO)
                                        when "0100" =>          -- IRQ_EPC              (RO)
                                                data_in_cpu <= irq_epc_reg(7 downto 0) & irq_epc_reg(15 downto 8) & irq_epc_reg(23 downto 16) & irq_epc_reg(31 downto 24);
                                                periph_data <= irq_epc_reg(7 downto 0) & irq_epc_reg(15 downto 8) & irq_epc_reg(23 downto 16) & irq_epc_reg(31 downto 24);
                                        when "0101" =>          -- COUNTER              (RO)
                                        when "0101" =>          -- COUNTER              (RO)
                                                data_in_cpu <= counter_reg(7 downto 0) & counter_reg(15 downto 8) & counter_reg(23 downto 16) & counter_reg(31 downto 24);
                                                periph_data <= counter_reg(7 downto 0) & counter_reg(15 downto 8) & counter_reg(23 downto 16) & counter_reg(31 downto 24);
                                        when "0110" =>          -- IRQ_COMPARE          (RW)
                                        when "0110" =>          -- IRQ_COMPARE          (RW)
                                                data_in_cpu <= compare_reg(7 downto 0) & compare_reg(15 downto 8) & compare_reg(23 downto 16) & compare_reg(31 downto 24);
                                                periph_data <= compare_reg(7 downto 0) & compare_reg(15 downto 8) & compare_reg(23 downto 16) & compare_reg(31 downto 24);
                                        when "0111" =>          -- IRQ_COMPARE2         (RW)
                                        when "0111" =>          -- IRQ_COMPARE2         (RW)
                                                data_in_cpu <= compare_reg(15 downto 8) & compare_reg(23 downto 16) & compare_reg(31 downto 24) & x"00";
                                                periph_data <= compare_reg(15 downto 8) & compare_reg(23 downto 16) & compare_reg(31 downto 24) & x"00";
                                        when "1000" =>          -- EXTIO_IN             (RO)
                                        when "1000" =>          -- EXTIO_IN             (RO)
                                                data_in_cpu <= extio_in & x"000000";
                                                periph_data <= extio_in & x"000000";
                                        when "1001" =>          -- EXTIO_OUT            (RW)
                                        when "1001" =>          -- EXTIO_OUT            (RW)
                                                data_in_cpu <= extio_out_reg & x"000000";
                                                periph_data <= extio_out_reg & x"000000";
                                        when "1110" =>          -- UART                 (RW)
                                        when "1110" =>          -- UART                 (RW)
                                                data_in_cpu <= data_read_uart & x"000000";
                                                periph_data <= data_read_uart & x"000000";
                                        when "1111" =>          -- UART_DIVISOR         (RW)
                                        when "1111" =>          -- UART_DIVISOR         (RW)
                                                data_in_cpu <= uart_divisor(7 downto 0) & uart_divisor(15 downto 8) & x"0000";
                                                periph_data <= uart_divisor(7 downto 0) & uart_divisor(15 downto 8) & x"0000";
                                        when others =>
                                        when others =>
                                                data_in_cpu <= data_read_mem;
                                                periph_data <= data_read_mem;
                                end case;
 
                        when others =>                          -- ROM / RAM area, external peripherals (f800 0000 - ffff fffc)
 
                                data_in_cpu <= data_read_mem;
 
                end case;
                end case;
 
                        end if;
 
                end if;
        end process;
        end process;
 
 
        inst_in_cpu <= data_read_mem;
        data_in_cpu <= data_read_mem when periph_access_dly = '0' else periph_data;
 
 
        -- peripheral register logic, write to peripheral registers
        -- peripheral register logic, write to peripheral registers
        process(clock, reset, counter_reg, data_addr_cpu, data_out_cpu, periph_access, periph_access_we, irq)
        process(clock, reset, counter_reg, address_cpu, data_out_cpu, periph_access, periph_access_we, irq_ack_cpu)
        begin
        begin
                if reset = '1' then
                if reset = '1' then
                        irq_vector_reg <= x"00000000";
                        irq_vector_reg <= x"00000000";
                        irq_mask_reg <= x"0000";
                        irq_mask_reg <= x"0000";
                        irq_status_reg <= x"00";
                        irq_status_reg <= x"00";
Line 203... Line 201...
                        end if;
                        end if;
                        if compare2_reg = counter_reg(23 downto 0) then
                        if compare2_reg = counter_reg(23 downto 0) then
                                compare2_trig <= '1';
                                compare2_trig <= '1';
                        end if;
                        end if;
                        if periph_access = '1' and periph_access_we = '1' then
                        if periph_access = '1' and periph_access_we = '1' then
                                case data_addr_cpu(7 downto 4) is
                                case address_cpu(7 downto 4) is
                                        when "0000" =>  -- IRQ_VECTOR
                                        when "0000" =>  -- IRQ_VECTOR
                                                irq_vector_reg <= data_out_cpu(7 downto 0) & data_out_cpu(15 downto 8) & data_out_cpu(23 downto 16) & data_out_cpu(31 downto 24);
                                                irq_vector_reg <= data_out_cpu(7 downto 0) & data_out_cpu(15 downto 8) & data_out_cpu(23 downto 16) & data_out_cpu(31 downto 24);
                                        when "0010" =>  -- IRQ_MASK
                                        when "0010" =>  -- IRQ_MASK
                                                irq_mask_reg <= data_out_cpu(23 downto 16) & data_out_cpu(31 downto 24);
                                                irq_mask_reg <= data_out_cpu(23 downto 16) & data_out_cpu(31 downto 24);
                                        when "0011" =>  -- IRQ_STATUS
                                        when "0011" =>  -- IRQ_STATUS
Line 230... Line 228...
                        end if;
                        end if;
                end if;
                end if;
        end process;
        end process;
 
 
        -- EPC register register load on interrupts
        -- EPC register register load on interrupts
        process(clock, reset, inst_addr_cpu, irq, irq_ack_cpu)
        process(clock, reset, address_cpu, irq, irq_ack_cpu)
        begin
        begin
                if reset = '1' then
                if reset = '1' then
                        irq_epc_reg <= x"00000000";
                        irq_epc_reg <= x"00000000";
                elsif clock'event and clock = '1' then
                elsif clock'event and clock = '1' then
                        if ((irq = '1' and irq_ack_cpu = '0') or exception_cpu = '1') then
                        if ((irq = '1' and irq_ack_cpu = '0') or exception_cpu = '1') then
                                irq_epc_reg <= inst_addr_cpu;
                                irq_epc_reg <= address_cpu;
                        end if;
                        end if;
                end if;
                end if;
        end process;
        end process;
 
 
        -- interrupt state machine
        -- interrupt state machine
Line 278... Line 276...
                        end if;
                        end if;
                end if;
                end if;
        end process;
        end process;
 
 
        -- data / peripheral access delay
        -- data / peripheral access delay
        process(clock, reset, irq_ack_cpu, data_access_cpu, stall)
        process(clock, reset, irq_ack_cpu, periph_access, stall)
        begin
        begin
                if reset = '1' then
                if reset = '1' then
                        data_access_cpu_dly <= '0';
                        periph_access_dly <= '0';
                        data_access_cpu_dly2 <= '0';
 
                elsif clock'event and clock = '1' then
                elsif clock'event and clock = '1' then
                        if stall = '0' then
                        if stall = '0' then
                                data_access_cpu_dly2 <= data_access_cpu_dly;
                                periph_access_dly <= periph_access;
                                if data_access_cpu = '1' and data_access_cpu_dly = '0' and data_access_cpu_dly2 = '0' then
 
                                        data_access_cpu_dly <= '1';
 
                                else
 
                                        data_access_cpu_dly <= '0';
 
                                end if;
 
                        end if;
                        end if;
                end if;
                end if;
        end process;
        end process;
 
 
        periph_access <= '1' when data_addr_cpu(31 downto 27) = "11110" and data_access_cpu = '1' else '0';
        periph_access <= '1' when address_cpu(31 downto 27) = "11110" and data_access_cpu = '1' else '0';
        periph_access_we <= '1' when periph_access <= '1' and data_w_cpu /= "0000" else '0';
        periph_access_we <= '1' when periph_access <= '1' and data_w_cpu /= "0000" else '0';
 
 
        -- memory address / write enable muxes and cpu stall logic
        -- memory address / write enable muxes and cpu stall logic
        addr_mem <= data_addr_cpu when data_access_cpu_dly = '0' and data_access_cpu = '1' and periph_access = '0' else inst_addr_cpu;
        addr_mem <= address_cpu;
        data_write_mem <= data_out_cpu;
        data_write_mem <= data_out_cpu;
        data_we_mem_s <= data_w_cpu when data_access_cpu_dly = '0' and data_access_cpu = '1' and periph_access = '0' else "0000";
        data_we_mem_s <= data_w_cpu when data_access_cpu = '1' and periph_access = '0' else "0000";
        data_we_mem <= data_we_mem_s;
        data_we_mem <= data_we_mem_s;
 
 
        busy_cpu <= (data_access_cpu and not data_access_cpu_dly);                                      -- load/store: 1 wait cycle
 
        stall_cpu <= stall;
        stall_cpu <= stall;
 
 
        -- interrupts and peripherals
        -- interrupts and peripherals
        interrupt <= '0' when (irq_cause and irq_mask_reg) = x"0000" else '1';
        interrupt <= '0' when (irq_cause and irq_mask_reg) = x"0000" else '1';
        irq_cause <= extio_in & not uart_write_busy & uart_data_avail & irq_compare2 & irq_compare & irq_counter2_not & irq_counter2 & irq_counter_not & irq_counter;
        irq_cause <= extio_in & not uart_write_busy & uart_data_avail & irq_compare2 & irq_compare & irq_counter2_not & irq_counter2 & irq_counter_not & irq_counter;
Line 326... Line 317...
        write_enable <= '1' when data_we_mem_s /= "0000" else '0';
        write_enable <= '1' when data_we_mem_s /= "0000" else '0';
        data_write_uart <= data_out_cpu(31 downto 24);
        data_write_uart <= data_out_cpu(31 downto 24);
 
 
        uart:
        uart:
        if uart_support = "yes" generate
        if uart_support = "yes" generate
                enable_uart <= '1' when periph_access = '1' and data_addr_cpu(7 downto 4) = "1110" else '0';
                enable_uart <= '1' when periph_access = '1' and address_cpu(7 downto 4) = "1110" else '0';
                enable_uart_write <= enable_uart and periph_access_we;
                enable_uart_write <= enable_uart and periph_access_we;
                enable_uart_read <= enable_uart and not periph_access_we;
                enable_uart_read <= enable_uart and not periph_access_we;
 
 
                -- a simple UART
                -- a simple UART
                serial: entity work.uart
                serial: entity work.uart

powered by: WebSVN 2.1.0

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