From a0269f602d01032cc3da714f8e11fbfb2188b120 Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Mon, 27 Sep 2010 21:07:17 +0000 Subject: [PATCH] Add fjmem example for Spartan-6 devices git-svn-id: https://urjtag.svn.sourceforge.net/svnroot/urjtag/trunk@1853 b68d4a1b-bc3d-0410-92ed-d4ac073336b7 --- urjtag/ChangeLog | 3 + .../fjmem/fjmem_config_pack_spartan6-p.vhd | 82 +++++ urjtag/extra/fjmem/fjmem_spartan6.vhd | 320 ++++++++++++++++++ 3 files changed, 405 insertions(+) create mode 100644 urjtag/extra/fjmem/fjmem_config_pack_spartan6-p.vhd create mode 100644 urjtag/extra/fjmem/fjmem_spartan6.vhd diff --git a/urjtag/ChangeLog b/urjtag/ChangeLog index aa8751f6..1c67b41a 100644 --- a/urjtag/ChangeLog +++ b/urjtag/ChangeLog @@ -28,6 +28,9 @@ doc/Makefile.am, doc/README.pld, src/global/log-error.c, configure.ac: New Programmable Logic Devices (PLD) subsystem by Michael Walle. + * extra/fjmem/fjmem_config_pack_spartan6-p.vhd, extra/fjmem/fjmem_spartan6.vhd: + Add fjmem example for Spartan-6 devices. + 2010-08-30 Mike Frysinger * configure.ac: Clean up libusb detection to prefer 1.0 over 0.1, and accept diff --git a/urjtag/extra/fjmem/fjmem_config_pack_spartan6-p.vhd b/urjtag/extra/fjmem/fjmem_config_pack_spartan6-p.vhd new file mode 100644 index 00000000..1dd9ac66 --- /dev/null +++ b/urjtag/extra/fjmem/fjmem_config_pack_spartan6-p.vhd @@ -0,0 +1,82 @@ +------------------------------------------------------------------------------- +-- +-- $Id$ +-- +-- This program is free software; you can redistribute it and/or +-- modify it under the terms of the GNU General Public License +-- as published by the Free Software Foundation; either version 2 +-- of the License, or (at your option) any later version. +-- +-- This program is distributed in the hope that it will be useful, +-- but WITHOUT ANY WARRANTY; without even the implied warranty of +-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +-- GNU General Public License for more details. +-- +-- You should have received a copy of the GNU General Public License +-- along with this program; if not, write to the Free Software +-- Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +-- 02111-1307, USA. +-- +-- Written by Michael Walle , 2010. +-- Based on fjmem_config_pack_spartan3-p.vhd by Arnim Laeuger. +-- +------------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; + +package fjmem_config_pack is + + ----------------------------------------------------------------------------- + -- Specify the active levels of trst_i, shift_i and res_i + -- + constant trst_act_level_c : std_logic := '1'; + constant shift_act_level_c : std_logic := '1'; + constant res_act_level_c : std_logic := '1'; + -- + ----------------------------------------------------------------------------- + + + ----------------------------------------------------------------------------- + -- Adapt the number of used blocks and the number of bits that are + -- required for the block field (2 ** num_block_field_c >= num_blocks_c) + -- + -- number of used blocks + constant num_blocks_c : natural := 2; + -- number of bits for block field + constant num_block_field_c : natural := 1; + -- + ----------------------------------------------------------------------------- + + + ----------------------------------------------------------------------------- + -- Don't change the array type + -- + type block_desc_t is + record + addr_width : natural; + data_width : natural; + end record; + type block_array_t is array (natural range 0 to num_blocks_c-1) of block_desc_t; + -- + ----------------------------------------------------------------------------- + + + ----------------------------------------------------------------------------- + -- Fill in the array for all your used blocks + -- + constant blocks_c : block_array_t := + ((addr_width => 24, -- block #0, FLASH + data_width => 16), + (addr_width => 8, -- block #1, dummy + data_width => 8) + ); + -- + -- And specify the maximum address and data width + -- + constant max_addr_width_c : natural := 24; + constant max_data_width_c : natural := 16; + -- + ----------------------------------------------------------------------------- + +end; diff --git a/urjtag/extra/fjmem/fjmem_spartan6.vhd b/urjtag/extra/fjmem/fjmem_spartan6.vhd new file mode 100644 index 00000000..b857ee81 --- /dev/null +++ b/urjtag/extra/fjmem/fjmem_spartan6.vhd @@ -0,0 +1,320 @@ +------------------------------------------------------------------------------- +-- +-- $Id$ +-- +-- This program is free software; you can redistribute it and/or +-- modify it under the terms of the GNU General Public License +-- as published by the Free Software Foundation; either version 2 +-- of the License, or (at your option) any later version. +-- +-- This program is distributed in the hope that it will be useful, +-- but WITHOUT ANY WARRANTY; without even the implied warranty of +-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +-- GNU General Public License for more details. +-- +-- You should have received a copy of the GNU General Public License +-- along with this program; if not, write to the Free Software +-- Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +-- 02111-1307, USA. +-- +-- Written by Michael Walle , 2010. +-- Based on fjmem_spartan3.vhd by Arnim Laeuger. +-- +------------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; + +entity fjmem_spartan6 is + + port ( + -- Clock oscillator + osc1 : in std_logic; + + -- Flash Memory + fl_a : out std_logic_vector(23 downto 0); + fl_d : inout std_logic_vector(15 downto 0); + fl_ce_n : out std_logic; + fl_oe_n : out std_logic; + fl_we_n : out std_logic; + fl_rp_n : out std_logic; + fl_sts : in std_logic; + + led : out std_logic_vector(1 downto 0) + ); + +end fjmem_spartan6; + + +library ieee; +use ieee.numeric_std.all; + +use work.fjmem_config_pack.all; + +architecture struct of fjmem_spartan6 is + + component fjmem_core + port ( + clkdr_i : in std_logic; + trst_i : in std_logic; + shift_i : in std_logic; + update_i : in std_logic; + tdi_i : in std_logic; + tdo_o : out std_logic; + clk_i : in std_logic; + res_i : in std_logic; + strobe_o : out std_logic; + read_o : out std_logic; + write_o : out std_logic; + ack_i : in std_logic; + cs_o : out std_logic_vector(num_blocks_c-1 downto 0); + addr_o : out std_logic_vector(max_addr_width_c-1 downto 0); + din_i : in std_logic_vector(max_data_width_c-1 downto 0); + dout_o : out std_logic_vector(max_data_width_c-1 downto 0) + ); + end component; + + component BSCAN_SPARTAN6 + port ( + CAPTURE : out std_ulogic := 'H'; + DRCK : out std_ulogic := 'L'; + RESET : out std_ulogic := 'L'; + RUNTEST : out std_ulogic := 'L'; + SEL : out std_ulogic := 'L'; + SHIFT : out std_ulogic := 'L'; + TCK : out std_ulogic := 'L'; + TDI : out std_ulogic := 'L'; + TMS : out std_ulogic := 'L'; + UPDATE : out std_ulogic := 'L'; + TDO : in std_ulogic := 'X' + ); + end component; + + + signal tdi_s, + tdo_s : std_logic; + signal clkdr_s, + trst_s, + shift_s, + update_s : std_logic; + + signal addr_s : std_logic_vector(max_addr_width_c-1 downto 0); + signal din_s, + dout_s : std_logic_vector(max_data_width_c-1 downto 0); + + signal res_s : std_logic; + + signal read_s, + write_s, + strobe_s : std_logic; + signal cs_s : std_logic_vector(1 downto 0); + signal ack_q : std_logic; + + type state_t is (IDLE, + READ_WAIT, + WRITE_DRIVE, + WRITE_WAIT, + WRITE_FINISH); + signal state_q : state_t; + + signal cnt_q : unsigned(2 downto 0); + + signal fl_ce_n_q, + fl_oe_n_q, + fl_we_n_q, + fl_d_en_q : std_logic; + +begin + + res_s <= '0'; + + + bscan_spartan6_b : BSCAN_SPARTAN6 + port map ( + CAPTURE => open, + DRCK => clkdr_s, + RESET => open, --trst_s, + RUNTEST => open, + SEL => open, + SHIFT => shift_s, + TCK => open, + TDI => tdi_s, + TMS => open, + UPDATE => update_s, + TDO => tdo_s + ); + trst_s <= '0'; + + + fjmem_core_b : fjmem_core + port map ( + clkdr_i => clkdr_s, + trst_i => trst_s, + shift_i => shift_s, + update_i => update_s, + tdi_i => tdi_s, + tdo_o => tdo_s, + clk_i => osc1, + res_i => res_s, + strobe_o => strobe_s, + read_o => read_s, + write_o => write_s, + ack_i => ack_q, + cs_o => cs_s, + addr_o => addr_s, + din_i => din_s, + dout_o => dout_s + ); + + + ----------------------------------------------------------------------------- + -- Process mem_ctrl + -- + -- Purpose: + -- Handles access to external memory. + -- + mem_ctrl: process (res_s, osc1) + begin + if res_s = '1' then + -- Flash + fl_ce_n_q <= '1'; + fl_oe_n_q <= '1'; + fl_we_n_q <= '1'; + fl_d_en_q <= '0'; + + ack_q <= '0'; + + state_q <= IDLE; + cnt_q <= (others => '0'); + + elsif rising_edge(osc1) then + case state_q is + when IDLE => + if strobe_s = '1' then + if write_s = '1' then + state_q <= WRITE_DRIVE; + else + state_q <= READ_WAIT; + ack_q <= '1'; + end if; + + case cs_s is + -- Flash + when "01" => + fl_ce_n_q <= '0'; + if read_s = '1' then + fl_oe_n_q <= '0'; + -- start counter on read + cnt_q <= (others => '1'); + end if; + if write_s = '1' then + fl_d_en_q <= '1'; + end if; + + -- unimlemented / invalid + when others => + null; + + end case; + end if; + + when READ_WAIT => + if cnt_q = 0 then + state_q <= IDLE; + ack_q <= '0'; + + -- disable all memories + fl_ce_n_q <= '1'; + fl_oe_n_q <= '1'; + end if; + + when WRITE_DRIVE => + state_q <= WRITE_WAIT; + + -- output drivers are active during this state + -- thus we can activate the write impulse at the end + case cs_s is + when "01" => + fl_we_n_q <= '0'; + -- start counter + cnt_q <= (others => '1'); + when others => + null; + end case; + + when WRITE_WAIT => + if cnt_q = 0 then + state_q <= WRITE_FINISH; + ack_q <= '0'; + + -- disable write signals + fl_we_n_q <= '1'; + end if; + + when WRITE_FINISH => + state_q <= IDLE; + + -- disable output enables + fl_d_en_q <= '0'; + -- disable all memories + fl_ce_n_q <= '1'; + fl_oe_n_q <= '1'; + + when others => + state_q <= IDLE; + + end case; + + if cnt_q /= 0 then + cnt_q <= cnt_q - 1; + end if; + + end if; + end process mem_ctrl; + -- + ----------------------------------------------------------------------------- + + + ----------------------------------------------------------------------------- + -- Process read_mux + -- + -- Purpose: + -- Read multiplexer from memory to jop_core. + -- + read_mux: process (cs_s, fl_d) + variable din_v : std_logic_vector(din_s'range); + begin + din_v := (others => '0'); + + if cs_s(0) = '1' then + din_v := din_v or fl_d; + end if; + + din_s <= din_v; + end process read_mux; + -- + ----------------------------------------------------------------------------- + + + ----------------------------------------------------------------------------- + -- Pin defaults + ----------------------------------------------------------------------------- + -- Flash Memory ------------------------------------------------------------- + fl_addr: process (addr_s) + begin + -- fl_a <= (others => '0'); + fl_a(23 downto 0) <= addr_s; + end process fl_addr; + fl_d <= dout_s + when fl_d_en_q = '1' else + (others => 'Z'); + fl_ce_n <= fl_ce_n_q; + fl_oe_n <= fl_oe_n_q; + fl_we_n <= fl_we_n_q; + fl_rp_n <= '1'; + + -- LEDs + led(0) <= fl_we_n_q; + led(1) <= fl_oe_n_q; + +end struct;