entity c4m_jtag_ioblock is
generic (
IR_WIDTH: integer := 2;
- IOS: integer := 1
+ IOTYPES: IOTYPE_VECTOR
);
port (
-- needed TAP signals
UPDATE: in std_logic;
-- The I/O access ports
- CORE_OUT: in std_logic_vector(IOS-1 downto 0);
- CORE_IN: out std_logic_vector(IOS-1 downto 0);
- CORE_EN: in std_logic_vector(IOS-1 downto 0);
+ CORE_OUT: in std_logic_vector(IOTYPES'range);
+ CORE_IN: out std_logic_vector(IOTYPES'range);
+ CORE_EN: in std_logic_vector(IOTYPES'range);
-- The pad connections
- PAD_OUT: out std_logic_vector(IOS-1 downto 0);
- PAD_IN: in std_logic_vector(IOS-1 downto 0);
- PAD_EN: out std_logic_vector(IOS-1 downto 0)
+ PAD_OUT: out std_logic_vector(IOTYPES'range);
+ PAD_IN: in std_logic_vector(IOTYPES'range);
+ PAD_EN: out std_logic_vector(IOTYPES'range)
);
end c4m_jtag_ioblock;
signal SAMPLEMODE: SRSAMPLEMODE_TYPE;
signal ISSAMPLECMD: boolean;
- signal BDSR_IN: std_logic_vector(IOS-1 downto 0);
- signal BDSR_OUT: std_logic_vector(IOS-1 downto 0);
+ signal BDSR_IN: std_logic_vector(0 to IOTYPES'length-1);
+ signal BDSR_OUT: std_logic_vector(0 to IOTYPES'length-1);
constant CMD_SAMPLEPRELOAD: std_logic_vector(IR_WIDTH-1 downto 0) := c4m_jtag_cmd_samplepreload(IR_WIDTH);
constant CMD_EXTEST: std_logic_vector(IR_WIDTH-1 downto 0) := c4m_jtag_cmd_extest(IR_WIDTH);
begin
+
-- JTAG baundary scan IO cells
- IOGEN: for i in 0 to IOS-1 generate
+ IOGEN: for i in IOTYPES'low to IOTYPES'high generate
begin
IOCELL: c4m_jtag_iocell
+ generic map (
+ IOTYPE => IOTYPES(i)
+ )
port map (
CORE_IN => CORE_IN(i),
CORE_OUT => CORE_OUT(i),
PAD_IN => PAD_IN(i),
PAD_OUT => PAD_OUT(i),
PAD_EN => PAD_EN(i),
- BDSR_IN => BDSR_IN(i),
- BDSR_OUT => BDSR_OUT(i),
+ BDSR_IN => BDSR_IN(i-IOTYPES'low),
+ BDSR_OUT => BDSR_OUT(i-IOTYPES'low),
IOMODE => IOMODE,
SAMPLEMODE => SAMPLEMODE,
TCK => TCK
);
end generate;
- BDSRCONN: for i in 0 to IOS-2 generate
+ BDSRCONN: for i in 0 to BDSR_IN'length-2 generate
begin
BDSR_IN(i+1) <= BDSR_OUT(i);
end generate;
- BDSR_IN(0) <= TDI;
+ BDSR_IN(BDSR_IN'low) <= TDI;
-- Set IOMODE
- -- Currently SR_2Core or SR_Z are not used
+ -- Currently SR_2Pad, SR_2Core or SR_Z are not used
+ -- We cheat by letting CMD_EXTEST handle both connection
+ -- to pad and core.
-- TODO: Handle more IOMODEs
- IOMODE <= SR_2Pad when IR = CMD_EXTEST else
+ IOMODE <= SR_2PadCore when IR = CMD_EXTEST else
SR_Through;
-- Set SAMPLEMODE
SR_Shift when ISSAMPLECMD and SHIFT = '1' else
SR_Normal;
- TDO <= BDSR_OUT(IOS-1) when ISSAMPLECMD and SHIFT = '1' else
+ TDO <= BDSR_OUT(BDSR_IN'high) when ISSAMPLECMD and SHIFT = '1' else
'0';
TDO_EN <= '1' when ISSAMPLECMD and SHIFT = '1' else
'0';
entity c4m_jtag_iocell is
generic (
- IR_WIDTH: integer := 2
+ IOTYPE: IOTYPE_TYPE
);
port (
-- core connections
signal SR_IOIN: std_logic;
signal SR_IOOUT: std_logic;
signal SR_IOEN: std_logic;
+ signal SR_IOIN_next: std_logic;
+ signal SR_IOOUT_next: std_logic;
+ signal SR_IOEN_next: std_logic;
signal CORE_IN_BD: std_logic;
signal PAD_OUT_BD: std_logic;
signal PAD_EN_BD: std_logic;
begin
- with IOMODE select
- CORE_IN <=
- PAD_IN when SR_Through | SR_Z,
- PAD_IN when SR_2Pad,
- CORE_IN_BD when SR_2Core,
- 'X' when others;
-
- with IOMODE select
- PAD_OUT <=
- CORE_OUT when SR_Through,
- PAD_OUT_BD when SR_2Pad,
- '0' when SR_2Core | SR_Z,
- 'X' when others;
-
- with IOMODE select
- PAD_EN <=
- CORE_EN when SR_Through,
- PAD_EN_BD when SR_2Pad,
- '0' when SR_2Core | SR_Z,
- 'X' when others;
+ --
+ -- CORE_* and PAD_* signals
+ --
+ INPUT_gen: if IOTYPE = IO_IN or IOTYPE = IO_INOUT3 generate
+ with IOMODE select
+ CORE_IN <=
+ PAD_IN when SR_Through | SR_Z,
+ PAD_IN when SR_2Pad,
+ CORE_IN_BD when SR_2Core | SR_2PadCore,
+ 'X' when others;
+ end generate INPUT_gen;
+ NOINPUT_gen: if IOTYPE /= IO_IN and IOTYPE /= IO_INOUT3 generate
+ CORE_IN <= 'X';
+ end generate NOINPUT_gen;
+
+ OUTPUT_gen: if IOTYPE /= IO_IN generate
+ with IOMODE select
+ PAD_OUT <=
+ CORE_OUT when SR_Through,
+ PAD_OUT_BD when SR_2Pad | SR_2PadCore,
+ '0' when SR_2Core | SR_Z,
+ 'X' when others;
+ end generate OUTPUT_gen;
+ NOOUTPUT_gen: if IOTYPE = IO_IN generate
+ PAD_OUT <= 'X';
+ end generate NOOUTPUT_gen;
+
+ ENABLE_gen: if IOTYPE = IO_OUT3 or IOTYPE = IO_INOUT3 generate
+ with IOMODE select
+ PAD_EN <=
+ CORE_EN when SR_Through,
+ PAD_EN_BD when SR_2Pad | SR_2PadCore,
+ '0' when SR_2Core | SR_Z,
+ 'X' when others;
+ end generate ENABLE_gen;
+ NOENABLE_gen: if IOTYPE /= IO_OUT3 and IOTYPE /= IO_INOUT3 generate
+ PAD_EN <= 'X';
+ end generate NOENABLE_gen;
+
+
+ --
+ -- SR_* signals
+ --
+ IOIN_WITHIN_gen: if IOTYPE = IO_IN or IOTYPE = IO_INOUT3 generate
+ with SAMPLEMODE select
+ SR_IOIN_next <=
+ PAD_IN when SR_Sample,
+ BDSR_IN when SR_Shift,
+ SR_IOIN when others;
+ end generate IOIN_WITHIN_gen;
+ IOIN_NOIN_gen: if IOTYPE /= IO_IN and IOTYPE /= IO_INOUT3 generate
+ SR_IOIN_next <= 'X';
+ end generate IOIN_NOIN_gen;
+
+ IOOUT_NOINWITHOUT_gen: if IOTYPE = IO_OUT or IOTYPE = IO_OUT3 generate
+ with SAMPLEMODE select
+ SR_IOOUT_next <=
+ CORE_OUT when SR_Sample,
+ BDSR_IN when SR_Shift,
+ SR_IOOUT when others;
+ end generate IOOUT_NOINWITHOUT_gen;
+ IOOUT_WITHINOUT_gen: if IOTYPE = IO_INOUT3 generate
+ with SAMPLEMODE select
+ SR_IOOUT_next <=
+ CORE_OUT when SR_Sample,
+ SR_IOIN when SR_Shift,
+ SR_IOOUT when others;
+ end generate IOOUT_WITHINOUT_gen;
+ IOOUT_NOOUT_gen: if IOTYPE = IO_IN generate
+ SR_IOOUT_next <= 'X';
+ end generate IOOUT_NOOUT_gen;
+
+ IOEN_WITHOUT3_gen: if IOTYPE = IO_OUT3 or IOTYPE = IO_INOUT3 generate
+ with SAMPLEMODE select
+ SR_IOEN_next <=
+ CORE_EN when SR_Sample,
+ SR_IOOUT when SR_Shift,
+ SR_IOEN when others;
+ end generate IOEN_WITHOUT3_gen;
+ IOEN_NOOUT3_gen: if IOTYPE /= IO_OUT3 and IOTYPE /= IO_INOUT3 generate
+ SR_IOEN_next <= 'X';
+ end generate IOEN_NOOUT3_gen;
process (TCK)
begin
-- Sampling of inputs and shifting of boundary scan SR needs to be done on
- -- rising edge of TCK
+ -- rising edge of TCK.
if rising_edge(TCK) then
- case SAMPLEMODE is
- when SR_Sample =>
- SR_IOIN <= PAD_IN;
- SR_IOOUT <= CORE_OUT;
- SR_IOEN <= CORE_EN;
-
- when SR_Shift =>
- SR_IOIN <= BDSR_IN;
- SR_IOOUT <= SR_IOIN;
- SR_IOEN <= SR_IOOUT;
-
- when others =>
- null;
- end case;
+ SR_IOIN <= SR_IOIN_next;
+ SR_IOOUT <= SR_IOOUT_next;
+ SR_IOEN <= SR_IOEN_next;
end if;
-- Update of output from boundary scan SR needs to be done on falling edge
-- of TCK
- if falling_edge(TCK) then
- case SAMPLEMODE is
- when SR_Update =>
- CORE_IN_BD <= SR_IOIN;
- PAD_OUT_BD <= SR_IOOUT;
- PAD_EN_BD <= SR_IOEN;
-
- when others =>
- null;
- end case;
+ if falling_edge(TCK) and SAMPLEMODE = SR_Update then
+ CORE_IN_BD <= SR_IOIN;
+ PAD_OUT_BD <= SR_IOOUT;
+ PAD_EN_BD <= SR_IOEN;
end if;
end process;
- BDSR_OUT <= SR_IOEN;
+
+ --
+ -- BDSR_OUT signal
+ --
+ BDSROUT_NOOUT_gen: if IOTYPE = IO_IN generate
+ BDSR_OUT <= SR_IOIN;
+ end generate BDSROUT_NOOUT_gen;
+ BDSROUT_WITHOUT_gen: if IOTYPE = IO_OUT generate
+ BDSR_OUT <= SR_IOOUT;
+ end generate BDSROUT_WITHOUT_gen;
+ BDSROUT_WITHOUT3_gen: if IOTYPE = IO_OUT3 or IOTYPE = IO_INOUT3 generate
+ BDSR_OUT <= SR_IOEN;
+ end generate BDSROUT_WITHOUT3_gen;
end rtl;
SR_Through, -- Connect core signal to pad signals
SR_2Pad, -- Connect BD to pad
SR_2Core, -- Connect BD to core
+ SR_2PadCore, -- Connect BD to pad and core
SR_Z -- pad is high impedance
);
type SRSAMPLEMODE_TYPE is (
SR_Update, -- Update BD from SR on falling edge of TCK
SR_Shift -- Shift the BD SR
);
+ type IOTYPE_TYPE is (
+ IO_IN, -- Input only
+ IO_OUT, -- Output only, without tristate
+ IO_OUT3, -- Output only, with tristate
+ IO_INOUT3 -- Input and output with tristate
+ );
+ type IOTYPE_VECTOR is array ( natural range <> ) of IOTYPE_TYPE;
+
+ constant IOTYPES_NULL: IOTYPE_VECTOR(1 to 0) := (others => IO_INOUT3);
function c4m_jtag_cmd_idcode(width: integer) return std_logic_vector;
function c4m_jtag_cmd_bypass(width: integer) return std_logic_vector;
function c4m_jtag_cmd_samplepreload(width: integer) return std_logic_vector;
function c4m_jtag_cmd_extest(width: integer) return std_logic_vector;
+ function gen_iotypes(count: integer; iotype: IOTYPE_TYPE := IO_INOUT3) return IOTYPE_VECTOR;
component c4m_jtag_tap_fsm is
port (
end component c4m_jtag_idblock;
component c4m_jtag_iocell is
+ generic (
+ IOTYPE: IOTYPE_TYPE
+ );
port (
-- core connections
CORE_IN: out std_logic;
component c4m_jtag_ioblock is
generic (
IR_WIDTH: integer := 2;
- IOS: integer := 1
+ IOTYPES: IOTYPE_VECTOR
);
port (
-- needed TAP signals
-- The instruction
IR: in std_logic_vector(IR_WIDTH-1 downto 0);
- -- What action to perform
+ -- actions
CAPTURE: in std_logic;
SHIFT: in std_logic;
UPDATE: in std_logic;
-- The I/O access ports
- CORE_OUT: in std_logic_vector(IOS-1 downto 0);
- CORE_IN: out std_logic_vector(IOS-1 downto 0);
- CORE_EN: in std_logic_vector(IOS-1 downto 0);
+ CORE_OUT: in std_logic_vector(IOTYPES'range);
+ CORE_IN: out std_logic_vector(IOTYPES'range);
+ CORE_EN: in std_logic_vector(IOTYPES'range);
-- The pad connections
- PAD_OUT: out std_logic_vector(IOS-1 downto 0);
- PAD_IN: in std_logic_vector(IOS-1 downto 0);
- PAD_EN: out std_logic_vector(IOS-1 downto 0)
+ PAD_OUT: out std_logic_vector(IOTYPES'range);
+ PAD_IN: in std_logic_vector(IOTYPES'range);
+ PAD_EN: out std_logic_vector(IOTYPES'range)
);
end component c4m_jtag_ioblock;
DEBUG: boolean := false;
IR_WIDTH: integer := 2;
- IOS: integer := 1;
+ IOTYPES: IOTYPE_VECTOR := IOTYPES_NULL;
-- The default MANUFACTURING ID is not representing a valid
-- manufacturer according to the JTAG standard
CAPTURE: out std_logic; -- In DR_Capture state
SHIFT: out std_logic; -- In DR_Shift state
UPDATE: out std_logic; -- In DR_Update state
+
-- The I/O access ports
- CORE_IN: out std_logic_vector(IOS-1 downto 0);
- CORE_EN: in std_logic_vector(IOS-1 downto 0);
- CORE_OUT: in std_logic_vector(IOS-1 downto 0);
+ CORE_IN: out std_logic_vector(IOTYPES'range);
+ CORE_EN: in std_logic_vector(IOTYPES'range);
+ CORE_OUT: in std_logic_vector(IOTYPES'range);
-- The pad connections
- PAD_IN: in std_logic_vector(IOS-1 downto 0);
- PAD_EN: out std_logic_vector(IOS-1 downto 0);
- PAD_OUT: out std_logic_vector(IOS-1 downto 0)
+ PAD_IN: in std_logic_vector(IOTYPES'range);
+ PAD_EN: out std_logic_vector(IOTYPES'range);
+ PAD_OUT: out std_logic_vector(IOTYPES'range)
);
end component c4m_jtag_tap_controller;
end c4m_jtag;
return_vector := (others => '0');
return return_vector;
end;
+
+ function gen_iotypes(count: integer; iotype: IOTYPE_TYPE := IO_INOUT3) return IOTYPE_VECTOR is
+ variable return_vector: IOTYPE_VECTOR(0 to count-1);
+ begin
+ return_vector := (others => iotype);
+ return return_vector;
+ end function gen_iotypes;
end package body;
DEBUG: boolean := false;
IR_WIDTH: integer := 2;
- IOS: integer := 1;
+ IOTYPES: IOTYPE_VECTOR := IOTYPES_NULL;
MANUFACTURER: std_logic_vector(10 downto 0) := "10001111111";
PART_NUMBER: std_logic_vector(15 downto 0) := "0000000000000001";
UPDATE: out std_logic;
-- The I/O access ports
- CORE_IN: out std_logic_vector(IOS-1 downto 0);
- CORE_EN: in std_logic_vector(IOS-1 downto 0);
- CORE_OUT: in std_logic_vector(IOS-1 downto 0);
+ CORE_IN: out std_logic_vector(IOTYPES'range);
+ CORE_EN: in std_logic_vector(IOTYPES'range);
+ CORE_OUT: in std_logic_vector(IOTYPES'range);
-- The pad connections
- PAD_IN: in std_logic_vector(IOS-1 downto 0);
- PAD_EN: out std_logic_vector(IOS-1 downto 0);
- PAD_OUT: out std_logic_vector(IOS-1 downto 0)
+ PAD_IN: in std_logic_vector(IOTYPES'range);
+ PAD_EN: out std_logic_vector(IOTYPES'range);
+ PAD_OUT: out std_logic_vector(IOTYPES'range)
);
end c4m_jtag_tap_controller;
architecture rtl of c4m_jtag_tap_controller is
+ constant null_logic_vector: std_logic_vector(1 to 0) := (others => 'X');
+
signal S_RESET: std_logic;
signal S_ISIR: std_logic;
signal S_ISDR: std_logic;
SHIFT => S_SHIFT and S_ISDR,
UPDATE => S_UPDATE and S_ISDR
);
-
- -- The IOS
- IOBLOCK: c4m_jtag_ioblock
- generic map (
- IR_WIDTH => IR_WIDTH,
- IOS => IOS
- )
- port map (
- TCK => TCK,
- TDI => TDI,
- TDO => IO_TDO,
- TDO_EN => IO_TDO_EN,
- IR => S_IR,
- CAPTURE => S_CAPTURE and S_ISDR,
- SHIFT => S_SHIFT and S_ISDR,
- UPDATE => S_UPDATE and S_ISDR,
- CORE_OUT => CORE_OUT,
- CORE_IN => CORE_IN,
- CORE_EN => CORE_EN,
- PAD_OUT => PAD_OUT,
- PAD_IN => PAD_IN,
- PAD_EN => PAD_EN
- );
+
+ -- The IOs
+ IOBLOCK_gen: if IOTYPES'length > 0 generate
+ IOBLOCK: c4m_jtag_ioblock
+ generic map (
+ IR_WIDTH => IR_WIDTH,
+ IOTYPES => IOTYPES
+ )
+ port map (
+ TCK => TCK,
+ TDI => TDI,
+ TDO => IO_TDO,
+ TDO_EN => IO_TDO_EN,
+ IR => S_IR,
+ CAPTURE => S_CAPTURE and S_ISDR,
+ SHIFT => S_SHIFT and S_ISDR,
+ UPDATE => S_UPDATE and S_ISDR,
+ CORE_OUT => CORE_OUT,
+ CORE_IN => CORE_IN,
+ CORE_EN => CORE_EN,
+ PAD_OUT => PAD_OUT,
+ PAD_IN => PAD_IN,
+ PAD_EN => PAD_EN
+ );
+ end generate IOBLOCK_gen;
+ NOIOBLOCK_gen: if IOTYPES'length = 0 generate
+ IO_TDO <= '0';
+ IO_TDO_EN <= '0';
+ CORE_IN <= null_logic_vector;
+ PAD_EN <= null_logic_vector;
+ PAD_OUT <= null_logic_vector;
+ end generate NOIOBLOCK_gen;
TDO <= IR_TDO when IR_TDO_EN = '1' else
ID_TDO when ID_TDO_EN = '1' else
severity ERROR;
end generate CHECK_EN;
end rtl;
-
-
$(VHDLDIR)/c4m_jtag_iocell.vhdl \
$(VHDLDIR)/c4m_jtag_ioblock.vhdl \
$(VHDLDIR)/c4m_jtag_idblock.vhdl \
- $(VHDLDIR)/c4m_jtag_tap_controller.vhdl
-TOPLEVEL=c4m_jtag_tap_controller
+ $(VHDLDIR)/c4m_jtag_tap_controller.vhdl \
+ $(CURDIR)/controller.vhdl
+#VHDL_SOURCES end
+TOPLEVEL=controller
TOPLEVEL_LANG=vhdl
MODULE=test
SIM=ghdl
--- /dev/null
+library ieee;
+use ieee.std_logic_1164.ALL;
+
+use work.c4m_jtag.ALL;
+
+package controller_pkg is
+ constant IOTYPES: IOTYPE_VECTOR(0 to 3) := (
+ 0 => IO_IN,
+ 1 => IO_OUT,
+ 2 => IO_OUT3,
+ 3 => IO_INOUT3
+ );
+end package controller_pkg;
+
+library ieee;
+use ieee.std_logic_1164.ALL;
+
+use work.c4m_jtag.ALL;
+use work.controller_pkg.ALL;
+
+entity controller is
+ port (
+ -- The TAP signals
+ TCK: in std_logic;
+ TMS: in std_logic;
+ TDI: in std_logic;
+ TDO: out std_logic;
+ TRST_N: in std_logic;
+
+ -- The Instruction Register
+ IR: out std_logic_vector(1 downto 0);
+
+ -- The FSM state indicators
+ RESET: out std_logic;
+ CAPTURE: out std_logic;
+ SHIFT: out std_logic;
+ UPDATE: out std_logic;
+
+ -- The I/O access ports
+ CORE_IN: out std_logic_vector(IOTYPES'range);
+ CORE_EN: in std_logic_vector(IOTYPES'range);
+ CORE_OUT: in std_logic_vector(IOTYPES'range);
+
+ -- The pad connections
+ PAD_IN: in std_logic_vector(IOTYPES'range);
+ PAD_EN: out std_logic_vector(IOTYPES'range);
+ PAD_OUT: out std_logic_vector(IOTYPES'range)
+ );
+end controller;
+
+architecture rtl of controller is
+begin
+ ctrl: c4m_jtag_tap_controller
+ generic map (
+ DEBUG => true,
+ IOTYPES => IOTYPES
+ )
+ port map (
+ TCK => TCK,
+ TMS => TMS,
+ TDI => TDI,
+ TDO => TDO,
+ TRST_N => TRST_N,
+ IR => IR,
+ RESET => RESET,
+ CAPTURE => CAPTURE,
+ SHIFT => SHIFT,
+ UPDATE => UPDATE,
+ CORE_IN => CORE_IN,
+ CORE_EN => CORE_EN,
+ CORE_OUT => CORE_OUT,
+ PAD_IN => PAD_IN,
+ PAD_EN => PAD_EN,
+ PAD_OUT => PAD_OUT
+ );
+end architecture rtl;
dut._log.info("Load SAMPLEPRELOAD command")
yield master.load_ir(master.SAMPLEPRELOAD)
- data_in.binstr = "011"
+ data_in.binstr = "0101110"
dut._log.info(" preloading data {}".format(data_in.binstr))
# Set the ios pins
- dut.core_out = 0
- dut.core_en = 0
- dut.pad_in = 1
+ dut.core_out = BinaryValue("X010")
+ dut.core_en = BinaryValue("XX01")
+ dut.pad_in = BinaryValue("1XX0")
yield master.shift_data(data_in)
dut._log.info(" output: {}".format(master.result.binstr))
- assert(master.result.binstr == "100")
+ assert(master.result.binstr == "1010001")
dut._log.info("Load EXTEST command")
yield master.load_ir(master.EXTEST)
- data_in.binstr = "100"
+ data_in.binstr = "1010001"
dut._log.info(" input data {}".format(data_in.binstr))
# Set the ios pins
- dut.core_out = 1
- dut.core_en = 1
- dut.pad_in = 0
+ dut.core_out = BinaryValue("X101")
+ dut.core_en = BinaryValue("XX10")
+ dut.pad_in = BinaryValue("0XX1")
yield master.shift_data(data_in)
dut._log.info(" output: {}".format(master.result.binstr))
- assert(master.result.binstr == "011")
+ assert(master.result.binstr == "0101110")
dut._log.info("Do a capture of the last loaded data")
yield master.shift_data([])
use work.c4m_jtag.ALL;
+package dual_parallel_pkg is
+ constant IOTYPES: IOTYPE_VECTOR(0 to 0) := (0 => IO_INOUT3);
+end package dual_parallel_pkg;
+
+
+library ieee;
+use ieee.std_logic_1164.ALL;
+
+use work.c4m_jtag.ALL;
+use work.dual_parallel_pkg.ALL;
+
entity dual_parallel is
port (
-- Instance 1
signal I2_PAD_OUT: std_logic;
begin
CTRL1: c4m_jtag_tap_controller
+ generic map (
+ DEBUG => true,
+ IOTYPES => IOTYPES
+ )
port map (
TCK => I1_TCK,
TMS => I1_TMS,
);
CTRL2: c4m_jtag_tap_controller
+ generic map (
+ DEBUG => true,
+ IOTYPES => IOTYPES
+ )
port map (
TCK => I2_TCK,
TMS => I2_TMS,
--- /dev/null
+CURDIR=$(realpath .)
+TOPDIR=$(realpath ../../../..)
+
+VHDLDIR=$(TOPDIR)/c4m/vhdl/jtag
+VHDL_SOURCES = \
+ $(VHDLDIR)/c4m_jtag_pkg.vhdl \
+ $(VHDLDIR)/c4m_jtag_tap_fsm.vhdl \
+ $(VHDLDIR)/c4m_jtag_irblock.vhdl \
+ $(VHDLDIR)/c4m_jtag_iocell.vhdl \
+ $(VHDLDIR)/c4m_jtag_ioblock.vhdl \
+ $(VHDLDIR)/c4m_jtag_idblock.vhdl \
+ $(VHDLDIR)/c4m_jtag_tap_controller.vhdl \
+ $(CURDIR)/ioblock.vhdl \
+#end VHDL_SOURCES
+TOPLEVEL=ioblock
+TOPLEVEL_LANG=vhdl
+MODULE=test
+SIM=ghdl
+GPI_IMPL=vhpi
+GHDL_ARGS=--std=08
+SIM_ARGS=--wave=test.ghw
+
+COCOTBMAKEFILESDIR=$(shell cocotb-config --makefiles)
+
+include $(COCOTBMAKEFILESDIR)/Makefile.inc
+include $(COCOTBMAKEFILESDIR)/Makefile.sim
--- /dev/null
+library ieee;
+use ieee.std_logic_1164.all;
+
+use work.c4m_jtag.all;
+
+package ioblock_pkg is
+ constant IOTYPES: IOTYPE_VECTOR(0 to 3) := (
+ 0 => IO_IN,
+ 1 => IO_OUT,
+ 2 => IO_OUT3,
+ 3 => IO_INOUT3
+ );
+ constant IR_WIDTH: integer := 2;
+end package ioblock_pkg;
+
+
+library ieee;
+use ieee.std_logic_1164.all;
+
+use work.c4m_jtag.all;
+use work.ioblock_pkg.all;
+
+entity ioblock is
+ port (
+ TCK: in std_logic;
+ TDI: in std_logic;
+ TDO: out std_logic;
+ TDO_EN: out std_logic;
+
+ IR: in std_logic_vector(IR_WIDTH-1 downto 0);
+
+ CAPTURE: in std_logic;
+ SHIFT: in std_logic;
+ UPDATE: in std_logic;
+
+ CORE_OUT: in std_logic_vector(IOTYPES'range);
+ CORE_IN: out std_logic_vector(IOTYPES'range);
+ CORE_EN: in std_logic_vector(IOTYPES'range);
+
+ PAD_OUT: out std_logic_vector(IOTYPES'range);
+ PAD_IN: in std_logic_vector(IOTYPES'range);
+ PAD_EN: out std_logic_vector(IOTYPES'range)
+ );
+end entity ioblock;
+
+architecture rtl of ioblock is
+begin
+ blck: c4m_jtag_ioblock
+ generic map (
+ IR_WIDTH => IR_WIDTH,
+ IOTYPES => IOTYPES
+ )
+ port map (
+ TCK => TCK,
+ TDI => TDI,
+ TDO => TDO,
+ TDO_EN => TDO_EN,
+ IR => IR,
+ CAPTURE => CAPTURE,
+ SHIFT => SHIFT,
+ UPDATE => UPDATE,
+ CORE_OUT => CORE_OUT,
+ CORE_IN => CORE_IN,
+ CORE_EN => CORE_EN,
+ PAD_OUT => PAD_OUT,
+ PAD_IN => PAD_IN,
+ PAD_EN => PAD_EN
+ );
+end architecture rtl;
--- /dev/null
+import cocotb
+from cocotb.utils import get_sim_steps
+from cocotb.binary import BinaryValue
+from cocotb.triggers import Timer
+
+def report_bdsr(dut):
+ for handle in dut.blck:
+ if handle._name.startswith("iogen"):
+ for handle2 in handle:
+ if handle2._name == "iocell":
+ values = {}
+ for handle3 in handle2:
+ if handle3._name in ("bdsr_in", "bdsr_out", "sr_ioin", "sr_ioout", "sr_ioen"):
+ values[handle3._name] = handle3.value.binstr
+ dut._log.info("{}: {!r}".format(handle2._path, values))
+
+@cocotb.test()
+def test01_boundaryscan(dut):
+ """
+ Check initialization
+ """
+ dut.ir = 0
+ dut.tck = 0
+ dut.tdi = 1
+ dut.capture = 0
+ dut.shift = 0
+ dut.update = 0
+
+ # Boundary scan: IN > OUT > OUT3 > INOUT3
+ # Length: 1 + 1 + 2 + 3 = 7
+
+ yield Timer(1)
+
+ report_bdsr(dut)
+
+ assert dut.core_in.value.binstr == "UXXU"
+ assert dut.pad_out.value.binstr == "XUUU"
+ assert dut.pad_en.value.binstr == "XXUU"
+
+ dut.ir = BinaryValue("10") # SAMPLEPRELOAD
+ dut.core_out = BinaryValue("0000")
+ dut.core_en = BinaryValue("0000")
+ dut.pad_in = BinaryValue("0000")
+ yield Timer(1)
+
+ assert dut.core_in.value.binstr == "0XX0"
+ assert dut.pad_out.value.binstr == "X000"
+ assert dut.pad_en.value.binstr == "XX00"
+
+ dut.capture = 1
+ yield Timer(1)
+ dut.tck = 1
+ yield Timer(1)
+ dut.capture = 0
+ dut.tck = 0
+ yield Timer(1)
+
+ assert dut.core_in.value.binstr == "0XX0"
+ assert dut.pad_out.value.binstr == "X000"
+ assert dut.pad_en.value.binstr == "XX00"
+
+ dut.shift = 1
+ yield Timer(1)
+ for i in range(7):
+ dut._log.info("Cycle {}".format(i))
+ report_bdsr(dut)
+ assert dut.tdo.value.binstr == "0"
+ dut.tck = 1
+ yield Timer(1)
+ dut.tck = 0
+ yield Timer(1)
+ dut._log.info("Cycle 7")
+ report_bdsr(dut)
+ assert dut.tdo.value.binstr == "1"
+
+ dut.shift = 0
+ dut.update = 1
+ yield Timer(1)
+ dut.tck = 1
+ yield Timer(1)
+ dut.update = 0
+ dut.tck = 0
+ yield Timer(1)
+
+ assert dut.core_in.value.binstr == "0XX0"
+ assert dut.pad_out.value.binstr == "X000"
+ assert dut.pad_en.value.binstr == "XX00"
+
+ dut.ir = BinaryValue("00") # EXTEST
+ yield Timer(1)
+
+ assert dut.core_in.value.binstr == "0XX0"
+ assert dut.pad_out.value.binstr == "X111"
+ assert dut.pad_en.value.binstr == "XX11"
signal TRST_N: std_logic;
constant CLK_PERIOD: time := 10 ns;
+ constant NULL_STDVECTOR: std_logic_vector(1 to 0) := (others => 'X');
procedure ClkCycle(
signal CLK: out std_logic;
SHIFT => open,
UPDATE => open,
IR => open,
- CORE_OUT => "0",
+ CORE_OUT => NULL_STDVECTOR,
CORE_IN => open,
- CORE_EN => "0",
+ CORE_EN => NULL_STDVECTOR,
PAD_OUT => open,
- PAD_IN => "0",
+ PAD_IN => NULL_STDVECTOR,
PAD_EN => open
);