new fpga firmware - sorry, only one blob
new features: - bit to swap I and Q (spectrum inversion) - make GPS PPS input usable as clock reference (PPS acts as clock gate for a counter) - change unused pins into GPIOs (input, output, etc. configuration via SPI register bank) - LED connected to FPGA can be switched on and off have a look at the updated register description ODF/PDF
This commit is contained in:
parent
1c329c8165
commit
83340d0b37
|
@ -1,5 +1,6 @@
|
|||
.\src\mt_toolbox\mt_toolbox.vhd
|
||||
.\src\mt_toolbox\mt_clktools.vhd
|
||||
.\src\mt_toolbox\mt_synctools.vhd
|
||||
.\src\mt_filter\mt_filter.vhd
|
||||
.\src\mt_filter\mt_fil_storage_slow.vhd
|
||||
.\src\mt_filter\mt_fil_mac_slow.vhd
|
||||
|
@ -11,6 +12,8 @@
|
|||
.\src\usbrx\datapath\usbrx_decimate.vhd
|
||||
.\src\usbrx\datapath\usbrx_ssc.vhd
|
||||
.\src\usbrx\toplevel\usbrx_clkgen.vhd
|
||||
.\src\usbrx\toplevel\usbrx_clkref.vhd
|
||||
.\src\usbrx\toplevel\usbrx_gpio.vhd
|
||||
.\src\usbrx\toplevel\usbrx_spi.vhd
|
||||
.\src\usbrx\toplevel\usbrx_regbank.vhd
|
||||
.\src\usbrx\toplevel\usbrx_pwm.vhd
|
||||
|
|
|
@ -44,3 +44,9 @@ Enabled=1
|
|||
LIB=
|
||||
Enabled=1
|
||||
VerilogLanguage=7
|
||||
[file:.\src\usbrx\toplevel\usbrx_clkref.vhd]
|
||||
Enabled=1
|
||||
[file:.\src\mt_toolbox\mt_synctools.vhd]
|
||||
Enabled=1
|
||||
[file:.\src\usbrx\toplevel\usbrx_gpio.vhd]
|
||||
Enabled=1
|
||||
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -54,15 +54,21 @@
|
|||
<Source name="../src/mt_toolbox/mt_clktools.vhd" type="VHDL" type_short="VHDL">
|
||||
<Options/>
|
||||
</Source>
|
||||
<Source name="../src/mt_toolbox/mt_synctools.vhd" type="VHDL" type_short="VHDL">
|
||||
<Options/>
|
||||
</Source>
|
||||
<Source name="../src/usbrx/toplevel/usbrx_clkref.vhd" type="VHDL" type_short="VHDL">
|
||||
<Options/>
|
||||
</Source>
|
||||
<Source name="../src/usbrx/toplevel/usbrx_gpio.vhd" type="VHDL" type_short="VHDL">
|
||||
<Options/>
|
||||
</Source>
|
||||
<Source name="../deploy/usbrx.xcf" type="ispVM Download Project" type_short="ispVM" excluded="TRUE">
|
||||
<Options/>
|
||||
</Source>
|
||||
<Source name="usbrx_vhdl.lpf" type="Logic Preference" type_short="LPF">
|
||||
<Options/>
|
||||
</Source>
|
||||
<Source name="usbrx_vhdl/usbrx_vhdl.xcf" type="ispVM Download Project" type_short="ispVM">
|
||||
<Options/>
|
||||
</Source>
|
||||
</Implementation>
|
||||
<Strategy name="Strategy1" file="Strategy1.sty"/>
|
||||
</BaliProject>
|
||||
|
|
|
@ -32,6 +32,7 @@ LOCATE COMP "gpio_6" SITE "A9" ;
|
|||
LOCATE COMP "gpio_7" SITE "A10" ;
|
||||
LOCATE COMP "gpio_8" SITE "A11" ;
|
||||
LOCATE COMP "gpio_9" SITE "A13" ;
|
||||
LOCATE COMP "led" SITE "M7" ;
|
||||
LOCATE COMP "vgnd_0" SITE "B3" ;
|
||||
LOCATE COMP "vgnd_1" SITE "C5" ;
|
||||
LOCATE COMP "vgnd_2" SITE "C8" ;
|
||||
|
@ -83,7 +84,7 @@ IOBUF PORT "tx_syn" IO_TYPE=LVCMOS33 DRIVE=4 ;
|
|||
IOBUF PORT "tx_dat" IO_TYPE=LVCMOS33 DRIVE=4 ;
|
||||
IOBUF PORT "gain0" IO_TYPE=LVCMOS33 DRIVE=4 ;
|
||||
IOBUF PORT "gain1" IO_TYPE=LVCMOS33 DRIVE=4 ;
|
||||
IOBUF PORT "gps_1pps" IO_TYPE=LVCMOS33 DRIVE=4 ;
|
||||
IOBUF PORT "gps_1pps" IO_TYPE=LVCMOS33 ;
|
||||
IOBUF PORT "gpio_0" IO_TYPE=LVCMOS33 DRIVE=4 ;
|
||||
IOBUF PORT "gpio_1" IO_TYPE=LVCMOS33 DRIVE=4 ;
|
||||
IOBUF PORT "gpio_2" IO_TYPE=LVCMOS33 DRIVE=4 ;
|
||||
|
@ -94,6 +95,7 @@ IOBUF PORT "gpio_6" IO_TYPE=LVCMOS33 DRIVE=4 ;
|
|||
IOBUF PORT "gpio_7" IO_TYPE=LVCMOS33 DRIVE=4 ;
|
||||
IOBUF PORT "gpio_8" IO_TYPE=LVCMOS33 DRIVE=4 ;
|
||||
IOBUF PORT "gpio_9" IO_TYPE=LVCMOS33 DRIVE=4 ;
|
||||
IOBUF PORT "led" IO_TYPE=LVCMOS33 DRIVE=4 ;
|
||||
IOBUF PORT "vgnd_0" IO_TYPE=LVCMOS33 DRIVE=4 ;
|
||||
IOBUF PORT "vgnd_1" IO_TYPE=LVCMOS33 DRIVE=4 ;
|
||||
IOBUF PORT "vgnd_2" IO_TYPE=LVCMOS33 DRIVE=4 ;
|
||||
|
|
|
@ -35,12 +35,7 @@ entity mt_reset_gen is
|
|||
ext_rst : in std_logic; -- external reset
|
||||
pll_locked : in std_logic; -- PLLs locked?
|
||||
reset_pll : out std_logic; -- reset signal for PLLs
|
||||
reset_sys : out std_logic; -- global reset signal
|
||||
|
||||
-- debug
|
||||
dbg_ext : out std_logic;
|
||||
dbg_rst : out std_logic;
|
||||
dbg_lock : out std_logic
|
||||
reset_sys : out std_logic -- global reset signal
|
||||
);
|
||||
end mt_reset_gen;
|
||||
|
||||
|
@ -112,11 +107,6 @@ begin
|
|||
|
||||
-- output PLL-reset
|
||||
reset_pll <= reset_pll_i;
|
||||
|
||||
-- debug
|
||||
dbg_ext <= ext_rst;
|
||||
dbg_rst <= reset_pll_i;
|
||||
dbg_lock <= pll_locked;
|
||||
end;
|
||||
|
||||
|
||||
|
|
|
@ -0,0 +1,135 @@
|
|||
-----------------------------------------------------------------------------------
|
||||
-- Filename : mt_synctools.vhd
|
||||
-- Project : maintech IP-Core toolbox
|
||||
-- Purpose : Basic tools for clock-domain-crossings
|
||||
--
|
||||
-----------------------------------------------------------------------------------
|
||||
|
||||
-----------------------------------------------------------------------------------
|
||||
-- Copyright (C) 2012 maintech GmbH, Otto-Hahn-Str. 15, 97204 Hoechberg, Germany --
|
||||
-- written by Matthias Kleffel --
|
||||
-- --
|
||||
-- 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 as version 3 of the License, or --
|
||||
-- --
|
||||
-- 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 V3 for more details. --
|
||||
-- --
|
||||
-- You should have received a copy of the GNU General Public License --
|
||||
-- along with this program. If not, see <http://www.gnu.org/licenses/>. --
|
||||
-----------------------------------------------------------------------------------
|
||||
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
-- mt_sync_dualff (dual flip-flop synchronizer) -------------------------------
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
library work;
|
||||
use work.mt_toolbox.all;
|
||||
|
||||
entity mt_sync_dualff is
|
||||
port(
|
||||
-- input
|
||||
i_data : in std_logic;
|
||||
|
||||
-- output
|
||||
o_clk : in std_logic;
|
||||
o_data : out std_logic
|
||||
);
|
||||
end mt_sync_dualff;
|
||||
|
||||
architecture rtl of mt_sync_dualff is
|
||||
-- signals
|
||||
signal sreg : std_logic := '0';
|
||||
signal oreg : std_logic := '0';
|
||||
|
||||
-- no SRL16s here...
|
||||
attribute shreg_extract of sreg : signal is "no";
|
||||
attribute shreg_extract of oreg : signal is "no";
|
||||
|
||||
begin
|
||||
process(o_clk)
|
||||
begin
|
||||
if rising_edge(o_clk) then
|
||||
sreg <= i_data;
|
||||
oreg <= sreg;
|
||||
end if;
|
||||
end process;
|
||||
o_data <= oreg;
|
||||
end rtl;
|
||||
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
-- mt_sync_feedback (feedback synchronizer) -----------------------------------
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
library work;
|
||||
use work.mt_toolbox.all;
|
||||
|
||||
entity mt_sync_feedback is
|
||||
port(
|
||||
-- input
|
||||
i_clk : in std_logic;
|
||||
i_data : in std_logic;
|
||||
|
||||
-- output
|
||||
o_clk : in std_logic;
|
||||
o_data : out std_logic
|
||||
);
|
||||
end mt_sync_feedback;
|
||||
|
||||
architecture rtl of mt_sync_feedback is
|
||||
|
||||
signal flip_i : std_logic := '0';
|
||||
signal flip_s1 : std_logic := '0';
|
||||
signal flip_s2 : std_logic := '0';
|
||||
signal flip_s3 : std_logic := '0';
|
||||
signal oreg : std_logic := '0';
|
||||
|
||||
attribute syn_keep of flip_i : signal is true;
|
||||
attribute syn_keep of flip_s1 : signal is true;
|
||||
attribute syn_keep of flip_s2 : signal is true;
|
||||
attribute syn_keep of flip_s3 : signal is true;
|
||||
attribute syn_keep of oreg : signal is true;
|
||||
|
||||
begin
|
||||
|
||||
process(i_clk)
|
||||
begin
|
||||
if rising_edge(i_clk) then
|
||||
-- update flip-bit on request
|
||||
if i_data='1' then
|
||||
flip_i <= not flip_i;
|
||||
end if;
|
||||
|
||||
-- debug check
|
||||
assert not (i_data='1' and flip_s1/=flip_i)
|
||||
report "mt_sync_feedback: pulses too close, failed to synchronize"
|
||||
severity failure;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
process(o_clk)
|
||||
begin
|
||||
if rising_edge(o_clk) then
|
||||
-- synchronize flip-bit
|
||||
flip_s1 <= flip_i;
|
||||
flip_s2 <= flip_s1;
|
||||
flip_s3 <= flip_s2;
|
||||
|
||||
-- create output-request
|
||||
oreg <= flip_s3 xor flip_s2;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
-- set output
|
||||
o_data <= oreg;
|
||||
|
||||
end rtl;
|
|
@ -72,9 +72,10 @@ package mt_toolbox is
|
|||
--
|
||||
-- common attributes
|
||||
--
|
||||
attribute syn_keep : boolean;
|
||||
attribute syn_ramstyle : string;
|
||||
attribute syn_romstyle : string;
|
||||
attribute syn_keep : boolean;
|
||||
attribute syn_ramstyle : string;
|
||||
attribute syn_romstyle : string;
|
||||
attribute shreg_extract : string;
|
||||
|
||||
end mt_toolbox;
|
||||
|
||||
|
|
|
@ -95,12 +95,32 @@ begin
|
|||
tx_dat <= '0';
|
||||
|
||||
-- GPS
|
||||
gps_1pps <= '0';
|
||||
-- gps_1pps <= '0';
|
||||
gps_10k <= '0';
|
||||
|
||||
-- gpios
|
||||
gpio <= (others=>'H');
|
||||
|
||||
-- generate pps signal
|
||||
-- (set every millisecond instead of every second
|
||||
-- to speed to simulation time)
|
||||
process
|
||||
variable cnt : natural;
|
||||
begin
|
||||
gps_1pps <= '0';
|
||||
|
||||
cnt := 1;
|
||||
loop
|
||||
wait for (cnt * 1 ms) - now;
|
||||
gps_1pps <= '1';
|
||||
wait for 1us;
|
||||
gps_1pps <= '0';
|
||||
cnt := cnt+1;
|
||||
end loop;
|
||||
|
||||
wait;
|
||||
end process;
|
||||
|
||||
-- dummy ADC model
|
||||
process
|
||||
-- constant word1 : unsigned(15 downto 0) := "0010000000000001";
|
||||
|
|
|
@ -54,25 +54,33 @@ architecture rtl of usbrx_offset is
|
|||
|
||||
-- clip & saturate sample
|
||||
function doClipValue(x : signed) return signed is
|
||||
variable xnorm : signed(x'length-1 downto 0) := x;
|
||||
begin
|
||||
if x >= 32768 then
|
||||
if xnorm >= 32768 then
|
||||
-- overflow
|
||||
return to_signed(+32767,16);
|
||||
elsif x < -32768 then
|
||||
elsif xnorm < -32768 then
|
||||
-- underflow
|
||||
return to_signed(-32768,16);
|
||||
else
|
||||
-- in range
|
||||
return x(15 downto 0);
|
||||
return xnorm(15 downto 0);
|
||||
end if;
|
||||
end doClipValue;
|
||||
|
||||
-- multiplier input
|
||||
signal mula_i, mula_q : signed(17 downto 0) := (others=>'0');
|
||||
signal mulb_i, mulb_q : signed(17 downto 0) := (others=>'0');
|
||||
|
||||
-- multiplier output
|
||||
signal mout_i, mout_q : signed(18 downto 0) := (others=>'0');
|
||||
|
||||
begin
|
||||
|
||||
-- control logic
|
||||
process(clk)
|
||||
variable s16i, s16q : signed(15 downto 0);
|
||||
variable s17i, s17q : signed(16 downto 0);
|
||||
variable mtmp_i, mtmp_q : signed(35 downto 0);
|
||||
variable atmp_i, atmp_q : signed(19 downto 0);
|
||||
begin
|
||||
if rising_edge(clk) then
|
||||
-- passthough clock
|
||||
|
@ -80,17 +88,30 @@ begin
|
|||
|
||||
-- handle data
|
||||
if in_clk='1' then
|
||||
-- convert input into 16bit signed
|
||||
s16i := signed(in_i xor "10000000000000") & "00";
|
||||
s16q := signed(in_q xor "10000000000000") & "00";
|
||||
-- apply swap-flag & convert input into 18bit signed
|
||||
if config.swap='0' then
|
||||
mula_i <= signed(in_i xor "10000000000000") & "0000";
|
||||
mula_q <= signed(in_q xor "10000000000000") & "0000";
|
||||
else
|
||||
mula_i <= signed(in_q xor "10000000000000") & "0000";
|
||||
mula_q <= signed(in_i xor "10000000000000") & "0000";
|
||||
end if;
|
||||
|
||||
-- add offset
|
||||
s17i := resize(s16i,17) + resize(config.ioff,17);
|
||||
s17q := resize(s16q,17) + resize(config.qoff,17);
|
||||
-- apply gain
|
||||
mulb_i <= signed("00" & config.igain);
|
||||
mulb_q <= signed("00" & config.qgain);
|
||||
mtmp_i := mula_i * mulb_i;
|
||||
mtmp_q := mula_q * mulb_q;
|
||||
mout_i <= mtmp_i(34 downto 16);
|
||||
mout_q <= mtmp_q(34 downto 16);
|
||||
|
||||
-- add offset (also adds 0.5 for rounding of multiplier-output)
|
||||
atmp_i := resize(mout_i,20) + resize(config.ioff&"1",20);
|
||||
atmp_q := resize(mout_q,20) + resize(config.qoff&"1",20);
|
||||
|
||||
-- clip output
|
||||
out_i <= doClipValue(s17i);
|
||||
out_q <= doClipValue(s17q);
|
||||
out_i <= doClipValue(atmp_i(19 downto 1));
|
||||
out_q <= doClipValue(atmp_q(19 downto 1));
|
||||
end if;
|
||||
|
||||
-- handle reset
|
||||
|
|
|
@ -42,12 +42,7 @@ entity usbrx_clkgen is
|
|||
clk_30 : out std_logic; -- 30MHz clock
|
||||
clk_80 : out std_logic; -- 80MHz clock
|
||||
rst_30 : out std_logic; -- 30MHz reset
|
||||
rst_80 : out std_logic; -- 80MHz reset
|
||||
|
||||
-- debug
|
||||
dbg_ext : out std_logic;
|
||||
dbg_rst : out std_logic;
|
||||
dbg_lock : out std_logic
|
||||
rst_80 : out std_logic -- 80MHz reset
|
||||
);
|
||||
end usbrx_clkgen;
|
||||
|
||||
|
@ -94,13 +89,7 @@ begin
|
|||
ext_rst => ext_rst,
|
||||
pll_locked => pll_locked,
|
||||
reset_pll => rst_pll,
|
||||
reset_sys => reset_i,
|
||||
|
||||
|
||||
-- debug
|
||||
dbg_ext => dbg_ext,
|
||||
dbg_rst => dbg_rst,
|
||||
dbg_lock => dbg_lock
|
||||
reset_sys => reset_i
|
||||
);
|
||||
|
||||
-- sync reset to clock-domains
|
||||
|
|
|
@ -0,0 +1,158 @@
|
|||
---------------------------------------------------------------------------------------------------
|
||||
-- Filename : usbrx_clkref.vhd
|
||||
-- Project : OsmoSDR FPGA Firmware
|
||||
-- Purpose : Reference Clock Measurement
|
||||
---------------------------------------------------------------------------------------------------
|
||||
|
||||
-----------------------------------------------------------------------------------
|
||||
-- Copyright (C) 2012 maintech GmbH, Otto-Hahn-Str. 15, 97204 Hoechberg, Germany --
|
||||
-- written by Matthias Kleffel --
|
||||
-- --
|
||||
-- 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 as version 3 of the License, or --
|
||||
-- --
|
||||
-- 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 V3 for more details. --
|
||||
-- --
|
||||
-- You should have received a copy of the GNU General Public License --
|
||||
-- along with this program. If not, see <http://www.gnu.org/licenses/>. --
|
||||
-----------------------------------------------------------------------------------
|
||||
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
use ieee.numeric_std.all;
|
||||
library work;
|
||||
use work.all;
|
||||
use work.mt_toolbox.all;
|
||||
use work.usbrx.all;
|
||||
|
||||
entity usbrx_clkref is
|
||||
port(
|
||||
-- system clocks
|
||||
clk_sys : in std_logic;
|
||||
rst_sys : in std_logic;
|
||||
|
||||
-- reference signal
|
||||
clk_ref : in std_logic;
|
||||
rst_ref : in std_logic;
|
||||
|
||||
-- 1pps signal
|
||||
gps_1pps : in std_logic;
|
||||
|
||||
-- status
|
||||
status : out usbrx_ref_status_t
|
||||
);
|
||||
end usbrx_clkref;
|
||||
|
||||
architecture rtl of usbrx_clkref is
|
||||
|
||||
-- deglitcher
|
||||
signal dgl_hist : std_logic_vector(3 downto 0);
|
||||
signal dgl_out : std_logic;
|
||||
|
||||
-- edge detection
|
||||
signal pps_last : std_logic;
|
||||
|
||||
-- active counters
|
||||
signal cnt_lsb : unsigned(24 downto 0);
|
||||
|
||||
-- latched counters
|
||||
signal lat_upd : std_logic;
|
||||
signal lat_lsb : unsigned(24 downto 0);
|
||||
signal lat_msb : unsigned(6 downto 0);
|
||||
|
||||
-- output register
|
||||
signal out_upd : std_logic;
|
||||
signal out_lsb : unsigned(24 downto 0);
|
||||
signal out_msb : unsigned(6 downto 0);
|
||||
|
||||
begin
|
||||
|
||||
-- reference counter
|
||||
process(clk_ref)
|
||||
variable cnt0,cnt1 : natural range 0 to 4;
|
||||
variable re : boolean;
|
||||
begin
|
||||
if rising_edge(clk_ref) then
|
||||
-- set default values
|
||||
lat_upd <= '0';
|
||||
|
||||
-- deglitch pps signal
|
||||
dgl_hist <= dgl_hist(dgl_hist'left-1 downto 0) & gps_1pps;
|
||||
cnt0 := 0;
|
||||
cnt1 := 0;
|
||||
for i in dgl_hist'range loop
|
||||
if dgl_hist(i)='0' then
|
||||
cnt0 := cnt0 + 1;
|
||||
end if;
|
||||
if dgl_hist(i)='1' then
|
||||
cnt1 := cnt1 + 1;
|
||||
end if;
|
||||
end loop;
|
||||
if cnt0 >= 3 then
|
||||
dgl_out <= '0';
|
||||
elsif cnt1 >= 3 then
|
||||
dgl_out <= '1';
|
||||
end if;
|
||||
|
||||
-- detect rising edge on pps
|
||||
pps_last <= dgl_out;
|
||||
re := (dgl_out='1' and pps_last='0');
|
||||
|
||||
-- update counters
|
||||
if re then
|
||||
cnt_lsb <= to_unsigned(0, cnt_lsb'length);
|
||||
lat_lsb <= cnt_lsb;
|
||||
lat_msb <= lat_msb + 1;
|
||||
lat_upd <= '1';
|
||||
else
|
||||
cnt_lsb <= cnt_lsb + 1;
|
||||
end if;
|
||||
|
||||
-- handle reset
|
||||
if rst_ref='1' then
|
||||
dgl_hist <= (others=>'0');
|
||||
dgl_out <= '0';
|
||||
pps_last <= '0';
|
||||
cnt_lsb <= (others=>'0');
|
||||
lat_upd <= '0';
|
||||
lat_lsb <= (others=>'0');
|
||||
lat_msb <= (others=>'0');
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
-- bring update-pulse into correct clock domain
|
||||
syn: entity mt_sync_feedback
|
||||
port map (
|
||||
i_clk => clk_ref,
|
||||
i_data => lat_upd,
|
||||
o_clk => clk_sys,
|
||||
o_data => out_upd
|
||||
);
|
||||
|
||||
-- output register
|
||||
process(clk_sys)
|
||||
begin
|
||||
if rising_edge(clk_sys) then
|
||||
-- update output when requested
|
||||
if out_upd='1' then
|
||||
out_lsb <= lat_lsb;
|
||||
out_msb <= lat_msb;
|
||||
end if;
|
||||
|
||||
-- handle reset
|
||||
if rst_sys='1' then
|
||||
out_lsb <= (others=>'0');
|
||||
out_msb <= (others=>'0');
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
-- output status
|
||||
status.lsb <= out_lsb;
|
||||
status.msb <= out_msb;
|
||||
end rtl;
|
|
@ -0,0 +1,72 @@
|
|||
---------------------------------------------------------------------------------------------------
|
||||
-- Filename : usbrx_gpio.vhd
|
||||
-- Project : OsmoSDR FPGA Firmware
|
||||
-- Purpose : GPIO Block
|
||||
---------------------------------------------------------------------------------------------------
|
||||
|
||||
-----------------------------------------------------------------------------------
|
||||
-- Copyright (C) 2012 maintech GmbH, Otto-Hahn-Str. 15, 97204 Hoechberg, Germany --
|
||||
-- written by Matthias Kleffel --
|
||||
-- --
|
||||
-- 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 as version 3 of the License, or --
|
||||
-- --
|
||||
-- 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 V3 for more details. --
|
||||
-- --
|
||||
-- You should have received a copy of the GNU General Public License --
|
||||
-- along with this program. If not, see <http://www.gnu.org/licenses/>. --
|
||||
-----------------------------------------------------------------------------------
|
||||
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
use ieee.numeric_std.all;
|
||||
library work;
|
||||
use work.all;
|
||||
use work.mt_toolbox.all;
|
||||
use work.usbrx.all;
|
||||
|
||||
entity usbrx_gpio is
|
||||
port(
|
||||
-- common
|
||||
clk : in std_logic;
|
||||
reset : in std_logic;
|
||||
|
||||
-- GPIOs
|
||||
gpio : inout std_logic_vector(10 downto 0);
|
||||
|
||||
-- config / status
|
||||
config : in usbrx_gpio_config_t;
|
||||
status : out usbrx_gpio_status_t
|
||||
);
|
||||
end usbrx_gpio;
|
||||
|
||||
architecture rtl of usbrx_gpio is
|
||||
|
||||
-- register
|
||||
signal ireg : std_logic_vector(10 downto 0) := (others=>'0');
|
||||
signal oreg : std_logic_vector(10 downto 0) := (others=>'0');
|
||||
signal oena : std_logic_vector(10 downto 0) := (others=>'0');
|
||||
|
||||
begin
|
||||
|
||||
-- create output-driver
|
||||
od: for i in gpio'range generate
|
||||
begin
|
||||
gpio(i) <= oreg(i) when oena(i)='1' else 'Z';
|
||||
end generate;
|
||||
|
||||
-- IOBs
|
||||
process(clk)
|
||||
begin
|
||||
if rising_edge(clk) then
|
||||
ireg <= to_X01(gpio);
|
||||
oreg <= config.odata;
|
||||
oena <= config.oena;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
end rtl;
|
|
@ -37,15 +37,16 @@ entity usbrx_regbank is
|
|||
|
||||
-- config
|
||||
cfg_pwm : out usbrx_pwm_config_t;
|
||||
cfg_gpio : out usbrx_gpio_config_t;
|
||||
cfg_adc : out usbrx_adc_config_t;
|
||||
cfg_ssc : out usbrx_ssc_config_t;
|
||||
cfg_fil : out usbrx_fil_config_t;
|
||||
cfg_off : out usbrx_off_config_t;
|
||||
|
||||
-- status (TODO HACK)
|
||||
adc_i : in unsigned(13 downto 0);
|
||||
adc_q : in unsigned(13 downto 0);
|
||||
|
||||
-- status
|
||||
stat_ref : in usbrx_ref_status_t;
|
||||
stat_gpio : in usbrx_gpio_status_t;
|
||||
|
||||
-- SPI interface
|
||||
spi_ncs : in std_logic;
|
||||
spi_sclk : in std_logic;
|
||||
|
@ -71,6 +72,10 @@ architecture rtl of usbrx_regbank is
|
|||
signal reg_ssc2 : std_logic_vector(7 downto 0);
|
||||
signal reg_fil : std_logic_vector(2 downto 0);
|
||||
signal reg_off : std_logic_vector(31 downto 0);
|
||||
signal reg_gain : std_logic_vector(31 downto 0);
|
||||
signal reg_swap : std_logic_vector(0 downto 0);
|
||||
signal reg_ioe : std_logic_vector(10 downto 0);
|
||||
signal reg_iod : std_logic_vector(10 downto 0);
|
||||
|
||||
-- avoid block-ram inference
|
||||
attribute syn_romstyle : string;
|
||||
|
@ -111,6 +116,10 @@ begin
|
|||
reg_ssc2 <= x"01";
|
||||
reg_fil <= "011";
|
||||
reg_off <= x"00000000";
|
||||
reg_gain <= x"80008000";
|
||||
reg_swap <= "0";
|
||||
reg_ioe <= "00000000000";
|
||||
reg_iod <= "00000000000";
|
||||
elsif rising_edge(clk) then
|
||||
-- output zeros by default
|
||||
bus_rdata <= (others=>'0');
|
||||
|
@ -152,9 +161,8 @@ begin
|
|||
end if;
|
||||
|
||||
when 5 =>
|
||||
-- ADC Quickhack
|
||||
bus_rdata(15 downto 0) <= to_slv16(adc_i);
|
||||
bus_rdata(31 downto 16) <= to_slv16(adc_q);
|
||||
-- <unused>
|
||||
null;
|
||||
|
||||
when 6 =>
|
||||
-- decimation filter
|
||||
|
@ -164,11 +172,44 @@ begin
|
|||
end if;
|
||||
|
||||
when 7 =>
|
||||
-- offset stage
|
||||
-- sample offset
|
||||
bus_rdata <= reg_off;
|
||||
if bus_wena='1' then
|
||||
reg_off <= bus_wdata(31 downto 0);
|
||||
end if;
|
||||
when 8 =>
|
||||
-- sample gain
|
||||
bus_rdata <= reg_gain;
|
||||
if bus_wena='1' then
|
||||
reg_gain <= bus_wdata(31 downto 0);
|
||||
end if;
|
||||
when 9 =>
|
||||
-- sample swap
|
||||
bus_rdata(0 downto 0) <= reg_swap;
|
||||
if bus_wena='1' then
|
||||
reg_swap <= bus_wdata( 0 downto 0);
|
||||
end if;
|
||||
|
||||
when 10 =>
|
||||
-- GPIO - output enable
|
||||
bus_rdata(10 downto 0) <= reg_ioe;
|
||||
if bus_wena='1' then
|
||||
reg_ioe <= bus_wdata(10 downto 0);
|
||||
end if;
|
||||
when 11 =>
|
||||
-- GPIO - output data
|
||||
bus_rdata(10 downto 0) <= reg_iod;
|
||||
if bus_wena='1' then
|
||||
reg_iod <= bus_wdata(10 downto 0);
|
||||
end if;
|
||||
when 12 =>
|
||||
-- GPIO - input data
|
||||
bus_rdata(10 downto 0) <= stat_gpio.idata;
|
||||
|
||||
when 13 =>
|
||||
-- reference frequency
|
||||
bus_rdata(24 downto 0) <= std_logic_vector(stat_ref.lsb);
|
||||
bus_rdata(31 downto 25) <= std_logic_vector(stat_ref.msb);
|
||||
|
||||
when others =>
|
||||
-- invalid address
|
||||
|
@ -190,5 +231,10 @@ begin
|
|||
cfg_fil.decim <= unsigned(reg_fil);
|
||||
cfg_off.ioff <= signed(reg_off(15 downto 0));
|
||||
cfg_off.qoff <= signed(reg_off(31 downto 16));
|
||||
cfg_off.igain <= unsigned(reg_gain(15 downto 0));
|
||||
cfg_off.qgain <= unsigned(reg_gain(31 downto 16));
|
||||
cfg_off.swap <= reg_swap(0);
|
||||
cfg_gpio.oena <= reg_ioe;
|
||||
cfg_gpio.odata <= reg_iod;
|
||||
|
||||
end rtl;
|
||||
|
|
|
@ -71,6 +71,7 @@ entity usbrx_toplevel is
|
|||
gps_10k : in std_logic;
|
||||
|
||||
-- gpios
|
||||
led : inout std_logic;
|
||||
gpio : inout std_logic_vector(9 downto 0);
|
||||
|
||||
-- virtual GNDs/VCCs
|
||||
|
@ -89,11 +90,16 @@ architecture rtl of usbrx_toplevel is
|
|||
signal rst_80 : std_logic;
|
||||
|
||||
-- config
|
||||
signal cfg_pwm : usbrx_pwm_config_t;
|
||||
signal cfg_adc : usbrx_adc_config_t;
|
||||
signal cfg_ssc : usbrx_ssc_config_t;
|
||||
signal cfg_fil : usbrx_fil_config_t;
|
||||
signal cfg_off : usbrx_off_config_t;
|
||||
signal cfg_pwm : usbrx_pwm_config_t;
|
||||
signal cfg_gpio : usbrx_gpio_config_t;
|
||||
signal cfg_adc : usbrx_adc_config_t;
|
||||
signal cfg_ssc : usbrx_ssc_config_t;
|
||||
signal cfg_fil : usbrx_fil_config_t;
|
||||
signal cfg_off : usbrx_off_config_t;
|
||||
|
||||
-- status
|
||||
signal stat_ref : usbrx_ref_status_t;
|
||||
signal stat_gpio : usbrx_gpio_status_t;
|
||||
|
||||
-- ADC <-> offset
|
||||
signal adc_off_clk : std_logic;
|
||||
|
@ -110,22 +116,9 @@ architecture rtl of usbrx_toplevel is
|
|||
signal fil_out_i : signed(15 downto 0);
|
||||
signal fil_out_q : signed(15 downto 0);
|
||||
|
||||
-- blinken lights
|
||||
signal blcnt1 : unsigned(31 downto 0) := x"00000000";
|
||||
signal blcnt2 : unsigned(31 downto 0) := x"00000000";
|
||||
signal blcnt3 : unsigned(31 downto 0) := x"00000000";
|
||||
signal blink1 : std_logic := '0';
|
||||
signal blink2 : std_logic := '0';
|
||||
signal blink3 : std_logic := '0';
|
||||
|
||||
-- enusure that signal-names are kept (important for timing contraints)
|
||||
attribute syn_keep of clk_in_pclk : signal is true;
|
||||
|
||||
-- debug
|
||||
signal dbg_ext : std_logic;
|
||||
signal dbg_rst : std_logic;
|
||||
signal dbg_lock : std_logic;
|
||||
|
||||
begin
|
||||
|
||||
-- house-keeping
|
||||
|
@ -139,12 +132,7 @@ begin
|
|||
clk_30 => clk_30,
|
||||
clk_80 => clk_80,
|
||||
rst_30 => rst_30,
|
||||
rst_80 => rst_80,
|
||||
|
||||
-- debug
|
||||
dbg_ext => dbg_ext,
|
||||
dbg_rst => dbg_rst,
|
||||
dbg_lock => dbg_lock
|
||||
rst_80 => rst_80
|
||||
);
|
||||
|
||||
-- register bank
|
||||
|
@ -160,18 +148,53 @@ begin
|
|||
cfg_ssc => cfg_ssc,
|
||||
cfg_fil => cfg_fil,
|
||||
cfg_off => cfg_off,
|
||||
|
||||
-- status (TODO HACK)
|
||||
adc_i => adc_off_i,
|
||||
adc_q => adc_off_q,
|
||||
cfg_gpio => cfg_gpio,
|
||||
|
||||
-- status
|
||||
stat_ref => stat_ref,
|
||||
stat_gpio => stat_gpio,
|
||||
|
||||
-- SPI interface
|
||||
spi_ncs => ctl_cs,
|
||||
spi_sclk => ctl_sck,
|
||||
spi_mosi => ctl_mosi,
|
||||
spi_miso => ctl_miso
|
||||
);
|
||||
|
||||
|
||||
-- reference clock measurement
|
||||
refclk: entity usbrx_clkref
|
||||
port map (
|
||||
-- system clocks
|
||||
clk_sys => clk_80,
|
||||
rst_sys => rst_80,
|
||||
|
||||
-- reference signal
|
||||
clk_ref => clk_30,
|
||||
rst_ref => rst_30,
|
||||
|
||||
-- 1pps signal
|
||||
gps_1pps => gps_1pps,
|
||||
|
||||
-- status
|
||||
status => stat_ref
|
||||
);
|
||||
|
||||
-- GPIOs
|
||||
io: entity usbrx_gpio
|
||||
port map (
|
||||
-- common
|
||||
clk => clk_80,
|
||||
reset => rst_80,
|
||||
|
||||
-- GPIOs
|
||||
gpio(9 downto 0) => gpio,
|
||||
gpio(10) => led,
|
||||
|
||||
-- config / status
|
||||
config => cfg_gpio,
|
||||
status => stat_gpio
|
||||
);
|
||||
|
||||
-- gain PWMs
|
||||
pwm: entity usbrx_pwm
|
||||
port map (
|
||||
|
@ -273,53 +296,8 @@ begin
|
|||
ssc_dat => rx_dat
|
||||
);
|
||||
|
||||
-- TODO
|
||||
-- drive unused IOs
|
||||
ctl_int <= '1';
|
||||
-- tx_clk <= '0';
|
||||
|
||||
-- blinken lights
|
||||
process(clk_in_pclk)
|
||||
begin
|
||||
if rising_edge(clk_in_pclk) then
|
||||
if blcnt1=0 then
|
||||
blcnt1 <= to_unsigned(30000000/2-1, 32);
|
||||
blink1 <= not blink1;
|
||||
else
|
||||
blcnt1 <= blcnt1-1;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
process(clk_30)
|
||||
begin
|
||||
if rising_edge(clk_30) then
|
||||
if rst_30='1' then
|
||||
blcnt2 <= (others=>'0');
|
||||
blink2 <= '0';
|
||||
elsif blcnt2=0 then
|
||||
blcnt2 <= to_unsigned(30000000/2-1, 32);
|
||||
blink2 <= not blink2;
|
||||
else
|
||||
blcnt2 <= blcnt2-1;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
process(clk_80)
|
||||
begin
|
||||
if rising_edge(clk_80) then
|
||||
if rst_80='1' then
|
||||
blcnt3 <= (others=>'0');
|
||||
blink3 <= '0';
|
||||
elsif blcnt3=0 then
|
||||
blcnt3 <= to_unsigned(80000000/2-1, 32);
|
||||
blink3 <= not blink3;
|
||||
else
|
||||
blcnt3 <= blcnt3-1;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
-- 8 7 6 5 4 3 2 1
|
||||
gpio <= "00" & clk_80 & clk_30 & dbg_ext & dbg_rst & dbg_lock & blink3 & blink2 & blink1;
|
||||
|
||||
-- virtual GNDs/VCCs
|
||||
vgnd <= (others=>'0');
|
||||
|
|
|
@ -47,17 +47,37 @@ package usbrx is
|
|||
tmode : std_logic;
|
||||
end record;
|
||||
|
||||
-- offset stage
|
||||
-- offset stage config
|
||||
type usbrx_off_config_t is record
|
||||
ioff : signed(15 downto 0);
|
||||
qoff : signed(15 downto 0);
|
||||
swap : std_logic;
|
||||
ioff : signed(15 downto 0);
|
||||
qoff : signed(15 downto 0);
|
||||
igain : unsigned(15 downto 0);
|
||||
qgain : unsigned(15 downto 0);
|
||||
end record;
|
||||
|
||||
-- decimation filter config
|
||||
type usbrx_fil_config_t is record
|
||||
decim : unsigned(2 downto 0);
|
||||
end record;
|
||||
|
||||
-- clock reference status
|
||||
type usbrx_ref_status_t is record
|
||||
lsb : unsigned(24 downto 0);
|
||||
msb : unsigned(6 downto 0);
|
||||
end record;
|
||||
|
||||
-- GPIO config
|
||||
type usbrx_gpio_config_t is record
|
||||
oena : std_logic_vector(10 downto 0);
|
||||
odata : std_logic_vector(10 downto 0);
|
||||
end record;
|
||||
|
||||
-- clock reference status
|
||||
type usbrx_gpio_status_t is record
|
||||
idata : std_logic_vector(10 downto 0);
|
||||
end record;
|
||||
|
||||
end usbrx;
|
||||
|
||||
package body usbrx is
|
||||
|
|
|
@ -1,6 +1,15 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<XML>
|
||||
<document type="stimulators" version="1">
|
||||
<set name="ASDB Stimulators" active="1"/>
|
||||
<set name="ASDB Stimulators" active="1">
|
||||
<stimulator>
|
||||
<signal_path value="/tb_usbrx/uut/off/config.igain"/>
|
||||
<rawdescription value="VAL:FRM:Override:x"9000":<= x"9000":1:"/>
|
||||
</stimulator>
|
||||
<stimulator>
|
||||
<signal_path value="/tb_usbrx/uut/off/in_i"/>
|
||||
<rawdescription value="VAL:FRM:Override:10#4000:<= 10#4000:0:"/>
|
||||
</stimulator>
|
||||
</set>
|
||||
</document>
|
||||
</XML>
|
||||
|
|
|
@ -1 +1,2 @@
|
|||
i<>.\src\usbrx\toplevel\usbrx_toplevel.vhd
|
||||
i<>.\src\mt_toolbox\mt_synctools.vhd
|
||||
|
|
|
@ -24,7 +24,7 @@ LANGUAGE=VHDL
|
|||
REFRESH_FLOW=1
|
||||
FAMILY=Lattice XP2
|
||||
fileopeninsrc=1
|
||||
fileopenfolder=C:\
|
||||
fileopenfolder=C:\DVB\sr_systems\sr-usbrx\osmo-sdr\fpga\hw-v2\src\mt_toolbox
|
||||
IMPL_TOOL=
|
||||
SYNTH_TOOL=
|
||||
NoWarningsSDF=0
|
||||
|
@ -108,6 +108,7 @@ testbench=1
|
|||
[Files]
|
||||
mt_toolbox/mt_toolbox.vhd=-1
|
||||
mt_toolbox/mt_clktools.vhd=-1
|
||||
mt_toolbox/mt_synctools.vhd=-1
|
||||
mt_filter/mt_filter.vhd=-1
|
||||
mt_filter/mt_fil_storage_slow.vhd=-1
|
||||
mt_filter/mt_fil_mac_slow.vhd=-1
|
||||
|
@ -119,6 +120,8 @@ usbrx\datapath/usbrx_offset.vhd=-1
|
|||
usbrx\datapath/usbrx_decimate.vhd=-1
|
||||
usbrx\datapath/usbrx_ssc.vhd=-1
|
||||
usbrx\toplevel/usbrx_clkgen.vhd=-1
|
||||
usbrx\toplevel/usbrx_clkref.vhd=-1
|
||||
usbrx\toplevel/usbrx_gpio.vhd=-1
|
||||
usbrx\toplevel/usbrx_spi.vhd=-1
|
||||
usbrx\toplevel/usbrx_regbank.vhd=-1
|
||||
usbrx\toplevel/usbrx_pwm.vhd=-1
|
||||
|
@ -129,6 +132,7 @@ testbench/tb_usbrx.vhd=-1
|
|||
[Files.Data]
|
||||
.\src\mt_toolbox\mt_toolbox.vhd=VHDL Source Code
|
||||
.\src\mt_toolbox\mt_clktools.vhd=VHDL Source Code
|
||||
.\src\mt_toolbox\mt_synctools.vhd=VHDL Source Code
|
||||
.\src\mt_filter\mt_filter.vhd=VHDL Source Code
|
||||
.\src\mt_filter\mt_fil_storage_slow.vhd=VHDL Source Code
|
||||
.\src\mt_filter\mt_fil_mac_slow.vhd=VHDL Source Code
|
||||
|
@ -140,6 +144,8 @@ testbench/tb_usbrx.vhd=-1
|
|||
.\src\usbrx\datapath\usbrx_decimate.vhd=VHDL Source Code
|
||||
.\src\usbrx\datapath\usbrx_ssc.vhd=VHDL Source Code
|
||||
.\src\usbrx\toplevel\usbrx_clkgen.vhd=VHDL Source Code
|
||||
.\src\usbrx\toplevel\usbrx_clkref.vhd=VHDL Source Code
|
||||
.\src\usbrx\toplevel\usbrx_gpio.vhd=VHDL Source Code
|
||||
.\src\usbrx\toplevel\usbrx_spi.vhd=VHDL Source Code
|
||||
.\src\usbrx\toplevel\usbrx_regbank.vhd=VHDL Source Code
|
||||
.\src\usbrx\toplevel\usbrx_pwm.vhd=VHDL Source Code
|
||||
|
|
|
@ -1,63 +0,0 @@
|
|||
[General]
|
||||
CurrentVersion=103
|
||||
[COMPILESTATUS|.\src\mt_toolbox\mt_toolbox.vhd]
|
||||
FileTimeLow=30225029
|
||||
Status=Compiled
|
||||
[COMPILESTATUS|.\src\mt_toolbox\mt_clktools.vhd]
|
||||
FileTimeLow=30225029
|
||||
Status=Compiled
|
||||
[COMPILESTATUS|.\src\mt_filter\mt_filter.vhd]
|
||||
FileTimeLow=30225028
|
||||
Status=Compiled
|
||||
[COMPILESTATUS|.\src\mt_filter\mt_fil_storage_slow.vhd]
|
||||
FileTimeLow=30225028
|
||||
Status=Compiled
|
||||
[COMPILESTATUS|.\src\mt_filter\mt_fil_mac_slow.vhd]
|
||||
FileTimeLow=30222064
|
||||
Status=Compiled
|
||||
[COMPILESTATUS|.\src\mt_filter\mt_fir_symmetric_slow.vhd]
|
||||
FileTimeLow=30225032
|
||||
Status=Compiled
|
||||
[COMPILESTATUS|.\src\usbrx\usbrx.vhd]
|
||||
FileTimeLow=30225029
|
||||
Status=Compiled
|
||||
[COMPILESTATUS|.\src\usbrx\filter\usbrx_halfband.vhd]
|
||||
FileTimeLow=30225030
|
||||
Status=Compiled
|
||||
[COMPILESTATUS|.\src\usbrx\datapath\usbrx_ad7357.vhd]
|
||||
FileTimeLow=30225030
|
||||
Status=Compiled
|
||||
[COMPILESTATUS|.\src\usbrx\datapath\usbrx_offset.vhd]
|
||||
FileTimeLow=30225030
|
||||
Status=Compiled
|
||||
[COMPILESTATUS|.\src\usbrx\datapath\usbrx_decimate.vhd]
|
||||
FileTimeLow=30225031
|
||||
Status=Compiled
|
||||
[COMPILESTATUS|.\src\usbrx\datapath\usbrx_ssc.vhd]
|
||||
FileTimeLow=30225031
|
||||
Status=Compiled
|
||||
[COMPILESTATUS|.\src\usbrx\toplevel\usbrx_clkgen.vhd]
|
||||
FileTimeLow=30225031
|
||||
Status=Compiled
|
||||
[COMPILESTATUS|.\src\usbrx\toplevel\usbrx_spi.vhd]
|
||||
FileTimeLow=30225031
|
||||
Status=Compiled
|
||||
[COMPILESTATUS|.\src\usbrx\toplevel\usbrx_regbank.vhd]
|
||||
FileTimeLow=30225031
|
||||
Status=Compiled
|
||||
[COMPILESTATUS|.\src\usbrx\toplevel\usbrx_pwm.vhd]
|
||||
FileTimeLow=30225031
|
||||
Status=Compiled
|
||||
[COMPILESTATUS|.\src\usbrx\toplevel\usbrx_toplevel.vhd]
|
||||
FileTimeLow=30225031
|
||||
Status=Compiled
|
||||
[COMPILESTATUS|.\src\testbench\tb_filter.vhd]
|
||||
FileTimeLow=30225031
|
||||
Status=Compiled
|
||||
[COMPILESTATUS|.\src\testbench\tb_usbrx.vhd]
|
||||
FileTimeLow=30225031
|
||||
Status=Compiled
|
||||
[CACHEDOC|Aldec.Project.Generic.7|.\usbrx_vhdl.adf|]
|
||||
Path=
|
||||
[Gui config]
|
||||
RunFor=100 ns
|
Reference in New Issue