Commit ca0ce6ce authored by Tristan Gingold's avatar Tristan Gingold

wb_vic: add fixed polarity; partial rewrite.

parent 68e1c650
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;
This diff is collapsed.
--------------------------------------------------------------------------------
-- 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;
};
};
This diff is collapsed.
# ------------------------------------------------------------------------------
# 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 (
......
Markdown is supported
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