Skip to content
Snippets Groups Projects
Commit ca0ce6ce authored by Tristan Gingold's avatar Tristan Gingold
Browse files

wb_vic: add fixed polarity; partial rewrite.

parent 68e1c650
Branches
No related merge requests found
files = ["vic_prio_enc.vhd",
"wb_slave_vic.vhd",
files = ["wb_vic_regs.vhd",
"wb_vic.vhd",
"xwb_vic.vhd"]
--------------------------------------------------------------------------------
-- CERN BE-CO-HT
-- General Cores Library
-- https://www.ohwr.org/projects/general-cores
--------------------------------------------------------------------------------
--
-- unit name: vic_prio_enc
--
-- description: Priority encoder for VIC
--
--------------------------------------------------------------------------------
-- Copyright CERN 2010-2018
--------------------------------------------------------------------------------
-- Copyright and related rights are licensed under the Solderpad Hardware
-- License, Version 2.0 (the "License"); you may not use this file except
-- in compliance with the License. You may obtain a copy of the License at
-- http://solderpad.org/licenses/SHL-2.0.
-- Unless required by applicable law or agreed to in writing, software,
-- hardware and materials distributed under this License is distributed on an
-- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
-- or implied. See the License for the specific language governing permissions
-- and limitations under the License.
--------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
entity vic_prio_enc is
port (
in_i : in std_logic_vector(31 downto 0);
out_o : out std_logic_vector(4 downto 0)
);
end vic_prio_enc;
architecture syn of vic_prio_enc is
begin -- syn
prencode : process (in_i)
begin -- process prencode
if in_i(0) = '1' then
out_o <= "00000";
elsif in_i(1) = '1' then
out_o <= "00001";
elsif in_i(2) = '1' then
out_o <= "00010";
elsif in_i(3) = '1' then
out_o <= "00011";
elsif in_i(4) = '1' then
out_o <= "00100";
elsif in_i(5) = '1' then
out_o <= "00101";
elsif in_i(6) = '1' then
out_o <= "00110";
elsif in_i(7) = '1' then
out_o <= "00111";
elsif in_i(8+0) = '1' then
out_o <= "01000";
elsif in_i(8+1) = '1' then
out_o <= "01001";
elsif in_i(8+2) = '1' then
out_o <= "01010";
elsif in_i(8+3) = '1' then
out_o <= "01011";
elsif in_i(8+4) = '1' then
out_o <= "01100";
elsif in_i(8+5) = '1' then
out_o <= "01101";
elsif in_i(8+6) = '1' then
out_o <= "01110";
elsif in_i(8+7) = '1' then
out_o <= "01111";
elsif in_i(16+0) = '1' then
out_o <= "10000";
elsif in_i(16+1) = '1' then
out_o <= "10001";
elsif in_i(16+2) = '1' then
out_o <= "10010";
elsif in_i(16+3) = '1' then
out_o <= "10011";
elsif in_i(16+4) = '1' then
out_o <= "10100";
elsif in_i(16+5) = '1' then
out_o <= "10101";
elsif in_i(16+6) = '1' then
out_o <= "10110";
elsif in_i(16+7) = '1' then
out_o <= "10111";
elsif in_i(24+0) = '1' then
out_o <= "11000";
elsif in_i(24+1) = '1' then
out_o <= "11001";
elsif in_i(24+2) = '1' then
out_o <= "11010";
elsif in_i(24+3) = '1' then
out_o <= "11011";
elsif in_i(24+4) = '1' then
out_o <= "11100";
elsif in_i(24+5) = '1' then
out_o <= "11101";
elsif in_i(24+6) = '1' then
out_o <= "11110";
elsif in_i(24+7) = '1' then
out_o <= "11111";
else
out_o <= "XXXXX";
end if;
end process prencode;
end syn;
--------------------------------------------------------------------------------
-- CERN BE-CO-HT
-- General Cores Library
-- https://www.ohwr.org/projects/general-cores
--------------------------------------------------------------------------------
--
-- unit name: wb_slave_vic
--
-- description: Wishbone slave core for Vectored Interrupt Controller (VIC)
--
-- Originally auto-generated by wbgen2 from wb_slave_vic.wb
--
-- Warning!
-- This file has been hand-modified (for vector table pre-initialization).
-- Regenerating it using wbgen2 will break the design.
--
--------------------------------------------------------------------------------
-- Copyright CERN 2013-2018
--------------------------------------------------------------------------------
-- Copyright and related rights are licensed under the Solderpad Hardware
-- License, Version 2.0 (the "License"); you may not use this file except
-- in compliance with the License. You may obtain a copy of the License at
-- http://solderpad.org/licenses/SHL-2.0.
-- Unless required by applicable law or agreed to in writing, software,
-- hardware and materials distributed under this License is distributed on an
-- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
-- or implied. See the License for the specific language governing permissions
-- and limitations under the License.
--------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.wbgen2_pkg.all;
entity wb_slave_vic is
port (
rst_n_i : in std_logic;
clk_sys_i : in std_logic;
wb_adr_i : in std_logic_vector(5 downto 0);
wb_dat_i : in std_logic_vector(31 downto 0);
wb_dat_o : out std_logic_vector(31 downto 0);
wb_cyc_i : in std_logic;
wb_sel_i : in std_logic_vector(3 downto 0);
wb_stb_i : in std_logic;
wb_we_i : in std_logic;
wb_ack_o : out std_logic;
wb_stall_o : out std_logic;
-- Port for BIT field: 'VIC Enable' in reg: 'VIC Control Register'
vic_ctl_enable_o : out std_logic;
-- Port for BIT field: 'VIC output polarity' in reg: 'VIC Control Register'
vic_ctl_pol_o : out std_logic;
-- Port for BIT field: 'Emulate Edge sensitive output' in reg: 'VIC Control Register'
vic_ctl_emu_edge_o : out std_logic;
-- Port for std_logic_vector field: 'Emulated Edge pulse timer' in reg: 'VIC Control Register'
vic_ctl_emu_len_o : out std_logic_vector(15 downto 0);
-- Port for std_logic_vector field: 'Raw interrupt status' in reg: 'Raw Interrupt Status Register'
vic_risr_i : in std_logic_vector(31 downto 0);
-- Ports for PASS_THROUGH field: 'Enable IRQ' in reg: 'Interrupt Enable Register'
vic_ier_o : out std_logic_vector(31 downto 0);
vic_ier_wr_o : out std_logic;
-- Ports for PASS_THROUGH field: 'Disable IRQ' in reg: 'Interrupt Disable Register'
vic_idr_o : out std_logic_vector(31 downto 0);
vic_idr_wr_o : out std_logic;
-- Port for std_logic_vector field: 'IRQ disabled/enabled' in reg: 'Interrupt Mask Register'
vic_imr_i : in std_logic_vector(31 downto 0);
-- Port for std_logic_vector field: 'Vector Address' in reg: 'Vector Address Register'
vic_var_i : in std_logic_vector(31 downto 0);
-- Ports for PASS_THROUGH field: 'SWI interrupt mask' in reg: 'Software Interrupt Register'
vic_swir_o : out std_logic_vector(31 downto 0);
vic_swir_wr_o : out std_logic;
-- Ports for PASS_THROUGH field: 'End of Interrupt' in reg: 'End Of Interrupt Acknowledge Register'
vic_eoir_o : out std_logic_vector(31 downto 0);
vic_eoir_wr_o : out std_logic;
-- Ports for RAM: Interrupt Vector Table
-- Tom's handmade modifications here: the RAM is instantiated outside the WR slave
-- So that it can be pre-initialized with user-defined vector addresses.
vic_ivt_ram_addr_o : out std_logic_vector(4 downto 0);
vic_ivt_ram_data_i : in std_logic_vector(31 downto 0);
vic_ivt_ram_data_o : out std_logic_vector(31 downto 0);
vic_ivt_ram_wr_o : out std_logic
);
end wb_slave_vic;
architecture syn of wb_slave_vic is
signal vic_ctl_enable_int : std_logic ;
signal vic_ctl_pol_int : std_logic ;
signal vic_ctl_emu_edge_int : std_logic ;
signal vic_ctl_emu_len_int : std_logic_vector(15 downto 0);
signal vic_ivt_ram_rddata_int : std_logic_vector(31 downto 0);
signal vic_ivt_ram_rd_int : std_logic ;
signal vic_ivt_ram_wr_int : std_logic ;
signal ack_sreg : std_logic_vector(9 downto 0);
signal rddata_reg : std_logic_vector(31 downto 0);
signal wrdata_reg : std_logic_vector(31 downto 0);
signal bwsel_reg : std_logic_vector(3 downto 0);
signal rwaddr_reg : std_logic_vector(5 downto 0);
signal ack_in_progress : std_logic ;
signal wr_int : std_logic ;
signal rd_int : std_logic ;
signal allones : std_logic_vector(31 downto 0);
signal allzeros : std_logic_vector(31 downto 0);
begin
-- Some internal signals assignments. For (foreseen) compatibility with other bus standards.
wrdata_reg <= wb_dat_i;
bwsel_reg <= wb_sel_i;
rd_int <= wb_cyc_i and (wb_stb_i and (not wb_we_i));
wr_int <= wb_cyc_i and (wb_stb_i and wb_we_i);
allones <= (others => '1');
allzeros <= (others => '0');
--
-- Main register bank access process.
process (clk_sys_i, rst_n_i)
begin
if (rst_n_i = '0') then
ack_sreg <= "0000000000";
ack_in_progress <= '0';
rddata_reg <= "00000000000000000000000000000000";
vic_ctl_enable_int <= '0';
vic_ctl_pol_int <= '0';
vic_ctl_emu_edge_int <= '0';
vic_ctl_emu_len_int <= "0000000000000000";
vic_ier_wr_o <= '0';
vic_idr_wr_o <= '0';
vic_swir_wr_o <= '0';
vic_eoir_wr_o <= '0';
elsif rising_edge(clk_sys_i) then
-- advance the ACK generator shift register
ack_sreg(8 downto 0) <= ack_sreg(9 downto 1);
ack_sreg(9) <= '0';
if (ack_in_progress = '1') then
if (ack_sreg(0) = '1') then
vic_ier_wr_o <= '0';
vic_idr_wr_o <= '0';
vic_swir_wr_o <= '0';
vic_eoir_wr_o <= '0';
ack_in_progress <= '0';
else
vic_ier_wr_o <= '0';
vic_idr_wr_o <= '0';
vic_swir_wr_o <= '0';
vic_eoir_wr_o <= '0';
end if;
else
if ((wb_cyc_i = '1') and (wb_stb_i = '1')) then
case rwaddr_reg(5) is
when '0' =>
case rwaddr_reg(2 downto 0) is
when "000" =>
if (wb_we_i = '1') then
vic_ctl_enable_int <= wrdata_reg(0);
vic_ctl_pol_int <= wrdata_reg(1);
vic_ctl_emu_edge_int <= wrdata_reg(2);
vic_ctl_emu_len_int <= wrdata_reg(18 downto 3);
end if;
rddata_reg(0) <= vic_ctl_enable_int;
rddata_reg(1) <= vic_ctl_pol_int;
rddata_reg(2) <= vic_ctl_emu_edge_int;
rddata_reg(18 downto 3) <= vic_ctl_emu_len_int;
rddata_reg(19) <= 'X';
rddata_reg(20) <= 'X';
rddata_reg(21) <= 'X';
rddata_reg(22) <= 'X';
rddata_reg(23) <= 'X';
rddata_reg(24) <= 'X';
rddata_reg(25) <= 'X';
rddata_reg(26) <= 'X';
rddata_reg(27) <= 'X';
rddata_reg(28) <= 'X';
rddata_reg(29) <= 'X';
rddata_reg(30) <= 'X';
rddata_reg(31) <= 'X';
ack_sreg(0) <= '1';
ack_in_progress <= '1';
when "001" =>
if (wb_we_i = '1') then
end if;
rddata_reg(31 downto 0) <= vic_risr_i;
ack_sreg(0) <= '1';
ack_in_progress <= '1';
when "010" =>
if (wb_we_i = '1') then
vic_ier_wr_o <= '1';
end if;
rddata_reg(0) <= 'X';
rddata_reg(1) <= 'X';
rddata_reg(2) <= 'X';
rddata_reg(3) <= 'X';
rddata_reg(4) <= 'X';
rddata_reg(5) <= 'X';
rddata_reg(6) <= 'X';
rddata_reg(7) <= 'X';
rddata_reg(8) <= 'X';
rddata_reg(9) <= 'X';
rddata_reg(10) <= 'X';
rddata_reg(11) <= 'X';
rddata_reg(12) <= 'X';
rddata_reg(13) <= 'X';
rddata_reg(14) <= 'X';
rddata_reg(15) <= 'X';
rddata_reg(16) <= 'X';
rddata_reg(17) <= 'X';
rddata_reg(18) <= 'X';
rddata_reg(19) <= 'X';
rddata_reg(20) <= 'X';
rddata_reg(21) <= 'X';
rddata_reg(22) <= 'X';
rddata_reg(23) <= 'X';
rddata_reg(24) <= 'X';
rddata_reg(25) <= 'X';
rddata_reg(26) <= 'X';
rddata_reg(27) <= 'X';
rddata_reg(28) <= 'X';
rddata_reg(29) <= 'X';
rddata_reg(30) <= 'X';
rddata_reg(31) <= 'X';
ack_sreg(0) <= '1';
ack_in_progress <= '1';
when "011" =>
if (wb_we_i = '1') then
vic_idr_wr_o <= '1';
end if;
rddata_reg(0) <= 'X';
rddata_reg(1) <= 'X';
rddata_reg(2) <= 'X';
rddata_reg(3) <= 'X';
rddata_reg(4) <= 'X';
rddata_reg(5) <= 'X';
rddata_reg(6) <= 'X';
rddata_reg(7) <= 'X';
rddata_reg(8) <= 'X';
rddata_reg(9) <= 'X';
rddata_reg(10) <= 'X';
rddata_reg(11) <= 'X';
rddata_reg(12) <= 'X';
rddata_reg(13) <= 'X';
rddata_reg(14) <= 'X';
rddata_reg(15) <= 'X';
rddata_reg(16) <= 'X';
rddata_reg(17) <= 'X';
rddata_reg(18) <= 'X';
rddata_reg(19) <= 'X';
rddata_reg(20) <= 'X';
rddata_reg(21) <= 'X';
rddata_reg(22) <= 'X';
rddata_reg(23) <= 'X';
rddata_reg(24) <= 'X';
rddata_reg(25) <= 'X';
rddata_reg(26) <= 'X';
rddata_reg(27) <= 'X';
rddata_reg(28) <= 'X';
rddata_reg(29) <= 'X';
rddata_reg(30) <= 'X';
rddata_reg(31) <= 'X';
ack_sreg(0) <= '1';
ack_in_progress <= '1';
when "100" =>
if (wb_we_i = '1') then
end if;
rddata_reg(31 downto 0) <= vic_imr_i;
ack_sreg(0) <= '1';
ack_in_progress <= '1';
when "101" =>
if (wb_we_i = '1') then
end if;
rddata_reg(31 downto 0) <= vic_var_i;
ack_sreg(0) <= '1';
ack_in_progress <= '1';
when "110" =>
if (wb_we_i = '1') then
vic_swir_wr_o <= '1';
end if;
rddata_reg(0) <= 'X';
rddata_reg(1) <= 'X';
rddata_reg(2) <= 'X';
rddata_reg(3) <= 'X';
rddata_reg(4) <= 'X';
rddata_reg(5) <= 'X';
rddata_reg(6) <= 'X';
rddata_reg(7) <= 'X';
rddata_reg(8) <= 'X';
rddata_reg(9) <= 'X';
rddata_reg(10) <= 'X';
rddata_reg(11) <= 'X';
rddata_reg(12) <= 'X';
rddata_reg(13) <= 'X';
rddata_reg(14) <= 'X';
rddata_reg(15) <= 'X';
rddata_reg(16) <= 'X';
rddata_reg(17) <= 'X';
rddata_reg(18) <= 'X';
rddata_reg(19) <= 'X';
rddata_reg(20) <= 'X';
rddata_reg(21) <= 'X';
rddata_reg(22) <= 'X';
rddata_reg(23) <= 'X';
rddata_reg(24) <= 'X';
rddata_reg(25) <= 'X';
rddata_reg(26) <= 'X';
rddata_reg(27) <= 'X';
rddata_reg(28) <= 'X';
rddata_reg(29) <= 'X';
rddata_reg(30) <= 'X';
rddata_reg(31) <= 'X';
ack_sreg(0) <= '1';
ack_in_progress <= '1';
when "111" =>
if (wb_we_i = '1') then
vic_eoir_wr_o <= '1';
end if;
rddata_reg(0) <= 'X';
rddata_reg(1) <= 'X';
rddata_reg(2) <= 'X';
rddata_reg(3) <= 'X';
rddata_reg(4) <= 'X';
rddata_reg(5) <= 'X';
rddata_reg(6) <= 'X';
rddata_reg(7) <= 'X';
rddata_reg(8) <= 'X';
rddata_reg(9) <= 'X';
rddata_reg(10) <= 'X';
rddata_reg(11) <= 'X';
rddata_reg(12) <= 'X';
rddata_reg(13) <= 'X';
rddata_reg(14) <= 'X';
rddata_reg(15) <= 'X';
rddata_reg(16) <= 'X';
rddata_reg(17) <= 'X';
rddata_reg(18) <= 'X';
rddata_reg(19) <= 'X';
rddata_reg(20) <= 'X';
rddata_reg(21) <= 'X';
rddata_reg(22) <= 'X';
rddata_reg(23) <= 'X';
rddata_reg(24) <= 'X';
rddata_reg(25) <= 'X';
rddata_reg(26) <= 'X';
rddata_reg(27) <= 'X';
rddata_reg(28) <= 'X';
rddata_reg(29) <= 'X';
rddata_reg(30) <= 'X';
rddata_reg(31) <= 'X';
ack_sreg(0) <= '1';
ack_in_progress <= '1';
when others =>
-- prevent the slave from hanging the bus on invalid address
ack_in_progress <= '1';
ack_sreg(0) <= '1';
end case;
when '1' =>
if (rd_int = '1') then
ack_sreg(0) <= '1';
else
ack_sreg(0) <= '1';
end if;
ack_in_progress <= '1';
when others =>
-- prevent the slave from hanging the bus on invalid address
ack_in_progress <= '1';
ack_sreg(0) <= '1';
end case;
end if;
end if;
end if;
end process;
-- Data output multiplexer process
process (rddata_reg, rwaddr_reg, vic_ivt_ram_rddata_int, wb_adr_i )
begin
case rwaddr_reg(5) is
when '1' =>
wb_dat_o(31 downto 0) <= vic_ivt_ram_rddata_int;
when others =>
wb_dat_o <= rddata_reg;
end case;
end process;
-- Read & write lines decoder for RAMs
process (wb_adr_i, rd_int, wr_int )
begin
if (wb_adr_i(5) = '1') then
vic_ivt_ram_rd_int <= rd_int;
vic_ivt_ram_wr_int <= wr_int;
else
vic_ivt_ram_wr_int <= '0';
vic_ivt_ram_rd_int <= '0';
end if;
end process;
-- VIC Enable
vic_ctl_enable_o <= vic_ctl_enable_int;
-- VIC output polarity
vic_ctl_pol_o <= vic_ctl_pol_int;
-- Emulate Edge sensitive output
vic_ctl_emu_edge_o <= vic_ctl_emu_edge_int;
-- Emulated Edge pulse timer
vic_ctl_emu_len_o <= vic_ctl_emu_len_int;
-- Raw interrupt status
-- Enable IRQ
-- pass-through field: Enable IRQ in register: Interrupt Enable Register
vic_ier_o <= wrdata_reg(31 downto 0);
-- Disable IRQ
-- pass-through field: Disable IRQ in register: Interrupt Disable Register
vic_idr_o <= wrdata_reg(31 downto 0);
-- IRQ disabled/enabled
-- Vector Address
-- SWI interrupt mask
-- pass-through field: SWI interrupt mask in register: Software Interrupt Register
vic_swir_o <= wrdata_reg(31 downto 0);
-- End of Interrupt
-- pass-through field: End of Interrupt in register: End Of Interrupt Acknowledge Register
vic_eoir_o <= wrdata_reg(31 downto 0);
-- extra code for reg/fifo/mem: Interrupt Vector Table
-- RAM block instantiation for memory: Interrupt Vector Table
vic_ivt_ram_wr_o <= vic_ivt_ram_wr_int;
vic_ivt_ram_addr_o <= rwaddr_reg(4 downto 0);
vic_ivt_ram_data_o <= wrdata_reg;
vic_ivt_ram_rddata_int <= vic_ivt_ram_data_i;
rwaddr_reg <= wb_adr_i;
wb_stall_o <= (not ack_sreg(0)) and (wb_stb_i and wb_cyc_i);
-- ACK signal generation. Just pass the LSB of ACK counter.
wb_ack_o <= ack_sreg(0);
end syn;
--------------------------------------------------------------------------------
-- CERN BE-CO-HT
-- General Cores Library
-- https://www.ohwr.org/projects/general-cores
--------------------------------------------------------------------------------
--
-- unit name: wb_slave_vic
--
-- description: Wishbone slave core for Vectored Interrupt Controller (VIC)
-- block layout (wbgen2)
--
--------------------------------------------------------------------------------
-- Copyright CERN 2013-2018
--------------------------------------------------------------------------------
-- Copyright and related rights are licensed under the Solderpad Hardware
-- License, Version 2.0 (the "License"); you may not use this file except
-- in compliance with the License. You may obtain a copy of the License at
-- http://solderpad.org/licenses/SHL-2.0.
-- Unless required by applicable law or agreed to in writing, software,
-- hardware and materials distributed under this License is distributed on an
-- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
-- or implied. See the License for the specific language governing permissions
-- and limitations under the License.
--------------------------------------------------------------------------------
-- -*- Mode: LUA; tab-width: 2 -*-
peripheral {
name = "Vectored Interrupt Controller (VIC)";
description = "Module implementing a 2 to 32-input prioritized interrupt controller with internal interrupt vector storage support.";
prefix = "VIC";
hdl_entity = "wb_slave_vic";
reg {
name = "VIC Control Register";
prefix = "CTL";
field {
name = "VIC Enable";
description = "- 1: enables VIC operation\n- 0: disables VIC operation";
prefix = "ENABLE";
type = BIT;
access_dev = READ_ONLY;
access_bus = READ_WRITE;
};
field {
name = "VIC output polarity";
description = "- 1: IRQ output is active high\n- 0: IRQ output is active low";
prefix = "POL";
type = BIT;
access_dev = READ_ONLY;
access_bus = READ_WRITE;
};
field {
name = "Emulate Edge sensitive output";
description = "- 1: Forces a low pulse of <code>EMU_LEN</code> clock cycles at each write to <code>EOIR</code>. Useful for edge-only IRQ controllers such as Gennum.\n- 0: Normal IRQ master line behavior";
prefix = "EMU_EDGE";
type = BIT;
access_dev = READ_ONLY;
access_bus = READ_WRITE;
};
field {
name = "Emulated Edge pulse timer";
description = "Length of the delay (in <code>clk_sys_i</code> cycles) between write to <code>EOIR</code> and re-assertion of <code>irq_master_o</code>.";
prefix = "EMU_LEN";
type = SLV;
size = 16;
access_dev = READ_ONLY;
access_bus = READ_WRITE;
};
};
reg {
name = "Raw Interrupt Status Register";
prefix = "RISR";
field {
name = "Raw interrupt status";
description = "Each bit reflects the current state of corresponding IRQ input line.\n- read 1: interrupt line is currently active\n- read 0: interrupt line is inactive";
type = SLV;
size = 32;
access_dev = WRITE_ONLY;
access_bus = READ_ONLY;
};
};
reg {
name = "Interrupt Enable Register";
prefix = "IER";
field {
name = "Enable IRQ";
description = "- write 1: enables interrupt associated with written bit\n- write 0: no effect";
type = PASS_THROUGH;
size = 32;
};
};
reg {
name = "Interrupt Disable Register";
prefix = "IDR";
field {
name = "Disable IRQ";
description = "- write 1: enables interrupt associated with written bit\n- write 0: no effect";
type = PASS_THROUGH;
size = 32;
};
};
reg {
name = "Interrupt Mask Register";
prefix = "IMR";
field {
name = "IRQ disabled/enabled";
description = "- read 1: interrupt associated with read bit is enabled\n- read 0: interrupt is disabled";
type = SLV;
size = 32;
access_bus = READ_ONLY;
access_dev = WRITE_ONLY;
};
};
reg {
name = "Vector Address Register";
prefix = "VAR";
field {
name = "Vector Address";
description = "Address of pending interrupt vector, read from Interrupt Vector Table";
type = SLV;
size = 32;
access_bus = READ_ONLY;
access_dev = WRITE_ONLY;
};
};
reg {
name = "Software Interrupt Register";
description = "Writing 1 to one of bits of this register causes a software emulation of the respective interrupt.";
prefix = "SWIR";
field {
name = "SWI interrupt mask";
type = PASS_THROUGH;
size = 32;
};
};
reg {
name = "End Of Interrupt Acknowledge Register";
prefix = "EOIR";
field {
name = "End of Interrupt";
description = "Any write operation acknowledges the pending interrupt. Then, VIC advances to another pending interrupt(s) or releases the master interrupt output.";
type = PASS_THROUGH;
size = 32;
};
};
ram {
name = "Interrupt Vector Table";
description = "Vector Address Table. Word at offset N stores the vector address of IRQ N. When interrupt is requested, VIC reads it's vector address from this memory and stores it in VAR register. The contents of this table can be pre-initialized during synthesis through <code>g_init_vectors</code> generic parameter. This is used to auto-enumerate interrupts in SDB-based designs.";
prefix = "IVT_RAM";
size = 32;
width = 32;
access_bus = READ_WRITE;
access_dev = READ_ONLY;
};
};
......@@ -43,15 +43,19 @@ use work.genram_pkg.all;
entity wb_vic is
generic (
g_interface_mode : t_wishbone_interface_mode := CLASSIC;
g_address_granularity : t_wishbone_address_granularity := WORD;
g_INTERFACE_MODE : t_wishbone_interface_mode := CLASSIC;
g_ADDRESS_GRANULARITY : t_wishbone_address_granularity := WORD;
-- number of IRQ inputs.
g_num_interrupts : natural := 32;
g_NUM_INTERRUPTS : natural range 2 to 32 := 32;
-- initial values for the vector addresses.
g_init_vectors : t_wishbone_address_array := cc_dummy_address_array;
g_INIT_VECTORS : t_wishbone_address_array := cc_dummy_address_array;
g_retry_timeout : integer := 0
-- If True, the polarity is fixed and set by g_POLARITY
g_FIXED_POLARITY : boolean := False;
g_POLARITY : std_logic := '1';
g_RETRY_TIMEOUT : natural := 0
);
port (
......@@ -70,12 +74,9 @@ entity wb_vic is
irqs_i : in std_logic_vector(g_num_interrupts-1 downto 0); -- IRQ inputs
irq_master_o : out std_logic -- master IRQ output (multiplexed line, to the CPU)
);
);
end wb_vic;
architecture syn of wb_vic is
function f_resize_addr_array(a : t_wishbone_address_array; size : integer) return t_wishbone_address_array is
variable rv : t_wishbone_address_array(0 to size-1);
......@@ -94,10 +95,13 @@ architecture syn of wb_vic is
type t_state is (WAIT_IRQ, PROCESS_IRQ, WAIT_ACK, WAIT_MEM, WAIT_IDLE, RETRY);
signal irqs_i_reg : std_logic_vector(32 downto 0);
signal irqs_i_reg : std_logic_vector(g_NUM_INTERRUPTS - 1 downto 0);
signal vic_ctl_enable : std_logic;
signal vic_ctl_pol : std_logic;
signal vic_ctl_pol_in : std_logic;
signal vic_ctl_wr : std_logic;
signal vic_ctl_enable : std_logic;
signal vic_ctl_emu_edge : std_logic;
signal vic_ctl_emu_len : std_logic_vector(15 downto 0);
......@@ -112,7 +116,6 @@ architecture syn of wb_vic is
signal vic_eoir_wr : std_logic;
signal vic_ivt_ram_addr_wb : std_logic_vector(4 downto 0);
signal vic_ivt_ram_addr_int : std_logic_vector(4 downto 0);
signal vic_ivt_ram_data_towb : std_logic_vector(31 downto 0);
signal vic_ivt_ram_data_fromwb : std_logic_vector(31 downto 0);
signal vic_ivt_ram_data_int : std_logic_vector(31 downto 0);
......@@ -123,8 +126,7 @@ architecture syn of wb_vic is
signal swi_mask : std_logic_vector(31 downto 0);
signal current_irq : std_logic_vector(4 downto 0);
signal irq_id_encoded : std_logic_vector(4 downto 0);
signal current_irq : natural range 0 to 31;
signal state : t_state;
signal wb_in : t_wishbone_slave_in;
......@@ -134,11 +136,11 @@ architecture syn of wb_vic is
signal vector_table : t_wishbone_address_array(0 to 31) := f_resize_addr_array(g_init_vectors, 32);
constant c_valid_irq_mask : std_logic_vector(31 downto 0) :=
(31 downto g_NUM_INTERRUPTS => '0') & (g_NUM_INTERRUPTS - 1 downto 0 => '1');
begin -- syn
check1 : assert (g_num_interrupts >= 2 and g_num_interrupts <= 32)
report "invalid number of interrupts" severity failure;
-- Read and write vector table (from the bus)
p_vector_table_host : process(clk_sys_i)
variable sanitized_addr : integer;
begin
......@@ -152,39 +154,26 @@ begin -- syn
end if;
end process;
-- Read the vector for the current interrupt.
p_vector_table_int : process(clk_sys_i)
variable sanitized_addr : integer;
begin
if rising_edge(clk_sys_i) then
sanitized_addr := to_integer(unsigned(vic_ivt_ram_addr_int));
vic_ivt_ram_data_int <= vector_table(sanitized_addr);
vic_ivt_ram_data_int <= vector_table(current_irq);
end if;
end process;
p_register_irq_lines : process(clk_sys_i)
begin
if rising_edge(clk_sys_i) then
if rst_n_i = '0' then
irqs_i_reg <= (others => '0');
else
irqs_i_reg(g_num_interrupts-1 downto 0) <= (irqs_i or swi_mask(g_num_interrupts-1 downto 0)) and vic_imr(g_num_interrupts-1 downto 0);
irqs_i_reg(32 downto g_num_interrupts) <= (others => '0');
irqs_i_reg <= (irqs_i or swi_mask(g_NUM_INTERRUPTS-1 downto 0)) and vic_imr(g_NUM_INTERRUPTS-1 downto 0);
end if;
end if;
end process;
vic_risr <= irqs_i_reg(31 downto 0);
priority_encoder : entity work.vic_prio_enc
port map (
in_i => irqs_i_reg(31 downto 0),
out_o => irq_id_encoded);
vic_ivt_ram_addr_int <= current_irq;
vic_risr <= (31 downto g_NUM_INTERRUPTS => '0') & irqs_i_reg;
U_Slave_adapter : entity work.wb_slave_adapter
generic map (
......@@ -192,8 +181,8 @@ begin -- syn
g_master_mode => PIPELINED,
g_master_granularity => WORD,
g_slave_use_struct => false,
g_slave_mode => g_interface_mode,
g_slave_granularity => g_address_granularity)
g_slave_mode => g_INTERFACE_MODE,
g_slave_granularity => g_ADDRESS_GRANULARITY)
port map (
clk_sys_i => clk_sys_i,
rst_n_i => rst_n_i,
......@@ -213,10 +202,10 @@ begin -- syn
wb_out.err <= '0';
U_wb_controller : entity work.wb_slave_vic
U_wb_controller : entity work.wb_vic_regs
port map (
rst_n_i => rst_n_i,
clk_sys_i => clk_sys_i,
clk_i => clk_sys_i,
wb_adr_i => wb_in.adr(5 downto 0),
wb_dat_i => wb_in.dat,
wb_dat_o => wb_out.dat,
......@@ -227,50 +216,61 @@ begin -- syn
wb_ack_o => wb_out.ack,
wb_stall_o => wb_out.stall,
vic_ctl_enable_o => vic_ctl_enable,
vic_ctl_pol_o => vic_ctl_pol,
vic_ctl_emu_edge_o => vic_ctl_emu_edge,
vic_ctl_emu_len_o => vic_ctl_emu_len,
vic_risr_i => vic_risr,
vic_ier_o => vic_ier,
vic_ier_wr_o => vic_ier_wr,
vic_idr_o => vic_idr,
vic_idr_wr_o => vic_idr_wr,
vic_imr_i => vic_imr,
vic_var_i => vic_var,
vic_eoir_o => vic_eoir,
vic_eoir_wr_o => vic_eoir_wr,
vic_swir_o => vic_swir,
vic_swir_wr_o => vic_swir_wr,
vic_ivt_ram_addr_o => vic_ivt_ram_addr_wb,
vic_ivt_ram_data_i => vic_ivt_ram_data_towb,
vic_ivt_ram_data_o => vic_ivt_ram_data_fromwb,
vic_ivt_ram_wr_o => vic_ivt_ram_wr);
process (clk_sys_i)
begin -- process enable_disable_irqs
ctl_enable_o => vic_ctl_enable,
ctl_pol_o => vic_ctl_pol_in,
ctl_pol_i => vic_ctl_pol,
ctl_emu_edge_o => vic_ctl_emu_edge,
ctl_emu_len_o => vic_ctl_emu_len,
ctl_wr_o => vic_ctl_wr,
risr_i => vic_risr,
ier_o => vic_ier,
ier_wr_o => vic_ier_wr,
idr_o => vic_idr,
idr_wr_o => vic_idr_wr,
imr_i => vic_imr,
var_i => vic_var,
eoir_o => vic_eoir,
eoir_wr_o => vic_eoir_wr,
swir_o => vic_swir,
swir_wr_o => vic_swir_wr,
ivt_ram_addr_o => vic_ivt_ram_addr_wb,
ivt_ram_data_i => vic_ivt_ram_data_towb,
ivt_ram_data_o => vic_ivt_ram_data_fromwb,
ivt_ram_wr_o => vic_ivt_ram_wr);
gen_pol: if not g_FIXED_POLARITY generate
-- The polarity register
process (clk_sys_i)
begin
if rising_edge(clk_sys_i) then
if rst_n_i = '0' then
vic_ctl_pol <= '0';
else
if vic_ctl_wr = '1' then
vic_ctl_pol <= vic_ctl_pol_in;
end if;
end if;
end if;
end process;
end generate;
gen_fixed_pol: if g_FIXED_POLARITY generate
vic_ctl_pol <= g_POLARITY;
end generate;
p_vic_imr: process (clk_sys_i)
begin
if rising_edge(clk_sys_i) then
if rst_n_i = '0' then -- asynchronous reset (active low)
if rst_n_i = '0' then
vic_imr <= (others => '0');
else
if(vic_ier_wr = '1') then
for i in 0 to g_num_interrupts-1 loop
if(vic_ier(i) = '1') then
vic_imr(i) <= '1';
end if;
end loop; -- i
if vic_ier_wr = '1' then
vic_imr <= vic_imr or (vic_ier and c_valid_irq_mask);
end if;
if(vic_idr_wr = '1') then
for i in 0 to g_num_interrupts-1 loop
if(vic_idr(i) = '1') then
vic_imr(i) <= '0';
end if;
end loop; -- i
if vic_idr_wr = '1' then
vic_imr <= vic_imr and not vic_idr;
end if;
end if;
end if;
end process;
......@@ -278,10 +278,9 @@ begin -- syn
vic_fsm : process (clk_sys_i, rst_n_i)
begin -- process vic_fsm
if rising_edge(clk_sys_i) then
if rst_n_i = '0' then -- asynchronous reset (active low)
if rst_n_i = '0' then
state <= WAIT_IRQ;
current_irq <= (others => '0');
current_irq <= 0;
irq_master_o <= '0';
vic_var <= x"12345678";
swi_mask <= (others => '0');
......@@ -289,7 +288,7 @@ begin -- syn
else
if(vic_ctl_enable = '0') then
irq_master_o <= not vic_ctl_pol;
current_irq <= (others => '0');
current_irq <= 0;
state <= WAIT_IRQ;
vic_var <= x"12345678";
swi_mask <= (others => '0');
......@@ -301,13 +300,17 @@ begin -- syn
case state is
when WAIT_IRQ =>
if(irqs_i_reg /= (irqs_i_reg'range => '0')) then
current_irq <= irq_id_encoded;
state <= WAIT_MEM;
-- assert the master IRQ line
if irqs_i_reg /= (irqs_i_reg'range => '0') then
current_irq <= 0;
for i in 0 to g_NUM_INTERRUPTS - 1 loop
if irqs_i_reg (i) = '1' then
current_irq <= i;
exit;
end if;
end loop;
state <= WAIT_MEM;
else
-- no interrupts? de-assert the IRQ line
-- no interrupts? de-assert the IRQ line
irq_master_o <= not vic_ctl_pol;
vic_var <= (others => '0');
end if;
......@@ -316,16 +319,17 @@ begin -- syn
state <= PROCESS_IRQ;
when PROCESS_IRQ =>
-- fetch the vector address from vector table and load it into VIC_VAR register
vic_var <= vic_ivt_ram_data_int;
state <= WAIT_ACK;
irq_master_o <= vic_ctl_pol;
-- fetch the vector address from vector table and
-- load it into VIC_VAR register
vic_var <= vic_ivt_ram_data_int;
irq_master_o <= vic_ctl_pol;
timeout_count <= (others => '0');
state <= WAIT_ACK;
when WAIT_ACK =>
-- got write operation to VIC_EOIR register? if yes, advance to next interrupt.
if(vic_eoir_wr = '1') then
-- got write operation to VIC_EOIR register? if yes,
-- advance to next interrupt.
if vic_eoir_wr = '1' then
state <= WAIT_IDLE;
swi_mask <= (others => '0');
timeout_count <= (others => '0');
......@@ -342,12 +346,10 @@ begin -- syn
irq_master_o <= vic_ctl_pol;
state <= WAIT_ACK;
timeout_count <= (others => '0');
else
timeout_count <= timeout_count + 1;
else
timeout_count <= timeout_count + 1;
end if;
when WAIT_IDLE =>
if(vic_ctl_emu_edge = '0') then
state <= WAIT_IRQ;
......@@ -357,7 +359,6 @@ begin -- syn
if(timeout_count = unsigned(vic_ctl_emu_len)) then
state <= WAIT_IRQ;
end if;
end if;
end case;
end if;
......
# ------------------------------------------------------------------------------
# CERN BE-CO-HT
# General Cores Library
# https://www.ohwr.org/projects/general-cores
# ------------------------------------------------------------------------------
#
# unit name: wb_slave_vic
#
# description: Wishbone slave core for Vectored Interrupt Controller (VIC)
# block layout (cheby)
#
# ------------------------------------------------------------------------------
# Copyright CERN 2013-2018
# ------------------------------------------------------------------------------
# Copyright and related rights are licensed under the Solderpad Hardware
# License, Version 2.0 (the "License"); you may not use this file except
# in compliance with the License. You may obtain a copy of the License at
# http://solderpad.org/licenses/SHL-2.0.
# Unless required by applicable law or agreed to in writing, software,
# hardware and materials distributed under this License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
# or implied. See the License for the specific language governing permissions
# and limitations under the License.
# ------------------------------------------------------------------------------
memory-map:
bus: wb-32-be
name: wb_vic_regs
description: Vectored Interrupt Controller (VIC)
comment: |
Module implementing a 2 to 32-input prioritized interrupt controller with internal interrupt vector storage support.
children:
- reg:
name: CTL
address: 0x00000000
width: 32
access: rw
description: VIC Control Register
children:
- field:
name: ENABLE
range: 0
description: VIC Enable
comment: |
- 1: enables VIC operation
- 0: disables VIC operation
- field:
name: POL
range: 1
description: VIC output polarity
comment: |
- 1: IRQ output is active high
- 0: IRQ output is active low
x-hdl:
# Need a wire because it can be fixed.
type: wire
- field:
name: EMU_EDGE
range: 2
description: Emulate Edge sensitive output
comment: |
- 1: Forces a low pulse of <code>EMU_LEN</code> clock cycles at each write to <code>EOIR</code>. Deprecated.
- 0: Normal IRQ master line behavior
- field:
name: EMU_LEN
range: 18-3
description: Emulated Edge pulse timer
comment: |
Length of the delay (in <code>clk_sys_i</code> cycles) between write to <code>EOIR</code> and re-assertion of <code>irq_master_o</code>.
x-hdl:
write-strobe: True
- reg:
name: RISR
address: 0x00000004
width: 32
access: ro
description: Raw Interrupt Status Register
comment: |
Each bit reflects the current state of corresponding IRQ input line.
- read 1: interrupt line is currently active
- read 0: interrupt line is inactive
- reg:
name: IER
address: 0x00000008
width: 32
access: wo
description: Interrupt Enable Register
comment: |
- write 1: enables interrupt associated with written bit
- write 0: no effect
x-hdl:
type: wire
write-strobe: True
- reg:
name: IDR
address: 0x0000000c
width: 32
access: wo
description: Interrupt Disable Register
comment: |
- write 1: enables interrupt associated with written bit
- write 0: no effect
x-hdl:
type: wire
write-strobe: True
- reg:
name: IMR
address: 0x00000010
width: 32
access: ro
description: Interrupt Mask Register
comment: |
- read 1: interrupt associated with read bit is enabled
- read 0: interrupt is disabled
- reg:
name: VAR
address: 0x00000014
width: 32
access: ro
description: Vector Address Register
comment: |
Address of pending interrupt vector, read from Interrupt Vector Table
- reg:
name: SWIR
address: 0x00000018
width: 32
access: wo
description: Software Interrupt Register
comment: |
Writing 1 to one of bits of this register causes a software emulation of the respective interrupt.
x-hdl:
type: wire
write-strobe: True
- reg:
name: EOIR
address: 0x0000001c
width: 32
access: wo
description: End Of Interrupt Acknowledge Register
comment: |
Any write operation acknowledges the pending interrupt. Then, VIC advances to another pending interrupt(s) or releases the master interrupt output.
x-hdl:
type: wire
write-strobe: True
- submap:
name: IVT_RAM
address: 0x00000080
size: 0x80
interface: sram
description: Interrupt Vector Table
comment: |
Vector Address Table. Word at offset N stores the vector address of IRQ N. When interrupt is requested, VIC reads it's vector address from this memory and stores it in VAR register. The contents of this table can be pre-initialized during synthesis through <code>g_init_vectors</code> generic parameter. This is used to auto-enumerate interrupts in SDB-based designs.
# align: True
# children:
# - reg:
# name: data
# width: 32
# access: rw
-- Do not edit; this file was generated by Cheby using these options:
-- --gen-hdl -i wb_vic_regs.cheby
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity wb_vic_regs is
port (
rst_n_i : in std_logic;
clk_i : in std_logic;
wb_cyc_i : in std_logic;
wb_stb_i : in std_logic;
wb_adr_i : in std_logic_vector(7 downto 2);
wb_sel_i : in std_logic_vector(3 downto 0);
wb_we_i : in std_logic;
wb_dat_i : in std_logic_vector(31 downto 0);
wb_ack_o : out std_logic;
wb_err_o : out std_logic;
wb_rty_o : out std_logic;
wb_stall_o : out std_logic;
wb_dat_o : out std_logic_vector(31 downto 0);
-- VIC Enable
CTL_ENABLE_o : out std_logic;
-- VIC output polarity
CTL_POL_i : in std_logic;
-- VIC output polarity
CTL_POL_o : out std_logic;
-- Emulate Edge sensitive output
CTL_EMU_EDGE_o : out std_logic;
-- Emulated Edge pulse timer
CTL_EMU_LEN_o : out std_logic_vector(15 downto 0);
CTL_wr_o : out std_logic;
-- Raw Interrupt Status Register
RISR_i : in std_logic_vector(31 downto 0);
-- Interrupt Enable Register
IER_o : out std_logic_vector(31 downto 0);
IER_wr_o : out std_logic;
-- Interrupt Disable Register
IDR_o : out std_logic_vector(31 downto 0);
IDR_wr_o : out std_logic;
-- Interrupt Mask Register
IMR_i : in std_logic_vector(31 downto 0);
-- Vector Address Register
VAR_i : in std_logic_vector(31 downto 0);
-- Software Interrupt Register
SWIR_o : out std_logic_vector(31 downto 0);
SWIR_wr_o : out std_logic;
-- End Of Interrupt Acknowledge Register
EOIR_o : out std_logic_vector(31 downto 0);
EOIR_wr_o : out std_logic;
-- Interrupt Vector Table
IVT_RAM_addr_o : out std_logic_vector(6 downto 2);
IVT_RAM_data_i : in std_logic_vector(31 downto 0);
IVT_RAM_data_o : out std_logic_vector(31 downto 0);
IVT_RAM_wr_o : out std_logic
);
end wb_vic_regs;
architecture syn of wb_vic_regs is
signal rd_int : std_logic;
signal wr_int : std_logic;
signal rd_ack_int : std_logic;
signal wr_ack_int : std_logic;
signal wb_en : std_logic;
signal ack_int : std_logic;
signal wb_rip : std_logic;
signal wb_wip : std_logic;
signal CTL_ENABLE_reg : std_logic;
signal CTL_EMU_EDGE_reg : std_logic;
signal CTL_EMU_LEN_reg : std_logic_vector(15 downto 0);
signal IVT_RAM_rack : std_logic;
signal IVT_RAM_re : std_logic;
signal reg_rdat_int : std_logic_vector(31 downto 0);
signal rd_ack1_int : std_logic;
begin
-- WB decode signals
wb_en <= wb_cyc_i and wb_stb_i;
process (clk_i, rst_n_i) begin
if rst_n_i = '0' then
wb_rip <= '0';
elsif rising_edge(clk_i) then
wb_rip <= (wb_rip or (wb_en and not wb_we_i)) and not rd_ack_int;
end if;
end process;
rd_int <= (wb_en and not wb_we_i) and not wb_rip;
process (clk_i, rst_n_i) begin
if rst_n_i = '0' then
wb_wip <= '0';
elsif rising_edge(clk_i) then
wb_wip <= (wb_wip or (wb_en and wb_we_i)) and not wr_ack_int;
end if;
end process;
wr_int <= (wb_en and wb_we_i) and not wb_wip;
ack_int <= rd_ack_int or wr_ack_int;
wb_ack_o <= ack_int;
wb_stall_o <= not ack_int and wb_en;
wb_rty_o <= '0';
wb_err_o <= '0';
-- Assign outputs
CTL_ENABLE_o <= CTL_ENABLE_reg;
CTL_EMU_EDGE_o <= CTL_EMU_EDGE_reg;
CTL_EMU_LEN_o <= CTL_EMU_LEN_reg;
process (clk_i, rst_n_i) begin
if rst_n_i = '0' then
IVT_RAM_rack <= '0';
elsif rising_edge(clk_i) then
IVT_RAM_rack <= IVT_RAM_re and not IVT_RAM_rack;
end if;
end process;
IVT_RAM_data_o <= wb_dat_i;
IVT_RAM_addr_o <= wb_adr_i(6 downto 2);
-- Process for write requests.
process (clk_i, rst_n_i) begin
if rst_n_i = '0' then
wr_ack_int <= '0';
CTL_wr_o <= '0';
CTL_ENABLE_reg <= '0';
CTL_EMU_EDGE_reg <= '0';
CTL_EMU_LEN_reg <= "0000000000000000";
IER_wr_o <= '0';
IDR_wr_o <= '0';
SWIR_wr_o <= '0';
EOIR_wr_o <= '0';
IVT_RAM_wr_o <= '0';
elsif rising_edge(clk_i) then
wr_ack_int <= '0';
CTL_wr_o <= '0';
IER_wr_o <= '0';
IDR_wr_o <= '0';
SWIR_wr_o <= '0';
EOIR_wr_o <= '0';
IVT_RAM_wr_o <= '0';
case wb_adr_i(7 downto 7) is
when "0" =>
case wb_adr_i(6 downto 2) is
when "00000" =>
-- Register CTL
CTL_wr_o <= wr_int;
if wr_int = '1' then
CTL_ENABLE_reg <= wb_dat_i(0);
CTL_POL_o <= wb_dat_i(1);
CTL_EMU_EDGE_reg <= wb_dat_i(2);
CTL_EMU_LEN_reg <= wb_dat_i(18 downto 3);
end if;
wr_ack_int <= wr_int;
when "00001" =>
-- Register RISR
when "00010" =>
-- Register IER
IER_wr_o <= wr_int;
if wr_int = '1' then
IER_o <= wb_dat_i;
end if;
wr_ack_int <= wr_int;
when "00011" =>
-- Register IDR
IDR_wr_o <= wr_int;
if wr_int = '1' then
IDR_o <= wb_dat_i;
end if;
wr_ack_int <= wr_int;
when "00100" =>
-- Register IMR
when "00101" =>
-- Register VAR
when "00110" =>
-- Register SWIR
SWIR_wr_o <= wr_int;
if wr_int = '1' then
SWIR_o <= wb_dat_i;
end if;
wr_ack_int <= wr_int;
when "00111" =>
-- Register EOIR
EOIR_wr_o <= wr_int;
if wr_int = '1' then
EOIR_o <= wb_dat_i;
end if;
wr_ack_int <= wr_int;
when others =>
wr_ack_int <= wr_int;
end case;
when "1" =>
-- Submap IVT_RAM
IVT_RAM_wr_o <= wr_int;
wr_ack_int <= wr_int;
when others =>
wr_ack_int <= wr_int;
end case;
end if;
end process;
-- Process for registers read.
process (clk_i, rst_n_i) begin
if rst_n_i = '0' then
rd_ack1_int <= '0';
reg_rdat_int <= (others => 'X');
elsif rising_edge(clk_i) then
reg_rdat_int <= (others => '0');
case wb_adr_i(7 downto 7) is
when "0" =>
case wb_adr_i(6 downto 2) is
when "00000" =>
-- CTL
reg_rdat_int(0) <= CTL_ENABLE_reg;
reg_rdat_int(1) <= CTL_POL_i;
reg_rdat_int(2) <= CTL_EMU_EDGE_reg;
reg_rdat_int(18 downto 3) <= CTL_EMU_LEN_reg;
rd_ack1_int <= rd_int;
when "00001" =>
-- RISR
reg_rdat_int <= RISR_i;
rd_ack1_int <= rd_int;
when "00010" =>
-- IER
rd_ack1_int <= rd_int;
when "00011" =>
-- IDR
rd_ack1_int <= rd_int;
when "00100" =>
-- IMR
reg_rdat_int <= IMR_i;
rd_ack1_int <= rd_int;
when "00101" =>
-- VAR
reg_rdat_int <= VAR_i;
rd_ack1_int <= rd_int;
when "00110" =>
-- SWIR
rd_ack1_int <= rd_int;
when "00111" =>
-- EOIR
rd_ack1_int <= rd_int;
when others =>
rd_ack1_int <= rd_int;
end case;
when "1" =>
when others =>
rd_ack1_int <= rd_int;
end case;
end if;
end process;
-- Process for read requests.
process (wb_adr_i, reg_rdat_int, rd_ack1_int, rd_int, rd_int, IVT_RAM_data_i, IVT_RAM_rack) begin
-- By default ack read requests
wb_dat_o <= (others => '0');
IVT_RAM_re <= '0';
case wb_adr_i(7 downto 7) is
when "0" =>
case wb_adr_i(6 downto 2) is
when "00000" =>
-- CTL
wb_dat_o <= reg_rdat_int;
rd_ack_int <= rd_ack1_int;
when "00001" =>
-- RISR
wb_dat_o <= reg_rdat_int;
rd_ack_int <= rd_ack1_int;
when "00010" =>
-- IER
wb_dat_o <= reg_rdat_int;
rd_ack_int <= rd_ack1_int;
when "00011" =>
-- IDR
wb_dat_o <= reg_rdat_int;
rd_ack_int <= rd_ack1_int;
when "00100" =>
-- IMR
wb_dat_o <= reg_rdat_int;
rd_ack_int <= rd_ack1_int;
when "00101" =>
-- VAR
wb_dat_o <= reg_rdat_int;
rd_ack_int <= rd_ack1_int;
when "00110" =>
-- SWIR
wb_dat_o <= reg_rdat_int;
rd_ack_int <= rd_ack1_int;
when "00111" =>
-- EOIR
wb_dat_o <= reg_rdat_int;
rd_ack_int <= rd_ack1_int;
when others =>
rd_ack_int <= rd_int;
end case;
when "1" =>
-- Submap IVT_RAM
wb_dat_o <= IVT_RAM_data_i;
rd_ack_int <= IVT_RAM_rack;
IVT_RAM_re <= rd_int;
when others =>
rd_ack_int <= rd_int;
end case;
end process;
end syn;
......@@ -48,6 +48,10 @@ entity xwb_vic is
g_num_interrupts : natural := 32; -- number of IRQ inputs.
g_init_vectors : t_wishbone_address_array := cc_dummy_address_array;
-- If True, the polarity is fixed and set by g_POLARITY
g_FIXED_POLARITY : boolean := False;
g_POLARITY : std_logic := '1';
g_retry_timeout : integer := 0
);
......@@ -75,6 +79,8 @@ begin -- wrapper
g_address_granularity => g_address_granularity,
g_num_interrupts => g_num_interrupts,
g_init_vectors => g_init_vectors,
g_FIXED_POLARITY => g_FIXED_POLARITY,
g_POLARITY => g_POLARITY,
g_retry_timeout => g_retry_timeout)
port map (
clk_sys_i => clk_sys_i,
......
......@@ -1041,6 +1041,8 @@ package wishbone_pkg is
g_address_granularity : t_wishbone_address_granularity;
g_num_interrupts : natural;
g_init_vectors : t_wishbone_address_array := cc_dummy_address_array;
g_FIXED_POLARITY : boolean := False;
g_POLARITY : std_logic := '1';
g_retry_timeout : integer := 0
);
port (
......
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment