contrib/firmware/angie: add new spartan6 VHDL code

This new code implement two FIFOs for handling TX and RX
JTAG data transfers, its simply receives data and send it
OUT to target chip in respect of JTAG protocol timing
constraints.
The IN FIFO receives data from target chip and send it
back to openocd.

Change-Id: I17c1231e7f4b0a6b510359fe147b609922e0809e
Signed-off-by: Ahmed BOUDJELIDA <aboudjelida@nanoxplore.com>
Reviewed-on: https://review.openocd.org/c/openocd/+/8715
Tested-by: jenkins
Reviewed-by: Antonio Borneo <borneo.antonio@gmail.com>
This commit is contained in:
Ahmed BOUDJELIDA
2024-12-12 10:17:25 +01:00
committed by Antonio Borneo
parent 2f1a0ab35f
commit ceaa47a2aa
5 changed files with 514 additions and 109 deletions

View File

@@ -1,8 +1,8 @@
## SPDX-License-Identifier: BSD-3-Clause
##--------------------------------------------------------------------------
## Project Context: nanoXplore USB-JTAG Adapter Board, Spartan6
## Design Name: NJTAG USB-JTAG Adapter FPGA source code
## Module Name: _angie_openocd.ucf
## Project Context: nanoXplore USB to JTAG/I2C Adapter Board, Spartan6
## Design Name: ANGIE USB to JTAG/I2C Adapter FPGA source code
## Module Name: angie_bitstream.ucf
## Target Device: XC6SLX9-2 TQ144
## Tool versions: ISE Webpack 13.2 -> 14.2
## Author: Ahmed BOUDJELIDA nanoXplore SAS
@@ -10,41 +10,65 @@
# WARNING: PullUps on JTAG inputs should be enabled after configuration
# (bitgen option) since the pins are not connected.
net TRST LOC = 'P48' ;
net TMS LOC = 'P43' ;
net TCK LOC = 'P44' ;
net TDI LOC = 'P45' ;
net TDO LOC = 'P46' ;
net SRST LOC = 'P61' ;
CONFIG VCCAUX = "3.3";
net SDA LOC = 'P50' ;
net SCL LOC = 'P51' ;
net SDA_DIR LOC = 'P56' ;
net SCL_DIR LOC = 'P57' ;
# Timing
# net IH24 period = 40; # Constrain at 25MHz
# net IH40 period = 25; # Constrain at 40MHz
# DCMs placement on Spartan6
# INST S6MOD_CKMUL.H48_DCM LOC = DCM0;
net SI_TDO LOC = 'P16' ;
net SO_TRST LOC = 'P32' ;
net SO_TMS LOC = 'P27' ;
net SO_TCK LOC = 'P30' ;
net SO_TDI LOC = 'P26' ;
net SO_SRST LOC = 'P12' ;
# Clock 48MHz
net IFCLK_I LOC = 'P123' ;
net SO_SDA_OUT LOC = 'P140' ;
net SO_SDA_IN LOC = 'P1' ;
net SO_SCL LOC = 'P137';
net GD_IO<0> LOC = 'P48' ;
net GD_IO<1> LOC = 'P43' ;
net GD_IO<2> LOC = 'P44' ;
net GD_IO<3> LOC = 'P45' ;
net GD_IO<4> LOC = 'P46' ;
net GD_IO<5> LOC = 'P61' ;
net GD_IO<6> LOC = 'P62' ;
net GD_IO<7> LOC = 'P65' ;
net ST_0 LOC = 'P29' ;
net ST_1 LOC = 'P21' ;
net ST_2 LOC = 'P11' ;
net PA2_I LOC = 'P47' ;
#net PA3_I LOC = 'P64' ;
net JPW_I LOC = 'P14' ;
net ST_4 LOC = 'P134' ;
net ST_5 LOC = 'P139' ;
net GCTL0_I LOC = 'P70' ;
#net GCTL1_I LOC = 'P55' ;
#net GCTL2_I LOC = 'P67' ;
net GRDY1_I LOC = 'P118' ;
net FTP<0> LOC = 'P121' ;
net FTP<1> LOC = 'P120' ;
net FTP<2> LOC = 'P119' ;
net FTP<3> LOC = 'P116' ;
net FTP<4> LOC = 'P111' ;
net FTP<5> LOC = 'P112' ;
net FTP<6> LOC = 'P115' ;
net FTP<7> LOC = 'P114' ;
#net SDA_IO LOC = 'P50' ;
net SDA_IO LOC = 'P64' ; #PA3
#net SCL_I LOC = 'P51' ;
net SCL_I LOC = 'P39' ; #PA4 switch
net SDA_DIR_I LOC = 'P66' ; #PA0 switch
#net SCL_DIR_I LOC = 'P57' ;
net SO_SDA_OUT_O LOC = 'P140' ;
net SO_SDA_IN_I LOC = 'P1' ;
net SO_SCL_O LOC = 'P137' ;
net SO_TRST_O LOC = 'P32' ;
net SO_TMS_O LOC = 'P27' ;
net SO_TCK_O LOC = 'P30' ;
net SO_TDI_O LOC = 'P26' ;
net SO_SRST_O LOC = 'P12' ;
net SI_TDO_I LOC = 'P16' ;
net ST_0_O LOC = 'P29' ;
net ST_1_O LOC = 'P21' ;
net ST_2_O LOC = 'P11' ;
net ST_3_O LOC = 'P7' ;
net ST_4_O LOC = 'P134' ;
net ST_5_O LOC = 'P139' ;
net FTP_O<0> LOC = 'P121' ;
net FTP_O<1> LOC = 'P120' ;
net FTP_O<2> LOC = 'P119' ;
net FTP_O<3> LOC = 'P116' ;
net FTP_O<4> LOC = 'P111' ;
net FTP_O<5> LOC = 'P112' ;
net FTP_O<6> LOC = 'P115' ;
net FTP_O<7> LOC = 'P114' ;

View File

@@ -1,103 +1,428 @@
-- SPDX-License-Identifier: BSD-3-Clause
----------------------------------------------------------------------------
-- Project Context: nanoXplore USB-JTAG Adapter Board, Spartan6
-- Design Name: NJTAG USB-JTAG Adapter FPGA source code
-- Module Name: _angie_openocd.vhd
-- Project Context: nanoXplore USB to JTAG/I2C Adapter Board, Spartan6
-- Design Name: ANGIE USB to JTAG/I2C Adapter FPGA source code
-- Module Name: angie_bitstream.vhd
-- Target Device: XC6SLX9-2 TQ144
-- Tool versions: ISE Webpack 13.2 -> 14.2
-- Author: Ahmed BOUDJELIDA nanoXplore SAS
----------------------------------------------------------------------------
library work;
use work.all;
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;
library UNISIM;
use UNISIM.VComponents.all;
entity S609 is port(
TRST : in std_logic;
TMS : in std_logic;
TCK : in std_logic;
TDI : in std_logic;
TDO : out std_logic;
SRST : in std_logic;
entity angie_bitstream is port(
SDA_IO : inout std_logic;
SDA_DIR_I : in std_logic;
SCL_I : in std_logic;
SDA : inout std_logic;
SDA_DIR : in std_logic;
SCL : in std_logic;
SCL_DIR : in std_logic;
JPW_I : in std_logic; --Devkit power
FTP : out std_logic_vector(7 downto 0); -- Test points
SI_TDO : in std_logic;
ST_0 : out std_logic;
ST_1 : out std_logic;
ST_2 : out std_logic;
SO_SDA_OUT_O : out std_logic;
SO_SDA_IN_I : in std_logic;
SO_SCL_O : out std_logic;
ST_4 : out std_logic;
ST_5 : out std_logic;
ST_0_O : out std_logic;
ST_1_O : out std_logic;
ST_2_O : out std_logic;
ST_3_O : out std_logic;
ST_4_O : out std_logic;
ST_5_O : out std_logic;
SO_SDA_OUT : out std_logic;
SO_SDA_IN : in std_logic;
SO_SCL : out std_logic;
SO_TRST_O : out std_logic;
SO_TMS_O : out std_logic;
SO_TCK_O : out std_logic;
SO_TDI_O : out std_logic;
SO_SRST_O : out std_logic;
SI_TDO_I : in std_logic;
SO_TRST : out std_logic;
SO_TMS : out std_logic;
SO_TCK : out std_logic;
SO_TDI : out std_logic;
SO_SRST : out std_logic
PA2_I : in std_logic; -- GPIF IN
-- Clock 48MHz
IFCLK_I : in std_logic;
GCTL0_I : in std_logic;
GRDY1_I : out std_logic;
GD_IO : inout std_logic_vector(7 downto 0);
FTP_O : out std_logic_vector(15 downto 0)
);
end S609;
end angie_bitstream;
architecture A_angie_bitstream of angie_bitstream is
----------------------------------------Fifo out (PC to devkit)
signal rst_o, clk_wr_o, clk_rd_o : std_logic;
signal write_en_o, read_en_o : std_logic;
signal data_in_o, data_out_o : std_logic_vector(7 downto 0);
signal empty_o, full_o : std_logic;
----------------------------------------Fifo in (devkit to PC)
signal rst_i, clk_wr_i, clk_rd_i : std_logic;
signal write_en_i, read_en_i : std_logic;
signal data_in_i, data_out_i : std_logic_vector(7 downto 0);
signal empty_i, full_i : std_logic;
signal wr_o, rd_i : std_logic;
----------------------------------------MAE
signal transit1, transit2 : std_logic;
----------------------------------------DFF
signal pa2_dff_clk, pa2_dff_rst, pa2_dff_d, pa2_dff_q : std_logic;
signal trst_clk, trst_rst, trst_d, trst_q : std_logic;
signal tms_clk, tms_rst, tms_d, tms_q : std_logic;
signal tdi_clk, tdi_rst, tdi_d, tdi_q : std_logic;
signal tdo_clk, tdo_rst, tdo_d, tdo_q : std_logic;
signal srst_clk, srst_rst, srst_d, srst_q : std_logic;
----------------------------------------clk_div
signal clk_div_in, clk_div_out, reset_clk_div : std_logic;
signal clk_div2_in, clk_div2_out, reset_clk_div2 : std_logic;
----------------------------------------MAE
type State_Type is (IDLE, WRITE_OUT, WRITE_IN, DELAY, READ_IN);
signal state, state2 : State_Type;
signal reset_mae, reset_mae2 : std_logic;
-- Add Component DFF
component DFF
Port (
clk : in std_logic;
reset : in std_logic;
d : in std_logic;
q : out std_logic
);
end component;
-- Add Component Clk_div
component clk_div
Port (
clk_in : in std_logic;
reset : in std_logic;
clk_out : out std_logic
);
end component;
-- Add component FIFO 64B
component fifo_generator_v9_3
PORT (
rst : IN STD_LOGIC;
wr_clk : IN STD_LOGIC;
rd_clk : IN STD_LOGIC;
din : IN STD_LOGIC_VECTOR(7 DOWNTO 0);
wr_en : IN STD_LOGIC;
rd_en : IN STD_LOGIC;
dout : OUT STD_LOGIC_VECTOR(7 DOWNTO 0);
full : OUT STD_LOGIC;
empty : OUT STD_LOGIC
);
end component;
signal state1_debug, state2_debug : std_logic;
architecture A_S609 of S609 is
begin
-------------------------------------------------------------I2C :
SDA_IO <= not(SO_SDA_IN_I) when (SDA_DIR_I = '1') else 'Z';
SO_SDA_OUT_O <= SDA_IO;
ST_5_O <= SDA_DIR_I;
--Directions:
ST_0 <= '0';
ST_1 <= '1';
SO_SCL_O <= SCL_I when (JPW_I = '1') else '0';
ST_4_O <= '0';
--TDO:
TDO <= not SI_TDO;
------------------------------------------------------------JTAG :
-- Instantiate the Clk div by 10
clk_div_inst : clk_div
port map (
clk_in => clk_div_in,
reset => reset_clk_div,
clk_out => clk_div_out
);
-- Instantiate the Clk div by 10
clk_div2_inst : clk_div
port map (
clk_in => clk_div2_in,
reset => reset_clk_div2,
clk_out => clk_div2_out
);
--TRST - TCK - TMS - TDI:
SO_TRST <= TRST;
SO_TMS <= TMS;
SO_TCK <= TCK;
SO_TDI <= TDI;
ST_2 <= SRST;
SO_SRST <= '0';
-- Instantiate DFFs
DFF_inst_PA2 : DFF
port map (
clk => pa2_dff_clk,
reset => pa2_dff_rst,
d => pa2_dff_d,
q => pa2_dff_q
);
SO_SCL <= SCL;
DFF_inst_TRST : DFF
port map (
clk => trst_clk,
reset => trst_rst,
d => trst_d,
q => trst_q
);
SDA <= not(SO_SDA_IN) when (SDA_DIR = '1') else 'Z';
SO_SDA_OUT <= SDA;
DFF_inst_TMS : DFF
port map (
clk => tms_clk,
reset => tms_rst,
d => tms_d,
q => tms_q
);
process(SDA_DIR)
begin
if(SDA_DIR = '0') then
ST_5 <= '0';
else
ST_5 <= '1';
end if;
end process;
DFF_inst_TDI : DFF
port map (
clk => tdi_clk,
reset => tdi_rst,
d => tdi_d,
q => tdi_q
);
process(SCL_DIR)
begin
if(SCL_DIR = '0') then
ST_4 <= '0';
else
ST_4 <= '1';
end if;
end process;
DFF_inst_TDO : DFF
port map (
clk => tdo_clk,
reset => tdo_rst,
d => tdo_d,
q => tdo_q
);
DFF_inst_SRST : DFF
port map (
clk => srst_clk,
reset => srst_rst,
d => srst_d,
q => srst_q
);
-- Instantiate the FIFO OUT
U0 : fifo_generator_v9_3
port map (
rst => rst_o,
wr_clk => clk_wr_o,
rd_clk => clk_rd_o,
din => data_in_o,
wr_en => write_en_o,
rd_en => read_en_o,
dout => data_out_o,
full => full_o,
empty => empty_o
);
-- Instantiate the FIFO IN
U1 : fifo_generator_v9_3
port map (
rst => rst_i,
wr_clk => clk_wr_i,
rd_clk => clk_rd_i,
din => data_in_i,
wr_en => write_en_i,
rd_en => read_en_i,
dout => data_out_i,
full => full_i,
empty => empty_i
);
--------------- clock dividers
clk_div_in <= IFCLK_I; -- 48Mhz
clk_div2_in <= clk_div_out; -- 24Mhz
--------------- DFFs
pa2_dff_clk <= IFCLK_I;
trst_clk <= IFCLK_I;
tms_clk <= IFCLK_I;
tdi_clk <= IFCLK_I;
tdo_clk <= IFCLK_I;
srst_clk <= IFCLK_I;
--------------- FIFOs
clk_wr_o <= IFCLK_I;
clk_rd_o <= clk_div2_out;
clk_wr_i <= clk_div2_out;
clk_rd_i <= IFCLK_I;
--------------------------- GPIF ready :
GRDY1_I <= '1';
-------------------------------PA2 DFF :
pa2_dff_rst <= '0';
pa2_dff_d <= PA2_I;
-------------------- FX2<->Fifo Enable pins :
write_en_o <= not(wr_o) and not(GCTL0_I);
read_en_i <= not(rd_i) and not(GCTL0_I);
---------------- FX2->Fifo Data :
data_in_o <= GD_IO;
------------ FIFO_OUT->Devkit :
SO_TRST_O <= trst_q;
trst_d <= data_out_o(4);
SO_TMS_O <= tms_q;
tms_d <= data_out_o(3);
SO_TDI_O <= tdi_q;
tdi_d <= data_out_o(1);
------------
SO_TCK_O <= data_out_o(0);
-------------------- FIFO_OUT->FIFO_IN :
--data_in_i <= data_out_o;
-------------------- FIFO_IN<-Devkit :
data_in_i(0) <= '0';
data_in_i(1) <= '0';
data_in_i(2) <= tdo_q;
tdo_d <= not SI_TDO_I;
data_in_i(3) <= '0';
data_in_i(4) <= '0';
data_in_i(5) <= '0';
data_in_i(6) <= '0';
data_in_i(7) <= '0';
-------------------- FX2<-FIFO_IN :
GD_IO <= data_out_i when (state = READ_IN) else "ZZZZZZZZ";
state1_debug <= '1' when state = READ_IN else '0';
state2_debug <= '1' when state2 = WRITE_IN else '0';
--Points de test:
FTP(0) <= SDA;
FTP(1) <= SCL;
FTP(2) <= not(SO_SDA_IN);
FTP(3) <= SDA_DIR;
FTP(5) <= SRST;
FTP(4) <= SI_TDO;
FTP(6) <= '1';
FTP(7) <= '1';
FTP_O(0) <= IFCLK_I;
FTP_O(1) <= GCTL0_I;
FTP_O(2) <= GD_IO(0);
FTP_O(3) <= GD_IO(1);
FTP_O(4) <= JPW_I;
FTP_O(5) <= PA2_I;
FTP_O(6) <= empty_o;
FTP_O(7) <= not SI_TDO_I;
end A_S609;
process(pa2_dff_d, pa2_dff_q)
begin
if pa2_dff_d = '0' and pa2_dff_q = '1' then
reset_mae <= '1'; -- Reset State Machine
reset_mae2 <= '1'; -- Reset State Machine
rst_o <= '1'; -- Reset OUT
rst_i <= '1'; -- Reset IN
reset_clk_div <= '1';
reset_clk_div2 <= '1';
trst_rst <= '1';
tms_rst <= '1';
tdi_rst <= '1';
tdo_rst <= '1';
srst_rst <= '1';
else
reset_mae <= '0'; -- No Reset State Machine
reset_mae2 <= '0'; -- Reset State Machine
rst_o <= '0'; -- No Reset OUT
rst_i <= '0'; -- No Reset IN
reset_clk_div <= '0';
reset_clk_div2 <= '0';
trst_rst <= '0';
tms_rst <= '0';
tdi_rst <= '0';
tdo_rst <= '0';
srst_rst <= '0';
end if;
end process;
process(clk_div2_out, reset_mae2)
begin
if reset_mae2 = '1' then
state2 <= IDLE;
elsif rising_edge(clk_div2_out) then
case state2 is
when IDLE =>
read_en_o <= '0'; -- Disable read OUT
write_en_i <= '0'; -- Disable write IN
transit2 <= '1';
if transit1 = '0' and PA2_I = '0' then
state2 <= WRITE_IN;
else
state2 <= IDLE;
end if;
when WRITE_IN =>
read_en_o <= '1'; -- Enable read OUT
write_en_i <= '1'; -- Enable write IN
if PA2_I = '1' then
state2 <= DELAY; -- Change state to DELAY
else
state2 <= WRITE_IN; -- Stay in WRITE_IN state
end if;
when DELAY =>
transit2 <= '0'; -- Enable READ IN
if empty_o = '1' then
read_en_o <= '0'; -- Disable read OUT
write_en_i <= '0'; -- Disable write IN
state2 <= IDLE; -- Change state to IDLE
else
state2 <= DELAY; -- Stay in READ_IN state
end if;
when others =>
state2 <= IDLE;
end case;
end if;
end process;
process(IFCLK_I, reset_mae)
begin
if reset_mae = '1' then
state <= IDLE;
elsif rising_edge(IFCLK_I) then
case state is
when IDLE =>
wr_o <= '1'; -- Disable write OUT
rd_i <= '1'; -- Disable read IN
transit1 <= '1';
if PA2_I = '0' then
state <= WRITE_OUT; -- Change state to RESET
else
state <= IDLE; -- Stay in IDLE state
end if;
when WRITE_OUT =>
wr_o <= '0'; -- Enable write OUT
if empty_o = '0' then
transit1 <= '0'; -- Enable Rd OUT & Wr IN
state <= DELAY; -- Change state to DELAY
else
state <= WRITE_OUT; -- Stay in WRITE_OUT state
end if;
when DELAY =>
if transit2 = '0' then
wr_o <= '1'; -- Disable write OUT
state <= READ_IN;
else
state <= DELAY;
end if;
when READ_IN =>
rd_i <= '0'; -- Enable read IN
if empty_i = '1' then
rd_i <= '1'; -- Enable read IN
state <= IDLE; -- Change state to IDLE
else
state <= READ_IN; -- Stay in READ_IN state
end if;
when others =>
state <= IDLE;
end case;
end if;
end process;
-- OUT signals direction
-- TRST, TMS, TCK and TDI : out
ST_0_O <= '0';
-- TDO : in
ST_1_O <= '1';
-- SRST : out
ST_2_O <= srst_q;
srst_d <= data_out_o(6);
SO_SRST_O <= '0';
-- MOD : in
ST_3_O <= '1';
end A_angie_bitstream;

View File

@@ -0,0 +1,33 @@
library ieee;
use ieee.std_logic_1164.ALL;
use ieee.numeric_std.ALL;
entity clk_div is
Port (
clk_in : in std_logic;
reset : in std_logic;
clk_out : out std_logic
);
end clk_div;
architecture behavioral of clk_div is
-- Division factor N = 4, so we need a 2-bit counter (2^2 = 4)
-- signal counter : unsigned(1 downto 0) := (others => '0');
signal tmp : std_logic;
begin
process(clk_in, reset)
begin
if reset = '1' then
-- counter <= (others => '0');
tmp <= '0';
elsif rising_edge(clk_in) then
-- if counter = (2**2 - 1) then
-- counter <= (others => '0');
tmp <= NOT tmp; -- Toggle the output clock
-- else
-- counter <= counter + 1;
-- end if;
end if;
end process;
clk_out <= tmp;
end behavioral;

View File

@@ -0,0 +1,23 @@
library ieee;
use ieee.std_logic_1164.ALL;
use ieee.std_logic_arith.ALL;
use ieee.std_logic_unsigned.ALL;
entity DFF is
port ( clk : in std_logic;
reset : in std_logic;
d : in std_logic;
q : out std_logic);
end DFF;
architecture Behavioral of DFF is
begin
process(clk, reset)
begin
if reset = '1' then
q <= '1'; -- Reset output to 0
elsif rising_edge(clk) then
q <= d; -- Capture D at the rising edge of the clock
end if;
end process;
end Behavioral;