From 924882baa25b25b5b933a1f4e063d6effee2a053 Mon Sep 17 00:00:00 2001 From: Staf Verhaegen Date: Mon, 6 Jan 2020 18:05:06 +0100 Subject: [PATCH] Support for different IO types in VHDL code. IO cells can now be input, output, tri-state output, tri-state inout. Update tests and added separate test for c4m_jtag_ioblock. --- c4m/vhdl/jtag/c4m_jtag_ioblock.vhdl | 40 +++-- c4m/vhdl/jtag/c4m_jtag_iocell.vhdl | 154 ++++++++++++------ c4m/vhdl/jtag/c4m_jtag_pkg.vhdl | 52 ++++-- c4m/vhdl/jtag/c4m_jtag_tap_controller.vhdl | 73 +++++---- test/vhdl/cocotb/controller/Makefile | 6 +- test/vhdl/cocotb/controller/controller.vhdl | 76 +++++++++ test/vhdl/cocotb/controller/test.py | 20 +-- .../cocotb/dual_parallel/dual_parallel.vhdl | 19 +++ test/vhdl/cocotb/ioblock/Makefile | 26 +++ test/vhdl/cocotb/ioblock/ioblock.vhdl | 69 ++++++++ test/vhdl/cocotb/ioblock/test.py | 94 +++++++++++ test/vhdl/ghdl/idcode/idcode.vhdl | 7 +- 12 files changed, 510 insertions(+), 126 deletions(-) create mode 100644 test/vhdl/cocotb/controller/controller.vhdl create mode 100644 test/vhdl/cocotb/ioblock/Makefile create mode 100644 test/vhdl/cocotb/ioblock/ioblock.vhdl create mode 100644 test/vhdl/cocotb/ioblock/test.py diff --git a/c4m/vhdl/jtag/c4m_jtag_ioblock.vhdl b/c4m/vhdl/jtag/c4m_jtag_ioblock.vhdl index 10a592c..7b58d2d 100644 --- a/c4m/vhdl/jtag/c4m_jtag_ioblock.vhdl +++ b/c4m/vhdl/jtag/c4m_jtag_ioblock.vhdl @@ -8,7 +8,7 @@ use work.c4m_jtag.ALL; entity c4m_jtag_ioblock is generic ( IR_WIDTH: integer := 2; - IOS: integer := 1 + IOTYPES: IOTYPE_VECTOR ); port ( -- needed TAP signals @@ -26,14 +26,14 @@ entity c4m_jtag_ioblock is 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; @@ -42,16 +42,20 @@ architecture rtl of c4m_jtag_ioblock is 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), @@ -59,23 +63,25 @@ begin 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 @@ -85,7 +91,7 @@ begin 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'; diff --git a/c4m/vhdl/jtag/c4m_jtag_iocell.vhdl b/c4m/vhdl/jtag/c4m_jtag_iocell.vhdl index 6a218a6..b37c626 100644 --- a/c4m/vhdl/jtag/c4m_jtag_iocell.vhdl +++ b/c4m/vhdl/jtag/c4m_jtag_iocell.vhdl @@ -7,7 +7,7 @@ use work.c4m_jtag.ALL; entity c4m_jtag_iocell is generic ( - IR_WIDTH: integer := 2 + IOTYPE: IOTYPE_TYPE ); port ( -- core connections @@ -35,67 +35,127 @@ architecture rtl of c4m_jtag_iocell is 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; diff --git a/c4m/vhdl/jtag/c4m_jtag_pkg.vhdl b/c4m/vhdl/jtag/c4m_jtag_pkg.vhdl index 443a07c..7912914 100644 --- a/c4m/vhdl/jtag/c4m_jtag_pkg.vhdl +++ b/c4m/vhdl/jtag/c4m_jtag_pkg.vhdl @@ -7,6 +7,7 @@ package c4m_jtag is 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 ( @@ -15,11 +16,21 @@ package c4m_jtag 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 ( @@ -88,6 +99,9 @@ package c4m_jtag is end component c4m_jtag_idblock; component c4m_jtag_iocell is + generic ( + IOTYPE: IOTYPE_TYPE + ); port ( -- core connections CORE_IN: out std_logic; @@ -113,7 +127,7 @@ package c4m_jtag is component c4m_jtag_ioblock is generic ( IR_WIDTH: integer := 2; - IOS: integer := 1 + IOTYPES: IOTYPE_VECTOR ); port ( -- needed TAP signals @@ -125,20 +139,20 @@ package c4m_jtag is -- 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; @@ -147,7 +161,7 @@ package c4m_jtag is 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 @@ -171,15 +185,16 @@ package c4m_jtag is 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; @@ -212,4 +227,11 @@ package body c4m_jtag is 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; diff --git a/c4m/vhdl/jtag/c4m_jtag_tap_controller.vhdl b/c4m/vhdl/jtag/c4m_jtag_tap_controller.vhdl index f29c8f8..cfdf2f9 100644 --- a/c4m/vhdl/jtag/c4m_jtag_tap_controller.vhdl +++ b/c4m/vhdl/jtag/c4m_jtag_tap_controller.vhdl @@ -11,7 +11,7 @@ entity c4m_jtag_tap_controller is 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"; @@ -35,18 +35,20 @@ entity c4m_jtag_tap_controller is 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; @@ -117,29 +119,38 @@ begin 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 @@ -155,5 +166,3 @@ begin severity ERROR; end generate CHECK_EN; end rtl; - - diff --git a/test/vhdl/cocotb/controller/Makefile b/test/vhdl/cocotb/controller/Makefile index 05b570d..836f311 100644 --- a/test/vhdl/cocotb/controller/Makefile +++ b/test/vhdl/cocotb/controller/Makefile @@ -16,8 +16,10 @@ VHDL_SOURCES = \ $(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 diff --git a/test/vhdl/cocotb/controller/controller.vhdl b/test/vhdl/cocotb/controller/controller.vhdl new file mode 100644 index 0000000..35be680 --- /dev/null +++ b/test/vhdl/cocotb/controller/controller.vhdl @@ -0,0 +1,76 @@ +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; diff --git a/test/vhdl/cocotb/controller/test.py b/test/vhdl/cocotb/controller/test.py index 4772194..fc83b19 100644 --- a/test/vhdl/cocotb/controller/test.py +++ b/test/vhdl/cocotb/controller/test.py @@ -63,31 +63,31 @@ def test03_sample(dut): 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([]) diff --git a/test/vhdl/cocotb/dual_parallel/dual_parallel.vhdl b/test/vhdl/cocotb/dual_parallel/dual_parallel.vhdl index 870ea10..836c42f 100644 --- a/test/vhdl/cocotb/dual_parallel/dual_parallel.vhdl +++ b/test/vhdl/cocotb/dual_parallel/dual_parallel.vhdl @@ -5,6 +5,17 @@ use ieee.std_logic_1164.ALL; 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 @@ -36,6 +47,10 @@ architecture rtl of dual_parallel is 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, @@ -56,6 +71,10 @@ begin ); CTRL2: c4m_jtag_tap_controller + generic map ( + DEBUG => true, + IOTYPES => IOTYPES + ) port map ( TCK => I2_TCK, TMS => I2_TMS, diff --git a/test/vhdl/cocotb/ioblock/Makefile b/test/vhdl/cocotb/ioblock/Makefile new file mode 100644 index 0000000..5b9dbba --- /dev/null +++ b/test/vhdl/cocotb/ioblock/Makefile @@ -0,0 +1,26 @@ +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 diff --git a/test/vhdl/cocotb/ioblock/ioblock.vhdl b/test/vhdl/cocotb/ioblock/ioblock.vhdl new file mode 100644 index 0000000..e3bf078 --- /dev/null +++ b/test/vhdl/cocotb/ioblock/ioblock.vhdl @@ -0,0 +1,69 @@ +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; diff --git a/test/vhdl/cocotb/ioblock/test.py b/test/vhdl/cocotb/ioblock/test.py new file mode 100644 index 0000000..d9e386e --- /dev/null +++ b/test/vhdl/cocotb/ioblock/test.py @@ -0,0 +1,94 @@ +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" diff --git a/test/vhdl/ghdl/idcode/idcode.vhdl b/test/vhdl/ghdl/idcode/idcode.vhdl index cc7d167..05848b3 100644 --- a/test/vhdl/ghdl/idcode/idcode.vhdl +++ b/test/vhdl/ghdl/idcode/idcode.vhdl @@ -16,6 +16,7 @@ architecture rtl of bench_idcode is 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; @@ -54,11 +55,11 @@ begin 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 ); -- 2.30.2