added fpga source and project files for hardware v2

This commit is contained in:
Christian Daniel 2012-05-17 22:18:26 +02:00
parent 0f007d876a
commit c62f5734b7
38 changed files with 6070 additions and 0 deletions

1340
fpga/hw-v2/Edfmap.ini Normal file

File diff suppressed because it is too large Load Diff

125
fpga/hw-v2/bde.set Normal file
View File

@ -0,0 +1,125 @@
##########
BUS DEFAULT NAME
BUS
##########
BUS DEFAULT TYPE
STD_LOGIC_VECTOR
##########
BUS GLOBAL CONNECTOR
GlobalBus
##########
BUS INDEX END
0
##########
BUS INDEX START
7
##########
BUS TERMINAL BUFFER
BusBuffer
##########
BUS TERMINAL IN
BusInput
##########
BUS TERMINAL INOUT
BusBidirectional
##########
BUS TERMINAL OUT
BusOutput
##########
CHECK DIAGRAM
YES
##########
DEFAULT BDE LANGUAGE
VHDL
##########
FILE HEADER
--
-- file <GENERATEDFILE>
-- generated <TIME>
-- from <SOURCEFILE>
-- by <GENERATORVERSION>
--
##########
GLOBAL CONNECTOR
Global
##########
GND DEFAULT TYPE
STD_LOGIC
##########
GND DEFAULT VALUE
'0'
##########
HANGING WIRE DEFAULT TYPE
STD_LOGIC
##########
HANGING WIRE DEFAULT VALUE
'Z'
##########
INCLUDE ACTIVE LIBRARY CLAUSE
0
##########
INCREMENT NET FACTOR
1
##########
INCREMENT NET START
0
##########
INCREMENT NETS
0
##########
LIBRARIES
library IEEE;
use IEEE.std_logic_1164.all;
##########
TERMINAL BUFFER
Buffer
##########
TERMINAL IN
Input
##########
TERMINAL INOUT
Bidirectional
##########
TERMINAL OUT
Output
##########
USE GLOBAL DEFAULTS
1
##########
VCC DEFAULT TYPE
STD_LOGIC
##########
VCC DEFAULT VALUE
'1'
##########
VERILOG DANGLING DEFAULT VALUE
1'bZ
##########
VERILOG DESIGN UNIT HEADER
`timescale 1ps / 1ps
##########
VERILOG FILE HEADER
//
// file <GENERATEDFILE>
// generated <TIME>
// from <SOURCEFILE>
// by <GENERATORVERSION>
//
##########
VERILOG GND DEFAULT TYPE
supply0
##########
VERILOG GND DEFAULT VALUE
1'b0
##########
VERILOG VCC DEFAULT TYPE
supply1
##########
VERILOG VCC DEFAULT VALUE
1'b1
##########
WIRE DEFAULT NAME
NET
##########
WIRE DEFAULT TYPE
STD_LOGIC

View File

@ -0,0 +1,19 @@
.\src\mt_toolbox\mt_toolbox.vhd
.\src\mt_toolbox\mt_clktools.vhd
.\src\mt_filter\mt_filter.vhd
.\src\mt_filter\mt_fil_storage_slow.vhd
.\src\mt_filter\mt_fil_mac_slow.vhd
.\src\mt_filter\mt_fir_symmetric_slow.vhd
.\src\usbrx\usbrx.vhd
.\src\usbrx\filter\usbrx_halfband.vhd
.\src\usbrx\datapath\usbrx_ad7357.vhd
.\src\usbrx\datapath\usbrx_offset.vhd
.\src\usbrx\datapath\usbrx_decimate.vhd
.\src\usbrx\datapath\usbrx_ssc.vhd
.\src\usbrx\toplevel\usbrx_clkgen.vhd
.\src\usbrx\toplevel\usbrx_spi.vhd
.\src\usbrx\toplevel\usbrx_regbank.vhd
.\src\usbrx\toplevel\usbrx_pwm.vhd
.\src\usbrx\toplevel\usbrx_toplevel.vhd
.\src\testbench\tb_filter.vhd
.\src\testbench\tb_usbrx.vhd

46
fpga/hw-v2/compile.cfg Normal file
View File

@ -0,0 +1,46 @@
[View]
Entity=
Architecture=
TopLevelType=
[file:.\src\usbrx\toplevel\usbrx_toplevel.vhd]
Enabled=1
[file:.\src\usbrx\toplevel\usbrx_clkgen.vhd]
Enabled=1
[file:.\src\mt_toolbox\mt_toolbox.vhd]
Enabled=1
[file:.\src\usbrx\toplevel\usbrx_spi.vhd]
Enabled=1
[file:.\src\usbrx\toplevel\usbrx_regbank.vhd]
Enabled=1
[file:.\src\testbench\tb_usbrx.vhd]
Enabled=1
VerilogLanguage=7
LIB=
[file:.\src\usbrx\toplevel\usbrx_pwm.vhd]
Enabled=1
[file:.\src\mt_filter\mt_filter.vhd]
Enabled=1
[file:.\src\usbrx\filter\usbrx_halfband.vhd]
Enabled=1
[file:.\src\usbrx\datapath\usbrx_decimate.vhd]
Enabled=1
[file:.\src\usbrx\datapath\usbrx_ad7357.vhd]
Enabled=1
[file:.\src\usbrx\datapath\usbrx_ssc.vhd]
Enabled=1
[file:.\src\usbrx\usbrx.vhd]
Enabled=1
[file:.\src\usbrx\datapath\usbrx_offset.vhd]
Enabled=1
[file:.\src\mt_filter\mt_fil_storage_slow.vhd]
Enabled=1
[file:.\src\mt_filter\mt_fil_mac_slow.vhd]
Enabled=1
[file:.\src\mt_filter\mt_fir_symmetric_slow.vhd]
Enabled=1
[file:.\src\mt_toolbox\mt_clktools.vhd]
Enabled=1
[file:.\src\testbench\tb_filter.vhd]
LIB=
Enabled=1
VerilogLanguage=7

View File

@ -0,0 +1,49 @@
<?xml version='1.0' encoding='utf-8' ?>
<!DOCTYPE ispXCF SYSTEM "IspXCF.dtd" >
<ispXCF version="1.4">
<Comment></Comment>
<Chain>
<Comm>JTAG</Comm>
<Device>
<SelectedProg value="TRUE"/>
<Pos>1</Pos>
<Vendor>Lattice</Vendor>
<Family>LatticeXP2</Family>
<Name>LFXP2-5E</Name>
<IDCode>0x01299043</IDCode>
<Package>All</Package>
<PON>LFXP2-5E</PON>
<Bypass>
<InstrLen>8</InstrLen>
<InstrVal>11111111</InstrVal>
<BScanLen>1</BScanLen>
<BScanVal>0</BScanVal>
</Bypass>
<File>../diamond/usbrx_vhdl/usbrx_vhdl_usbrx_vhdl.jed</File>
<FileTime>5/2/2012 11:21:53</FileTime>
<JedecChecksum>0xA75C</JedecChecksum>
<Operation>FLASH Erase,Program,Verify,Refresh</Operation>
<Option>
<SVFVendor>JTAG STANDARD</SVFVendor>
<IOState>Leave Alone</IOState>
<PreloadLength>394</PreloadLength>
<Reinitialize value="TRUE"/>
<SVFProcessor>SVF Processor</SVFProcessor>
<Usercode>0xFFFFFFFF</Usercode>
<AccessMode>FLASH</AccessMode>
</Option>
</Device>
</Chain>
<ProjectOptions>
<Program>SEQUENTIAL</Program>
<Process>ENTIRED CHAIN</Process>
<OperationOverride>No Override</OperationOverride>
<StartTAP>TLR</StartTAP>
<EndTAP>TLR</EndTAP>
<VerifyUsercode value="FALSE"/>
</ProjectOptions>
<CableOptions>
<CableName>USB2</CableName>
<PortAdd>FTUSB-0</PortAdd>
</CableOptions>
</ispXCF>

View File

@ -0,0 +1,9 @@
[Runmanager]
Geometry=@ByteArray(\x1\xd9\xd0\xcb\0\x1\0\0\0\0\0\0\0\0\0\0\0\0\x1\x1c\0\0\0\xd8\0\0\0\0\0\0\0\0\xff\xff\xff\xff\xff\xff\xff\xff\0\0\0\x1\0\0)
windowState=@ByteArray(\0\0\0\xff\0\0\0\0\xfd\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x4\0\0\0\x4\0\0\0\b\0\0\0\b\xfc\0\0\0\x1\0\0\0\0\0\0\0\x1\xff\xff\xff\xff\x3\0\0\0\0\xff\xff\xff\xff\0\0\0\0\0\0\0\0)
headerState=@ByteArray(\0\0\0\xff\0\0\0\0\0\0\0\x1\0\0\0\x1\0\0\0\0\x1\0\0\0\0\0\0\0\0\0\0\0\x13\0\xfc\a\0\0\0\t\0\0\0\x10\0\0\0\x64\0\0\0\xf\0\0\0\x64\0\0\0\xe\0\0\0\x64\0\0\0\r\0\0\0\x64\0\0\0\f\0\0\0\x64\0\0\0\v\0\0\0\x64\0\0\0\n\0\0\0\x64\0\0\0\x12\0\0\0\x64\0\0\0\x11\0\0\0\x64\0\0\x3\xa7\0\0\0\x13\x1\x1\0\x1\0\0\0\0\0\0\0\0\0\0\0\0\x64\xff\xff\xff\xff\0\0\0\x81\0\0\0\0\0\0\0\x3\0\0\0#\0\0\0\x1\0\0\0\x2\0\0\x3\x84\0\0\0\t\0\0\0\0\0\0\0\0\0\0\0\t\0\0\0\0)
[usbrx_vhdl%3CStrategy1%3E]
isChecked=false
isHidden=false
isExpanded=false

View File

@ -0,0 +1,4 @@
[General]
PAR.auto_tasks=PARTrace, IOTiming
Map.auto_tasks=@Invalid()
Export.auto_tasks=TimingSimFileVHD, Bitgen

View File

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE strategy>
<Strategy version="1.0" predefined="0" description="" label="Strategy1">
<Property name="PROP_MAP_TimingDriven" value="True" time="0"/>
<Property name="PROP_MAP_TimingDrivenNodeRep" value="True" time="0"/>
<Property name="PROP_MAP_TimingDrivenPack" value="True" time="0"/>
</Strategy>

View File

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE Report>
<ReportView version="2.0">
<Implement name="usbrx_vhdl">
<ToolReport id="toolhle_genhierarchy" path="hdldiagram_gen_hierarchy.html" status="2"/>
<ToolReport id="toolhle_runbkm" path="" status="2"/>
<ToolReport id="toolpio" path="" status="2"/>
<ToolReport id="toolsso" path="" status="2"/>
</Implement>
</ReportView>

View File

@ -0,0 +1,68 @@
<?xml version="1.0" encoding="UTF-8"?>
<BaliProject version="1.3" title="usbrx_vhdl" device="LFXP2-5E-5M132C" default_implementation="usbrx_vhdl">
<Options/>
<Implementation title="usbrx_vhdl" dir="usbrx_vhdl" description="usbrx_vhdl" default_strategy="Strategy1">
<Options top="usbrx_toplevel"/>
<Source name="../src/mt_toolbox/mt_toolbox.vhd" type="VHDL" type_short="VHDL">
<Options/>
</Source>
<Source name="../src/usbrx/toplevel/usbrx_clkgen.vhd" type="VHDL" type_short="VHDL">
<Options/>
</Source>
<Source name="../src/usbrx/toplevel/usbrx_toplevel.vhd" type="VHDL" type_short="VHDL">
<Options/>
</Source>
<Source name="../src/usbrx/toplevel/usbrx_pwm.vhd" type="VHDL" type_short="VHDL">
<Options/>
</Source>
<Source name="../src/usbrx/toplevel/usbrx_regbank.vhd" type="VHDL" type_short="VHDL">
<Options/>
</Source>
<Source name="../src/usbrx/toplevel/usbrx_spi.vhd" type="VHDL" type_short="VHDL">
<Options/>
</Source>
<Source name="../src/mt_filter/mt_filter.vhd" type="VHDL" type_short="VHDL">
<Options/>
</Source>
<Source name="../src/usbrx/filter/usbrx_halfband.vhd" type="VHDL" type_short="VHDL">
<Options/>
</Source>
<Source name="../src/usbrx/datapath/usbrx_ssc.vhd" type="VHDL" type_short="VHDL">
<Options/>
</Source>
<Source name="../src/usbrx/datapath/usbrx_ad7357.vhd" type="VHDL" type_short="VHDL">
<Options/>
</Source>
<Source name="../src/usbrx/datapath/usbrx_decimate.vhd" type="VHDL" type_short="VHDL">
<Options/>
</Source>
<Source name="../src/usbrx/datapath/usbrx_offset.vhd" type="VHDL" type_short="VHDL">
<Options/>
</Source>
<Source name="../src/usbrx/usbrx.vhd" type="VHDL" type_short="VHDL">
<Options/>
</Source>
<Source name="../src/mt_filter/mt_fil_mac_slow.vhd" type="VHDL" type_short="VHDL">
<Options/>
</Source>
<Source name="../src/mt_filter/mt_fil_storage_slow.vhd" type="VHDL" type_short="VHDL">
<Options/>
</Source>
<Source name="../src/mt_filter/mt_fir_symmetric_slow.vhd" type="VHDL" type_short="VHDL">
<Options/>
</Source>
<Source name="../src/mt_toolbox/mt_clktools.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>

View File

@ -0,0 +1,130 @@
BLOCK RESETPATHS ;
BLOCK ASYNCPATHS ;
LOCATE COMP "clk_in_pclk" SITE "H1" ;
LOCATE COMP "adc_cs" SITE "G1" ;
LOCATE COMP "adc_sck" SITE "B1" ;
LOCATE COMP "adc_sd1" SITE "D1" ;
LOCATE COMP "adc_sd2" SITE "E1" ;
LOCATE COMP "ctl_int" SITE "P2" ;
LOCATE COMP "ctl_cs" SITE "P4" ;
LOCATE COMP "ctl_sck" SITE "P5" ;
LOCATE COMP "ctl_mosi" SITE "P6" ;
LOCATE COMP "ctl_miso" SITE "P7" ;
LOCATE COMP "dingsrst" SITE "P10" ;
LOCATE COMP "dings" SITE "P9" ;
LOCATE COMP "rx_clk" SITE "B14" ;
LOCATE COMP "rx_syn" SITE "D14" ;
LOCATE COMP "rx_dat" SITE "E14" ;
LOCATE COMP "tx_clk" SITE "A14" ;
LOCATE COMP "tx_syn" SITE "G14" ;
LOCATE COMP "tx_dat" SITE "F14" ;
LOCATE COMP "gain0" SITE "P1" ;
LOCATE COMP "gain1" SITE "N1" ;
LOCATE COMP "gps_1pps" SITE "P14" ;
LOCATE COMP "gps_10k" SITE "N14" ;
LOCATE COMP "gpio_0" SITE "A1" ;
LOCATE COMP "gpio_1" SITE "A2" ;
LOCATE COMP "gpio_2" SITE "A3" ;
LOCATE COMP "gpio_3" SITE "A5" ;
LOCATE COMP "gpio_4" SITE "A7" ;
LOCATE COMP "gpio_5" SITE "A8" ;
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 "vgnd_0" SITE "B3" ;
LOCATE COMP "vgnd_1" SITE "C5" ;
LOCATE COMP "vgnd_2" SITE "C8" ;
LOCATE COMP "vgnd_3" SITE "B2" ;
LOCATE COMP "vgnd_4" SITE "C2" ;
LOCATE COMP "vgnd_5" SITE "D2" ;
LOCATE COMP "vgnd_6" SITE "M6" ;
LOCATE COMP "vgnd_7" SITE "N2" ;
LOCATE COMP "vgnd_8" SITE "N3" ;
LOCATE COMP "vgnd_9" SITE "D12" ;
LOCATE COMP "vgnd_10" SITE "D13" ;
LOCATE COMP "vgnd_11" SITE "M10" ;
LOCATE COMP "vcc33_0" SITE "B6" ;
LOCATE COMP "vcc33_1" SITE "C7" ;
LOCATE COMP "vcc33_2" SITE "C10" ;
LOCATE COMP "vcc33_3" SITE "D3" ;
LOCATE COMP "vcc33_4" SITE "E3" ;
LOCATE COMP "vcc33_5" SITE "G2" ;
LOCATE COMP "vcc33_6" SITE "H2" ;
LOCATE COMP "vcc33_7" SITE "M4" ;
LOCATE COMP "vcc33_8" SITE "M5" ;
LOCATE COMP "vcc33_9" SITE "P13" ;
LOCATE COMP "vcc33_10" SITE "M13" ;
LOCATE COMP "vcc33_11" SITE "N13" ;
LOCATE COMP "vcc12_0" SITE "B9" ;
LOCATE COMP "vcc12_1" SITE "B10" ;
LOCATE COMP "vcc12_2" SITE "C9" ;
LOCATE COMP "vcc12_3" SITE "H13" ;
LOCATE COMP "vcc12_4" SITE "H14" ;
IOBUF PORT "clk_in_pclk" IO_TYPE=LVCMOS33 ;
IOBUF PORT "adc_cs" IO_TYPE=LVCMOS33 DRIVE=4 ;
IOBUF PORT "adc_sck" IO_TYPE=LVCMOS33 DRIVE=4 ;
IOBUF PORT "adc_sd1" IO_TYPE=LVCMOS33 ;
IOBUF PORT "adc_sd2" IO_TYPE=LVCMOS33 ;
IOBUF PORT "ctl_int" IO_TYPE=LVCMOS33 DRIVE=4 ;
IOBUF PORT "ctl_cs" IO_TYPE=LVCMOS33 ;
IOBUF PORT "ctl_sck" IO_TYPE=LVCMOS33 ;
IOBUF PORT "ctl_mosi" IO_TYPE=LVCMOS33 ;
IOBUF PORT "ctl_miso" IO_TYPE=LVCMOS33 DRIVE=4 ;
IOBUF PORT "dingsrst" IO_TYPE=LVCMOS33 ;
IOBUF PORT "dings" IO_TYPE=LVCMOS33 DRIVE=4 ;
IOBUF PORT "gps_10k" IO_TYPE=LVCMOS33 DRIVE=4 ;
IOBUF PORT "rx_clk" IO_TYPE=LVCMOS33 DRIVE=4 ;
IOBUF PORT "rx_syn" IO_TYPE=LVCMOS33 DRIVE=4 ;
IOBUF PORT "rx_dat" IO_TYPE=LVCMOS33 DRIVE=4 ;
IOBUF PORT "tx_clk" IO_TYPE=LVCMOS33 DRIVE=4 ;
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 "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 ;
IOBUF PORT "gpio_3" IO_TYPE=LVCMOS33 DRIVE=4 ;
IOBUF PORT "gpio_4" IO_TYPE=LVCMOS33 DRIVE=4 ;
IOBUF PORT "gpio_5" IO_TYPE=LVCMOS33 DRIVE=4 ;
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 "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 ;
IOBUF PORT "vgnd_3" IO_TYPE=LVCMOS33 DRIVE=4 ;
IOBUF PORT "vgnd_4" IO_TYPE=LVCMOS33 DRIVE=4 ;
IOBUF PORT "vgnd_5" IO_TYPE=LVCMOS33 DRIVE=4 ;
IOBUF PORT "vgnd_6" IO_TYPE=LVCMOS33 DRIVE=4 ;
IOBUF PORT "vgnd_7" IO_TYPE=LVCMOS33 DRIVE=4 ;
IOBUF PORT "vgnd_8" IO_TYPE=LVCMOS33 DRIVE=4 ;
IOBUF PORT "vgnd_9" IO_TYPE=LVCMOS33 DRIVE=4 ;
IOBUF PORT "vgnd_10" IO_TYPE=LVCMOS33 DRIVE=4 ;
IOBUF PORT "vgnd_11" IO_TYPE=LVCMOS33 DRIVE=4 ;
IOBUF PORT "vcc33_0" IO_TYPE=LVCMOS33 DRIVE=4 ;
IOBUF PORT "vcc33_1" IO_TYPE=LVCMOS33 DRIVE=4 ;
IOBUF PORT "vcc33_2" IO_TYPE=LVCMOS33 DRIVE=4 ;
IOBUF PORT "vcc33_3" IO_TYPE=LVCMOS33 DRIVE=4 ;
IOBUF PORT "vcc33_4" IO_TYPE=LVCMOS33 DRIVE=4 ;
IOBUF PORT "vcc33_5" IO_TYPE=LVCMOS33 DRIVE=4 ;
IOBUF PORT "vcc33_6" IO_TYPE=LVCMOS33 DRIVE=4 ;
IOBUF PORT "vcc33_7" IO_TYPE=LVCMOS33 DRIVE=4 ;
IOBUF PORT "vcc33_8" IO_TYPE=LVCMOS33 DRIVE=4 ;
IOBUF PORT "vcc33_9" IO_TYPE=LVCMOS33 DRIVE=4 ;
IOBUF PORT "vcc33_10" IO_TYPE=LVCMOS33 DRIVE=4 ;
IOBUF PORT "vcc33_11" IO_TYPE=LVCMOS33 DRIVE=4 ;
IOBUF PORT "vcc33_12" IO_TYPE=LVCMOS33 DRIVE=4 ;
IOBUF PORT "vcc12_0" IO_TYPE=LVCMOS33 DRIVE=4 ;
IOBUF PORT "vcc12_1" IO_TYPE=LVCMOS33 DRIVE=4 ;
IOBUF PORT "vcc12_2" IO_TYPE=LVCMOS33 DRIVE=4 ;
IOBUF PORT "vcc12_3" IO_TYPE=LVCMOS33 DRIVE=4 ;
IOBUF PORT "vcc12_4" IO_TYPE=LVCMOS33 DRIVE=4 ;
FREQUENCY PORT "clk_in_pclk" 30.000000 MHz ;
FREQUENCY NET "clk_80_c" 80.000000 MHz ;
SYSCONFIG INBUF=OFF ;

View File

@ -0,0 +1,3 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE strategy>
<Strategy version="1.0" predefined="0" description="" label=""/>

2
fpga/hw-v2/library.cfg Normal file
View File

@ -0,0 +1,2 @@
$include = "$VSIMSALIBRARYCFG"
usbrx_vhdl = "./usbrx_vhdl.LIB" 1322060719953

1
fpga/hw-v2/projlib.cfg Normal file
View File

@ -0,0 +1 @@
usbrx_vhdl = "./usbrx_vhdl.LIB" 1322060719655

View File

@ -0,0 +1,146 @@
---------------------------------------------------------------------------------------------------
-- Filename : mt_fil_mac_slow.vhd
-- Project : maintech filter toolbox
-- Purpose : MAC cell for FIR-like filters
-- - version for 'slow' filter versions
---------------------------------------------------------------------------------------------------
-----------------------------------------------------------------------------------
-- 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_fil_mac_slow ------------------------------------------------------------
-------------------------------------------------------------------------------
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.mt_filter.all;
entity mt_fil_mac_slow is
port (
-- common
clk : in std_logic;
reset : in std_logic;
-- control-path
start : in std_logic;
active : in std_logic;
presub : in std_logic;
-- data input
smp1 : in fir_dataword18;
smp2 : in fir_dataword18;
coeff : in fir_dataword18;
-- data output
dnew : out std_logic;
dout : out fir_dataword18
);
end mt_fil_mac_slow;
architecture rtl of mt_fil_mac_slow is
-- rounding constant (16 bits will get truncated)
constant RNDVAL : natural := (2**16/2);
-- control signals
signal done : std_logic;
signal active_del : std_logic_vector(2 downto 0);
signal start_del : std_logic_vector(2 downto 0);
signal done_del : std_logic_vector(2 downto 0);
-- data registers
signal psreg : std_logic;
signal dreg : signed(17 downto 0);
signal b0reg : signed(17 downto 0);
signal b1reg : signed(18 downto 0);
signal a0reg : signed(17 downto 0);
signal a1reg : signed(17 downto 0);
signal mreg : signed(35 downto 0);
signal preg : signed(35 downto 0);
begin
-- create done-flag after 'active' goes low or 'start' is set while still active
done <= (start or (not active)) and active_del(0);
-- create delayed control-signals
process(clk)
begin
if rising_edge(clk) then
active_del <= active_del(active_del'left-1 downto 0) & active;
start_del <= start_del(start_del'left-1 downto 0) & start;
done_del <= done_del(done_del'left-1 downto 0) & done;
end if;
end process;
-- do math
process(clk)
begin
if rising_edge(clk) then
-- simple storage registers
psreg <= presub;
dreg <= smp1;
b0reg <= smp2;
a0reg <= coeff;
a1reg <= a0reg;
-- pre-adder
if psreg='1'
then b1reg <= resize(b0reg,19) - resize(dreg,19);
else b1reg <= resize(b0reg,19) + resize(dreg,19);
end if;
-- multiplier
mreg <= a1reg * b1reg(18 downto 1);
-- post-adder / accumulator
if active_del(2)='1' then
if start_del(2)='1'
then preg <= mreg + to_signed(RNDVAL,36);
else preg <= mreg + preg;
end if;
end if;
end if;
end process;
-- update output
process(reset, clk)
begin
if reset='1' then
dnew <= '0';
dout <= (others=>'0');
elsif rising_edge(clk) then
if done_del(2)='1' then
dnew <= '1';
if preg(35)='0' and preg(34 downto 33)/="00" then
dout <= to_signed(2**17-1,18);
elsif preg(35)='1' and preg(34 downto 33)/="11" then
dout <= to_signed(-(2**17),18);
else
dout <= preg(33 downto 16);
end if;
else
dnew <= '0';
end if;
end if;
end process;
end rtl;

View File

@ -0,0 +1,403 @@
---------------------------------------------------------------------------------------------------
-- Filename : mt_fil_storage_slow.vhd
-- Project : maintech filter toolbox
-- Purpose : basic data storage for FIR-like filters
-- - version for 'slow' filter versions
---------------------------------------------------------------------------------------------------
-----------------------------------------------------------------------------------
-- 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_fil_dstorage_slow ------------------------------------------------------
-------------------------------------------------------------------------------
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.mt_filter.all;
entity mt_fil_dstorage_slow is
generic (
CHANNELS : natural;
DEPTH : natural;
RAMSTYLE : string
);
port (
-- common
clk : in std_logic;
reset : in std_logic;
-- control
chan : in unsigned(log2(CHANNELS)-1 downto 0);
load : in std_logic;
start : in std_logic;
stop : in std_logic;
active : in std_logic;
-- datapath
din : in fir_dataword18;
dout1 : out fir_dataword18;
dout2 : out fir_dataword18
);
end mt_fil_dstorage_slow;
architecture rtl of mt_fil_dstorage_slow is
--
-- types & rams
--
-- derived constants
constant MEMSIZE : natural := CHANNELS * DEPTH;
-- internal types
subtype offset_t is unsigned(log2(DEPTH)-1 downto 0);
subtype addr_t is unsigned(log2(MEMSIZE)-1 downto 0);
subtype data_t is fir_dataword18;
type atab_t is array(CHANNELS-1 downto 0) of addr_t;
type pram_t is array(CHANNELS-1 downto 0) of offset_t;
type sram_t is array(MEMSIZE-1 downto 0) of data_t;
-- create address tables
function get_addr_tab return atab_t is
variable res : atab_t;
begin
for i in res'range loop
res(i) := to_unsigned(i*DEPTH, addr_t'length);
end loop;
return res;
end get_addr_tab;
constant addr_tab : atab_t := get_addr_tab;
-- ram ports
signal sram1_we : std_logic;
signal sram1_waddr : addr_t;
signal sram1_wdata : data_t;
signal sram1_re : std_logic;
signal sram1_raddr : addr_t;
signal sram1_rdata : data_t := (others=>'0');
signal sram2_we : std_logic;
signal sram2_waddr : addr_t;
signal sram2_wdata : data_t;
signal sram2_re : std_logic;
signal sram2_raddr : addr_t;
signal sram2_rdata : data_t := (others=>'0');
-- actual rams
signal pram : pram_t := (others=>(others=>'0'));
signal sram1 : sram_t := (others=>(others=>'0'));
signal sram2 : sram_t := (others=>(others=>'0'));
-- configure rams
attribute syn_ramstyle of pram : signal is "logic";
attribute syn_ramstyle of sram1 : signal is RAMSTYLE;
attribute syn_ramstyle of sram2 : signal is RAMSTYLE&",no_rw_check";
--
-- status
--
-- delayed control signals
signal start_del : std_logic_vector(1 downto 0);
signal load_del : std_logic_vector(2 downto 0);
signal active_del : std_logic_vector(1 downto 0);
signal stop_del : std_logic_vector(2 downto 0);
-- status
signal selchan : unsigned(log2(CHANNELS)-1 downto 0);
signal baseaddr : addr_t;
signal woffset : offset_t;
signal roffset1 : offset_t;
signal roffset2 : offset_t;
begin
-- validate generics
assert DEPTH>1
report "mt_fil_dstorage_slow: DEPTH must be larger than 1"
severity FAILURE;
-- control logic
process(clk, reset)
variable offset : offset_t;
begin
if reset='1' then
start_del <= (others=>'0');
load_del <= (others=>'0');
active_del <= (others=>'0');
stop_del <= (others=>'0');
selchan <= (others=>'0');
baseaddr <= (others=>'0');
woffset <= (others=>'0');
roffset1 <= (others=>'0');
roffset2 <= (others=>'0');
sram1_re <= '0';
sram1_we <= '0';
sram1_raddr <= (others=>'0');
sram1_waddr <= (others=>'0');
sram1_wdata <= (others=>'0');
sram2_re <= '0';
sram2_we <= '0';
sram2_raddr <= (others=>'0');
sram2_waddr <= (others=>'0');
sram2_wdata <= (others=>'0');
elsif rising_edge(clk) then
-- set default values
sram1_re <= '0';
sram1_we <= '0';
sram2_re <= '0';
sram2_we <= '0';
-- create delayed flags
start_del <= start_del(start_del'left-1 downto 0) & start;
load_del <= load_del(load_del'left-1 downto 0) & load;
active_del <= active_del(active_del'left-1 downto 0) & active;
stop_del <= stop_del(stop_del'left-1 downto 0) & stop;
-- init status on start of burst
if start='1' then
-- remember channel
selchan <= chan;
-- get base-address for selected channels
baseaddr <= addr_tab(to_integer(chan));
-- init pointers
offset := pram(to_integer(chan));
woffset <= offset;
roffset1 <= offset;
if offset=(DEPTH-1)
then roffset2 <= to_unsigned(0,roffset2'length);
else roffset2 <= offset + 1;
end if;
end if;
-- store sample into ram and increment write-pointer if 'load'-flag is set
if load_del(0)='1' then
-- write sample into ram
sram1_we <= '1';
sram1_waddr <= baseaddr + woffset;
sram1_wdata <= din;
-- update write-pointer
woffset <= roffset2; -- 'roffset2' is actually "((woffset+1) mod DEPTH)" here
end if;
if load_del(1)='1' then
-- write-back updated write-pointer
pram(to_integer(selchan)) <= woffset;
end if;
-- carry sample from sram1 into sram2 if 'stop'-flag is set
if load_del(1)='1' then
sram2_waddr <= baseaddr + woffset;
end if;
if stop_del(2)='1' then
sram2_we <= '1';
sram2_wdata <= sram1_rdata;
end if;
-- issue read-requests when active
if active_del(0)='1' then
-- read samples from ram
sram1_re <= '1';
sram2_re <= '1';
sram1_raddr <= baseaddr + roffset1;
sram2_raddr <= baseaddr + roffset2;
-- update read-pointers
if roffset1=0
then roffset1 <= to_unsigned(DEPTH-1,roffset1'length);
else roffset1 <= roffset1 - 1;
end if;
if roffset2=(DEPTH-1)
then roffset2 <= to_unsigned(0,roffset2'length);
else roffset2 <= roffset2 + 1;
end if;
end if;
end if;
end process;
-- set output
dout1 <= sram1_rdata when load_del(2)='0' else din;
dout2 <= sram2_rdata;
-- infer rams
process(clk)
begin
if rising_edge(clk) then
if sram1_we='1' then
sram1(to_integer(sram1_waddr)) <= sram1_wdata;
end if;
if sram1_re='1' then
sram1_rdata <= sram1(to_integer(sram1_raddr));
end if;
if sram2_we='1' then
sram2(to_integer(sram2_waddr)) <= sram2_wdata;
end if;
if sram2_re='1' then
sram2_rdata <= sram2(to_integer(sram2_raddr));
end if;
end if;
end process;
end rtl;
-------------------------------------------------------------------------------
-- mt_fil_storage_slow --------------------------------------------------------
-------------------------------------------------------------------------------
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.mt_filter.all;
entity mt_fil_storage_slow is
generic (
COEFFS : fir_coefficients; -- coefficients
DCHAN : natural; -- number of data channels
TAPS : natural; -- number of samples in each segment
RAMSTYLE : string; -- ram style for inferred memories
ROMSTYLE : string -- ram style for coefficent rom
);
port (
-- common
clk : in std_logic;
reset : in std_logic;
-- config
chan : in unsigned(log2(DCHAN)-1 downto 0);
-- input
in_load : in std_logic;
in_start : in std_logic;
in_stop : in std_logic;
in_active : in std_logic;
in_data : in fir_dataword18;
-- output
out_load : out std_logic;
out_start : out std_logic;
out_stop : out std_logic;
out_active : out std_logic;
out_data1 : out fir_dataword18;
out_data2 : out fir_dataword18;
out_coeff : out fir_dataword18
);
end mt_fil_storage_slow;
architecture rtl of mt_fil_storage_slow is
-- status
signal del_load : std_logic_vector(1 downto 0);
signal del_start : std_logic_vector(1 downto 0);
signal del_stop : std_logic_vector(1 downto 0);
signal del_active : std_logic_vector(1 downto 0);
signal cind : unsigned(log2(TAPS)-1 downto 0);
-- coeff rom
constant rom_size : natural := 1 * (2**log2(TAPS));
type rom_t is array (0 to rom_size-1) of fir_dataword18;
function generate_rom return rom_t is
variable rom : rom_t;
variable ssize : natural;
begin
ssize := 2**log2(TAPS);
rom := (others=>(others=>'0'));
for t in 0 to TAPS-1 loop
rom(t) := to_signed(COEFFS(t), 18);
end loop;
return rom;
end generate_rom;
signal rom : rom_t := generate_rom;
-- don't waste blockram
attribute syn_romstyle of rom : signal is ROMSTYLE;
attribute syn_ramstyle of rom : signal is ROMSTYLE;
begin
-- data-buffer
dbuf: entity mt_fil_dstorage_slow
generic map (
CHANNELS => DCHAN,
DEPTH => TAPS,
RAMSTYLE => RAMSTYLE
)
port map (
clk => clk,
reset => reset,
chan => chan,
load => in_load,
start => in_start,
stop => in_stop,
active => in_active,
din => in_data,
dout1 => out_data1,
dout2 => out_data2
);
-- control logic
process(clk, reset)
begin
if reset='1' then
del_load <= (others=>'0');
del_start <= (others=>'0');
del_stop <= (others=>'0');
del_active <= (others=>'0');
out_load <= '0';
out_start <= '0';
out_stop <= '0';
out_active <= '0';
out_coeff <= (others=>'0');
cind <= (others=>'0');
elsif rising_edge(clk) then
-- create delayed control flags
del_load <= del_load(del_load'left-1 downto 0) & in_load;
del_start <= del_start(del_start'left-1 downto 0) & in_start;
del_stop <= del_stop(del_stop'left-1 downto 0) & in_stop;
del_active <= del_active(del_active'left-1 downto 0) & in_active;
-- output delayed control flags
out_load <= del_load(1);
out_start <= del_start(1);
out_stop <= del_stop(1);
out_active <= del_active(1);
-- update coeff-indices
if del_start(0)='1' then
cind <= to_unsigned(0, cind'length);
elsif del_active(0)='1' then
cind <= cind + 1;
end if;
-- output coefficent
out_coeff <= rom(to_integer(cind));
end if;
end process;
end rtl;

View File

@ -0,0 +1,46 @@
---------------------------------------------------------------------------------------------------
-- Filename : mt_filter.vhd
-- Project : maintech filter toolbox
-- Purpose : maintech filter toolbox package
--
-- Description : declaration of common types, functions and attributes
-- used throughout the filter toolbox
---------------------------------------------------------------------------------------------------
-----------------------------------------------------------------------------------
-- 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;
package mt_filter is
--
-- FIR filter types
--
subtype fir_dataword18 is signed(17 downto 0);
type fir_databus18 is array (natural range <>) of fir_dataword18;
subtype fir_coefficient is integer range -2**17 to 2**17-1;
type fir_coefficients is array (natural range <>) of fir_coefficient;
end mt_filter;
package body mt_filter is
-- nothing so far
end mt_filter;

View File

@ -0,0 +1,219 @@
---------------------------------------------------------------------------------------------------
-- Filename : mt_fir_symmetric_slow.vhd
-- Project : maintech filter toolbox
-- Purpose : Symmetric FIR filter
-- - multiplexed input/output for all data-channels
-- - single MAC-cell for all calculations
---------------------------------------------------------------------------------------------------
-----------------------------------------------------------------------------------
-- 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.mt_filter.all;
entity mt_fir_symmetric_slow is
generic (
CHANNELS : natural; -- number of data channels
TAPS : natural; -- number of filter taps (AFTER folding)
COEFFS : fir_coefficients; -- coefficent sets
RAMSTYLE : string; -- ram style for inferred memories
ROMSTYLE : string -- ram style for coefficent rom
);
port(
-- common
clk : in std_logic;
reset : in std_logic;
-- input port
in_clk : in std_logic;
in_ack : out std_logic;
in_chan : in unsigned(log2(CHANNELS)-1 downto 0);
in_data : in fir_dataword18;
-- output port
out_clk : out std_logic;
out_chan : out unsigned(log2(CHANNELS)-1 downto 0);
out_data : out fir_dataword18
);
end mt_fir_symmetric_slow;
architecture rtl of mt_fir_symmetric_slow is
-- internal types
subtype chan_t is unsigned(log2(CHANNELS)-1 downto 0);
type chan_array_t is array(natural range<>) of chan_t;
-- control signals
signal active : std_logic;
signal shiftcnt : unsigned(log2(TAPS)-1 downto 0);
signal ochan : chan_array_t(3 downto 0);
-- storage ports
signal st_chan : chan_t;
signal st_start : std_logic;
signal st_stop : std_logic;
signal st_active : std_logic;
signal st_din : fir_dataword18;
-- storage <-> MAC
signal st_mac_start : std_logic;
signal st_mac_stop : std_logic;
signal st_mac_active : std_logic;
signal st_mac_dout1 : fir_dataword18;
signal st_mac_dout2 : fir_dataword18;
signal st_mac_coeff : fir_dataword18;
-- MAC output
signal mac_dnew : std_logic;
signal mac_dout : fir_dataword18;
begin
-- control logic
process(clk, reset)
begin
if reset='1' then
active <= '0';
shiftcnt <= (others=>'0');
ochan <= (others=>(others=>'0'));
st_start <= '0';
st_stop <= '0';
st_active <= '0';
in_ack <= '0';
out_clk <= '0';
out_data <= (others=>'0');
out_chan <= (others=>'0');
elsif rising_edge(clk) then
-- set default values
in_ack <= '0';
out_clk <= '0';
st_start <= '0';
st_stop <= '0';
st_active <= '0';
-- get current status
if active='0' then
--> idle
-- check for new request
if in_clk='1' then
--> input new sample and start burst from storage to MAC cell
shiftcnt <= to_unsigned(TAPS-1, shiftcnt'length);
st_start <= '1';
st_active <= '1';
active <= '1';
end if;
else
--> active
-- control storage
if shiftcnt/=0 then
--> continue with burst
shiftcnt <= shiftcnt-1;
st_active <= '1';
if shiftcnt=1 then
-- last cycle of burst
st_stop <= '1';
in_ack <= '1';
active <= '0';
end if;
end if;
end if;
-- check if new result is ready
if mac_dnew='1' then
--> MAC done, update output
out_clk <= '1';
out_chan <= ochan(ochan'left);
out_data <= mac_dout;
end if;
-- delay channel-number to compensate for MAC delay
ochan <= ochan(ochan'left-1 downto 0) & ochan(0);
if st_mac_start='1' then
ochan(0) <= in_chan;
end if;
end if;
end process;
-- connect storage input
st_chan <= in_chan;
st_din <= in_data;
-- data storage
st: entity mt_fil_storage_slow
generic map (
COEFFS => COEFFS,
DCHAN => CHANNELS,
TAPS => TAPS,
RAMSTYLE => RAMSTYLE,
ROMSTYLE => ROMSTYLE
)
port map (
-- common
clk => clk,
reset => reset,
-- config
chan => st_chan,
-- input
in_load => st_start,
in_start => st_start,
in_stop => st_stop,
in_active => st_active,
in_data => st_din,
-- output
out_load => open,
out_start => st_mac_start,
out_stop => st_mac_stop,
out_active => st_mac_active,
out_data1 => st_mac_dout1,
out_data2 => st_mac_dout2,
out_coeff => st_mac_coeff
);
-- do create MAC cell
mac: entity mt_fil_mac_slow
port map (
-- common
clk => clk,
reset => reset,
-- control-path
start => st_mac_start,
active => st_mac_active,
presub => '0',
-- data input
smp1 => st_mac_dout1,
smp2 => st_mac_dout2,
coeff => st_mac_coeff,
-- data output
dnew => mac_dnew,
dout => mac_dout
);
end rtl;

View File

@ -0,0 +1,151 @@
---------------------------------------------------------------------------------------------------
-- Filename : mt_clktools.vhd
-- Project : maintech IP-Core toolbox
-- Purpose : Basic tools for clock/reset-generation
---------------------------------------------------------------------------------------------------
-----------------------------------------------------------------------------------
-- 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_reset_gen ---------------------------------------------------------------
-------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity mt_reset_gen is
port (
clk : in std_logic; -- some direct clock-input
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
);
end mt_reset_gen;
architecture rtl of mt_reset_gen is
-- reset generation
signal rst_roc2pll : std_logic_vector(15 downto 0) := (others=>'1'); -- delay between rst_roc <-> rst_pll
signal rst_pll2go : std_logic_vector( 5 downto 0) := (others=>'1'); -- delay between reset_pll <-> reset_I
signal reset_pll_i : std_logic := '1'; -- inner version of 'reset_pll'
signal reset_sys_i : std_logic; -- inner version of 'reset_sys'
-- TODO
signal lockcnt : unsigned(15 downto 0) := (others=>'0');
signal relock : std_logic := '0';
begin
-- generate PLL-reset
process(clk)
begin
if rising_edge(clk) then
-- if ext_rst='0' or relock='1' then
if relock='1' then
rst_roc2pll <= (others=>'1');
reset_pll_i <= '1';
else
rst_roc2pll <= '0' & rst_roc2pll(rst_roc2pll'high downto 1);
reset_pll_i <= rst_roc2pll(0);
end if;
end if;
end process;
-- TODO
process(clk)
begin
if rising_edge(clk) then
-- if ext_rst='0' or pll_locked='1' or relock='1' then
if pll_locked='1' or relock='1' then
lockcnt <= to_unsigned(0,16);
relock <= '0';
else
lockcnt <= lockcnt+1;
if lockcnt=30000-1 then
relock <= '1';
end if;
end if;
end if;
end process;
-- generate system-reset
process(clk, reset_pll_i)
begin
if reset_pll_i = '1' then
reset_sys_i <= '1';
rst_pll2go <= (others=>'1');
elsif rising_edge(clk) then
if pll_locked='0' then
rst_pll2go <= (others=>'1');
reset_sys_i <= '1';
else
rst_pll2go <= '0' & rst_pll2go(rst_pll2go'high downto 1);
reset_sys_i <= rst_pll2go(0);
end if;
end if;
end process;
-- output reset-signal
reset_sys <= reset_sys_i;
-- output PLL-reset
reset_pll <= reset_pll_i;
-- debug
dbg_ext <= ext_rst;
dbg_rst <= reset_pll_i;
dbg_lock <= pll_locked;
end;
-------------------------------------------------------------------------------
-- mt_reset_sync --------------------------------------------------------------
-------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
entity mt_reset_sync is
port (
clk : in std_logic;
rst_in : in std_logic;
rst_out : out std_logic
);
end mt_reset_sync;
architecture rtl of mt_reset_sync is
signal taps : std_logic_vector(3 downto 0);
begin
process(clk, rst_in)
begin
if rst_in='1' then
taps <= (others=>'1');
rst_out <= '1';
elsif rising_edge(clk) then
taps <= "0" & taps(taps'high downto 1);
rst_out <= taps(0);
end if;
end process;
end;

View File

@ -0,0 +1,182 @@
---------------------------------------------------------------------------------------------------
-- Filename : mt_toolbox.vhd
-- Project : maintech IP-Core toolbox
-- Purpose : maintech toolbox package
--
-- Description : declaration of common types, functions and attributes
-- used throughout the toolbox
---------------------------------------------------------------------------------------------------
-----------------------------------------------------------------------------------
-- 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;
package mt_toolbox is
--
-- basic types
--
subtype slv8_t is std_logic_vector(7 downto 0);
subtype slv16_t is std_logic_vector(15 downto 0);
subtype slv32_t is std_logic_vector(31 downto 0);
subtype byte_t is unsigned(7 downto 0);
subtype word_t is unsigned(15 downto 0);
subtype dword_t is unsigned(31 downto 0);
type slv8_array_t is array (natural range<>) of slv8_t;
type slv16_array_t is array (natural range<>) of slv16_t;
type slv32_array_t is array (natural range<>) of slv32_t;
type byte_array_t is array (natural range<>) of byte_t;
type word_array_t is array (natural range<>) of word_t;
type dword_array_t is array (natural range<>) of dword_t;
--
-- simple helper functions
--
function log2(x: natural) return positive;
--
-- type conversion helper
--
function to_slv8(x: std_logic) return std_logic_vector;
function to_slv8(x: std_logic_vector) return std_logic_vector;
function to_slv8(x: unsigned) return std_logic_vector;
function to_slv8(x: signed) return std_logic_vector;
function to_slv8(x: natural) return std_logic_vector;
function to_slv16(x: std_logic) return std_logic_vector;
function to_slv16(x: std_logic_vector) return std_logic_vector;
function to_slv16(x: unsigned) return std_logic_vector;
function to_slv16(x: signed) return std_logic_vector;
function to_slv16(x: natural) return std_logic_vector;
function to_slv32(x: std_logic) return std_logic_vector;
function to_slv32(x: std_logic_vector) return std_logic_vector;
function to_slv32(x: unsigned) return std_logic_vector;
function to_slv32(x: signed) return std_logic_vector;
function to_slv32(x: natural) return std_logic_vector;
--
-- common attributes
--
attribute syn_keep : boolean;
attribute syn_ramstyle : string;
attribute syn_romstyle : string;
end mt_toolbox;
package body mt_toolbox is
--
-- simple helper functions
--
-- calculate ceiling base 2 logarithm (returns always >=1)
function log2(x: natural) return positive is
variable x_tmp: natural;
variable y: positive;
begin
x_tmp := x-1;
y := 1;
while x_tmp > 1 loop
y := y+1;
x_tmp := x_tmp/2;
end loop;
return y;
end;
-- to_slv8 (pack basic types into "std_logic_vector(7 downto 0)")
function to_slv8(x: std_logic) return std_logic_vector is
variable res : std_logic_vector(7 downto 0);
begin
res := (0=>x,others=>'0');
return res;
end to_slv8;
function to_slv8(x: std_logic_vector) return std_logic_vector is
variable res : std_logic_vector(7 downto 0);
begin
res := (others=>'0');
res(x'length-1 downto 0) := x;
return res;
end to_slv8;
function to_slv8(x: unsigned) return std_logic_vector is
begin
return to_slv8(std_logic_vector(x));
end to_slv8;
function to_slv8(x: signed) return std_logic_vector is
begin
return to_slv8(std_logic_vector(x));
end to_slv8;
function to_slv8(x: natural) return std_logic_vector is
begin
return to_slv8(to_unsigned(x,8));
end to_slv8;
-- to_slv16 (pack basic types into "std_logic_vector(15 downto 0)")
function to_slv16(x: std_logic) return std_logic_vector is
variable res : std_logic_vector(15 downto 0);
begin
res := (0=>x,others=>'0');
return res;
end to_slv16;
function to_slv16(x: std_logic_vector) return std_logic_vector is
variable res : std_logic_vector(15 downto 0);
begin
res := (others=>'0');
res(x'length-1 downto 0) := x;
return res;
end to_slv16;
function to_slv16(x: unsigned) return std_logic_vector is
begin
return to_slv16(std_logic_vector(x));
end to_slv16;
function to_slv16(x: signed) return std_logic_vector is
begin
return to_slv16(std_logic_vector(x));
end to_slv16;
function to_slv16(x: natural) return std_logic_vector is
begin
return to_slv16(to_unsigned(x,16));
end to_slv16;
-- to_slv32 (pack basic types into "std_logic_vector(31 downto 0)")
function to_slv32(x: std_logic) return std_logic_vector is
variable res : std_logic_vector(31 downto 0);
begin
res := (0=>x,others=>'0');
return res;
end to_slv32;
function to_slv32(x: std_logic_vector) return std_logic_vector is
variable res : std_logic_vector(31 downto 0);
begin
res := (others=>'0');
res(x'length-1 downto 0) := x;
return res;
end to_slv32;
function to_slv32(x: unsigned) return std_logic_vector is
begin
return to_slv32(std_logic_vector(x));
end to_slv32;
function to_slv32(x: signed) return std_logic_vector is
begin
return to_slv32(std_logic_vector(x));
end to_slv32;
function to_slv32(x: natural) return std_logic_vector is
begin
return to_slv32(to_unsigned(x,32));
end to_slv32;
end mt_toolbox;

View File

@ -0,0 +1,131 @@
---------------------------------------------------------------------------------------------------
-- Filename : usbrx_toplevel.vhd
-- Project : OsmoSDR FPGA Firmware Testbench
-- Purpose : Decimation Filter Stimulus
---------------------------------------------------------------------------------------------------
-----------------------------------------------------------------------------------
-- 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.std_logic_misc.all;
use ieee.numeric_std.all;
use ieee.math_real.all;
library work;
use work.all;
use work.mt_toolbox.all;
use work.mt_filter.all;
use work.usbrx.all;
entity tb_filter is
end tb_filter;
architecture rtl of tb_filter is
-- common
signal clk : std_logic := '1';
signal reset : std_logic := '1';
-- config
signal config : usbrx_fil_config_t;
-- input
signal in_clk : std_logic;
signal in_i : signed(15 downto 0);
signal in_q : signed(15 downto 0);
-- output
signal out_clk : std_logic;
signal out_i : signed(15 downto 0);
signal out_q : signed(15 downto 0);
begin
-- generate clock
clk <= not clk after 500ns / 100.0;
reset <= '1', '0' after 123ns;
-- set config
config.decim <= "110";
-- input control
process
variable t : real := 0.0;
variable f : real := 1.0;
begin
in_clk <= '0';
in_i <= to_signed(0,16);
in_q <= to_signed(0,16);
wait until rising_edge(clk) and reset='0';
loop
-- wait some time
for i in 0 to 38 loop
wait until rising_edge(clk);
end loop;
-- get sample data
in_i <= to_signed(integer(cos(t)*10000.0),16);
in_q <= to_signed(0,16);
-- input sample
in_clk <= '1';
wait until rising_edge(clk);
in_clk <= '0';
-- update time
t := t + f/2000000.0*2.0*MATH_PI;
if t >= 2.0*MATH_PI then
t := t - 2.0*MATH_PI;
end if;
-- update frequency
f := f + 1.0;
if f>1000000.0 then
f := 1.0;
end if;
end loop;
wait;
end process;
-- create filter core
uut: entity usbrx_decimate
port map (
-- common
clk => clk,
reset => reset,
-- config
config => config,
-- input
in_clk => in_clk,
in_i => in_i,
in_q => in_q,
-- output
out_clk => out_clk,
out_i => out_i,
out_q => out_q
);
end rtl;

View File

@ -0,0 +1,356 @@
---------------------------------------------------------------------------------------------------
-- Filename : usbrx_toplevel.vhd
-- Project : OsmoSDR FPGA Firmware Testbench
-- Purpose : Toplevel Stimulus
---------------------------------------------------------------------------------------------------
-----------------------------------------------------------------------------------
-- 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.std_logic_misc.all;
use ieee.numeric_std.all;
library work;
use work.all;
use work.mt_toolbox.all;
entity tb_usbrx is
end tb_usbrx;
architecture rtl of tb_usbrx is
-- common
signal clk_in_pclk : std_logic := '1';
-- special control
signal dings : std_logic;
signal dingsrst : std_logic;
-- ADC interface
signal adc_cs : std_logic;
signal adc_sck : std_logic;
signal adc_sd1 : std_logic;
signal adc_sd2 : std_logic;
-- control SPI
signal ctl_int : std_logic;
signal ctl_cs : std_logic;
signal ctl_sck : std_logic;
signal ctl_mosi : std_logic;
signal ctl_miso : std_logic;
-- data SPIs
signal rx_clk : std_logic;
signal rx_syn : std_logic;
signal rx_dat : std_logic;
-- data SPIs
signal tx_clk : std_logic := '1';
signal tx_syn : std_logic;
signal tx_dat : std_logic;
-- gain PWMs
signal gain0 : std_logic;
signal gain1 : std_logic;
-- GPS
signal gps_1pps : std_logic;
signal gps_10k : std_logic;
-- gpios
signal gpio : std_logic_vector(9 downto 0);
-- virtual GNDs/VCCs
signal vgnd : std_logic_vector(11 downto 0);
signal vcc33 : std_logic_vector(11 downto 0);
signal vcc12 : std_logic_vector(4 downto 0);
begin
-- generate clocks
clk_in_pclk <= not clk_in_pclk after 500 ns / 30.0;
tx_clk <= '0'; --not tx_clk after 500 ns / 24.0;
-- special control
dings <= '0';
dingsrst <= '1'; --, '0' after 100 us, '1' after 200 us;
-- data SPIs
tx_syn <= '0';
tx_dat <= '0';
-- GPS
gps_1pps <= '0';
gps_10k <= '0';
-- gpios
gpio <= (others=>'H');
-- dummy ADC model
process
-- constant word1 : unsigned(15 downto 0) := "0010000000000001";
-- constant word2 : unsigned(15 downto 0) := "0001111111111110";
-- constant word1 : unsigned(15 downto 0) := "0001111111111111";
-- constant word2 : unsigned(15 downto 0) := "0001111111111111";
variable word1 : unsigned(15 downto 0) := "0011010111001101";
variable word2 : unsigned(15 downto 0) := "0001001111000101";
variable sreg1 : unsigned(15 downto 0);
variable sreg2 : unsigned(15 downto 0);
variable cnt : natural;
begin
adc_sd1 <= 'Z';
adc_sd2 <= 'Z';
cnt := 0;
loop
wait until falling_edge(adc_cs);
word1 := to_unsigned(8192 + cnt, 16);
word2 := to_unsigned(8192 - cnt, 16);
cnt := (cnt + 1) mod 8192;
sreg1 := word1;
sreg2 := word2;
adc_sd1 <= transport 'X', sreg1(15) after 5ns;
adc_sd2 <= transport 'X', sreg2(15) after 5ns;
sreg1 := shift_left(sreg1,1);
sreg2 := shift_left(sreg2,1);
il: loop
wait until rising_edge(adc_cs) or falling_edge(adc_sck);
exit when rising_edge(adc_cs);
adc_sd1 <= transport 'X', sreg1(15) after 11.0ns;
adc_sd2 <= transport 'X', sreg2(15) after 11.0ns;
sreg1 := shift_left(sreg1,1);
sreg2 := shift_left(sreg2,1);
end loop;
adc_sd1 <= transport 'X', 'Z' after 9.5ns;
adc_sd2 <= transport 'X', 'Z' after 9.5ns;
end loop;
end process;
-- SPI interface
process
-- write cycle
procedure spi_write(addr: in integer; data: in slv32_t) is
variable sreg : std_logic_vector(39 downto 0);
begin
-- assemble message
sreg(39) := '0';
sreg(38 downto 32) := std_logic_vector(to_unsigned(addr,7));
sreg(31 downto 0) := data;
-- assert CS
ctl_sck <= '1';
ctl_mosi <= '1';
ctl_cs <= '0';
wait for 250ns;
-- clock out data
for i in 39 downto 0 loop
ctl_sck <= '0';
ctl_mosi <= sreg(i);
wait for 250ns;
ctl_sck <= '1';
wait for 250ns;
end loop;
-- deassert CS
wait for 250ns;
ctl_cs <= '1';
wait for 250ns;
end procedure spi_write;
-- write cycle
procedure spi_writem(addr,count: in integer; data: in slv32_array_t) is
variable sreg : std_logic_vector(31 downto 0);
begin
-- assert CS
ctl_sck <= '1';
ctl_mosi <= '1';
ctl_cs <= '0';
wait for 250ns;
-- write command
sreg(7) := '0';
sreg(6 downto 0) := std_logic_vector(to_unsigned(addr,7));
for i in 7 downto 0 loop
ctl_sck <= '0';
ctl_mosi <= sreg(i);
wait for 250ns;
ctl_sck <= '1';
wait for 250ns;
end loop;
--write data
for j in 0 to count-1 loop
sreg := data(j);
for i in 31 downto 0 loop
ctl_sck <= '0';
ctl_mosi <= sreg(i);
wait for 250ns;
ctl_sck <= '1';
wait for 250ns;
end loop;
end loop;
-- deassert CS
wait for 250ns;
ctl_cs <= '1';
wait for 250ns;
end procedure spi_writem;
-- read cycle
procedure spi_read(addr,count: in integer; data: out slv32_array_t) is
variable sreg : std_logic_vector(7 downto 0);
begin
-- assemble message
sreg(7) := '1';
sreg(6 downto 0) := std_logic_vector(to_unsigned(addr,7));
-- assert CS
ctl_sck <= '1';
ctl_mosi <= '1';
ctl_cs <= '0';
wait for 250ns;
-- clock out command
for i in 7 downto 0 loop
ctl_sck <= '0';
ctl_mosi <= sreg(i);
wait for 250ns;
ctl_sck <= '1';
wait for 250ns;
end loop;
wait for 50us;
-- read data
for j in 0 to count-1 loop
for i in 31 downto 0 loop
ctl_sck <= '0';
wait for 250ns;
data(j)(i) := ctl_miso;
ctl_sck <= '1';
wait for 250ns;
if i=24 or i=16 or i=8 then
wait for 50us;
end if;
end loop;
end loop;
-- deassert CS
wait for 250ns;
ctl_cs <= '1';
wait for 250ns;
end procedure spi_read;
variable temp : slv32_array_t(0 to 5);
begin
ctl_cs <= '1';
ctl_sck <= '1';
ctl_mosi <= '1';
wait for 30us;
-- spi_write(4,x"00000001");
-- spi_read(0,1,temp);
-- spi_read(0,1,temp);
-- wait;
--
-- temp(0) := x"00000000";
-- temp(1) := x"12345678";
-- temp(2) := x"9ABCDEF0";
-- temp(3) := x"11233435";
-- temp(4) := x"23652662";
-- temp(5) := x"98735773";
-- spi_writem(0,6,temp);
--
-- temp := (others=>x"00000000");
-- spi_read(0,6,temp);
wait;
end process;
-- unit under test
uut: entity usbrx_toplevel
port map (
-- common
clk_in_pclk => clk_in_pclk,
-- special control
dings => dings,
dingsrst => dingsrst,
-- ADC interface
adc_cs => adc_cs,
adc_sck => adc_sck,
adc_sd1 => adc_sd1,
adc_sd2 => adc_sd2,
-- control SPI
ctl_int => ctl_int,
ctl_cs => ctl_cs,
ctl_sck => ctl_sck,
ctl_mosi => ctl_mosi,
ctl_miso => ctl_miso,
-- data SPIs
rx_clk => rx_clk,
rx_syn => rx_syn,
rx_dat => rx_dat,
-- data SPIs
tx_clk => tx_clk,
tx_syn => tx_syn,
tx_dat => tx_dat,
-- gain PWMs
gain0 => gain0,
gain1 => gain1,
-- GPS
gps_1pps => gps_1pps,
gps_10k => gps_10k,
-- gpios
gpio => gpio,
-- virtual GNDs/VCCs
vgnd => vgnd,
vcc33 => vcc33,
vcc12 => vcc12
);
end rtl;

View File

@ -0,0 +1,299 @@
---------------------------------------------------------------------------------------------------
-- Filename : usbrx_ad7357.vhd
-- Project : OsmoSDR FPGA Firmware
-- Purpose : AD7357 Interface
---------------------------------------------------------------------------------------------------
-----------------------------------------------------------------------------------
-- 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 xp2;
use xp2.all;
use xp2.components.all;
library work;
use work.all;
use work.mt_toolbox.all;
use work.usbrx.all;
entity usbrx_ad7357 is
port(
-- common
clk : in std_logic;
reset : in std_logic;
-- config
config : in usbrx_adc_config_t;
-- ADC interface
adc_cs : out std_logic;
adc_sck : out std_logic;
adc_sd1 : in std_logic;
adc_sd2 : in std_logic;
-- output
out_clk : out std_logic;
out_i : out unsigned(13 downto 0);
out_q : out unsigned(13 downto 0)
);
end usbrx_ad7357;
architecture rtl of usbrx_ad7357 is
-- internal types
type state_t is (S_ACQUISITION, S_CONVERT);
-- main status
signal state : state_t;
signal counter : unsigned(7 downto 0);
-- SCK generator
signal cg_div : unsigned(7 downto 0);
signal cg_count : unsigned(7 downto 0);
signal cg_phase : std_logic;
signal cg_ddr_a : std_logic;
signal cg_ddr_b : std_logic;
signal cg_renxt : std_logic;
signal cg_redge : std_logic;
-- chip select (+ delayed versions)
signal css : std_logic_vector(3 downto 0);
-- latch input on rising/falling edge of current cycle
-- (+ delayed versions)
signal latch_r : std_logic_vector(3 downto 0);
signal latch_f : std_logic_vector(3 downto 0);
-- input register stage #1
signal sd1_s1r : std_logic; -- SD1 - rising edge
signal sd1_s1f : std_logic; -- SD1 - falling edge
signal sd2_s1r : std_logic; -- SD2 - rising edge
signal sd2_s1f : std_logic; -- SD2 - falling edge
-- input register stage #2
signal sd1_s2r : std_logic; -- SD1 - rising edge
signal sd1_s2f : std_logic; -- SD1 - falling edge
signal sd2_s2r : std_logic; -- SD2 - rising edge
signal sd2_s2f : std_logic; -- SD2 - falling edge
-- input shift registers
signal sreg1 : std_logic_vector(13 downto 0);
signal sreg2 : std_logic_vector(13 downto 0);
-- output latches
signal onew : std_logic;
signal oreg1 : std_logic_vector(13 downto 0);
signal oreg2 : std_logic_vector(13 downto 0);
begin
-- SCL clock generator logic
process(clk)
begin
if rising_edge(clk) then
-- set default values
cg_renxt <= '0';
cg_redge <= cg_renxt;
latch_r <= latch_r(latch_r'left-1 downto 0) & '0';
latch_f <= latch_f(latch_f'left-1 downto 0) & '0';
-- get config
cg_div <= config.clkdiv;
-- get operation mode
if cg_div=0 or cg_div=1 then
--> full speed, just pass through clock
cg_ddr_a <= '0';
cg_ddr_b <= '1';
cg_renxt <= '1';
latch_f(0) <= '1';
else
--> divided clock, update divider-logic
if cg_count=0 then
-- toggle clock on FE in middle of cycle
cg_count <= cg_div - 2;
cg_phase <= not cg_phase;
cg_ddr_a <= cg_phase;
cg_ddr_b <= not cg_phase;
cg_renxt <= not cg_phase;
latch_r(0) <= cg_phase;
elsif cg_count=1 then
-- toggle clock on RE after this cycle
cg_count <= cg_div - 1;
cg_phase <= '0'; --not cg_phase;
cg_ddr_a <= '1'; --cg_phase;
cg_ddr_b <= '1'; --cg_phase;
latch_f(0) <= '1';
else
-- leave clock unchanged
cg_count <= cg_count - 2;
cg_ddr_a <= cg_phase;
cg_ddr_b <= cg_phase;
end if;
-- failsafe
if cg_count=1 and cg_div(0)='0' then
cg_count <= cg_div - 2;
end if;
end if;
-- handle reset
if reset='1' then
cg_div <= (others=>'1');
cg_count <= (others=>'0');
cg_phase <= '0';
cg_renxt <= '0';
cg_redge <= '0';
cg_ddr_a <= '1';
cg_ddr_b <= '1';
latch_r <= (others=>'0');
latch_f <= (others=>'0');
end if;
end if;
end process;
-- output register for SCLK
oddr: ODDRXC
port map (
clk => clk,
rst => reset,
da => cg_ddr_a,
db => cg_ddr_b,
q => adc_sck
);
-- main control logig
process(clk)
begin
if rising_edge(clk) then
-- set default values
css <= css(css'left-1 downto 0) & css(0);
-- update status
case state is
when S_ACQUISITION =>
-- doing ACQUISITION, wait until ready to start conversion
if cg_redge='1' then
-- new SCLK cycle, check if wait-counter has ellapsed
counter <= counter - 1;
if counter<=1 then
--> counter ellapsed, start conversion
state <= S_CONVERT;
counter <= to_unsigned(15,counter'length);
css(0) <= '0';
end if;
end if;
when S_CONVERT =>
-- doing conversion, wait until all bits are clocked out
if cg_redge='1' then
-- new SCLK cycle, check if bit-counter has ellapsed
counter <= counter - 1;
if counter=0 then
-- all bits received, return to ACQUISITION state
state <= S_ACQUISITION;
counter <= config.acqlen;
css(0) <= '1';
end if;
end if;
end case;
-- handle reset
if reset='1' then
state <= S_ACQUISITION; -- TODO
counter <= (others=>'0');
css <= (others=>'1');
end if;
end if;
end process;
-- output chip-select
adc_cs <= css(0);
-- input capture registers
iddr1: IDDRXC
port map (
clk => clk,
rst => '0',
ce => '1',
d => adc_sd1,
qa => sd1_s1r,
qb => sd1_s1f
);
iddr2: IDDRXC
port map (
clk => clk,
rst => '0',
ce => '1',
d => adc_sd2,
qa => sd2_s1r,
qb => sd2_s1f
);
-- input data handling
process(clk)
begin
if rising_edge(clk) then
-- set default valies
onew <= '0';
-- register input-bits once more
sd1_s2r <= sd1_s1r;
sd1_s2f <= sd1_s1f;
sd2_s2r <= sd2_s1r;
sd2_s2f <= sd2_s1f;
-- update shift-registers
if latch_r(3)='1' then
sreg1 <= sreg1(12 downto 0) & sd1_s2r;
sreg2 <= sreg2(12 downto 0) & sd2_s2r;
elsif latch_f(3)='1' then
sreg1 <= sreg1(12 downto 0) & sd1_s2f;
sreg2 <= sreg2(12 downto 0) & sd2_s2f;
end if;
-- latch away shift-register when requested
if css(2)='1' and css(3)='0' then
onew <= '1';
oreg1 <= sreg1;
oreg2 <= sreg2;
end if;
-- handle reset
if reset='1' then
sd1_s2r <= '0';
sd1_s2f <= '0';
sd2_s2r <= '0';
sd2_s2f <= '0';
sreg1 <= (others=>'0');
sreg2 <= (others=>'0');
oreg1 <= (others=>'0');
oreg2 <= (others=>'0');
onew <= '0';
end if;
end if;
end process;
-- set output
out_clk <= onew;
out_i <= unsigned(oreg1);
out_q <= unsigned(oreg2);
end rtl;

View File

@ -0,0 +1,218 @@
---------------------------------------------------------------------------------------------------
-- Filename : usbrx_decimate.vhd
-- Project : OsmoSDR FPGA Firmware
-- Purpose : Variable decimation filter
-- (possible factors: 1,2,4,8,16,32,64)
---------------------------------------------------------------------------------------------------
-----------------------------------------------------------------------------------
-- 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/>. --
-----------------------------------------------------------------------------------
-------------------------------------------------------------------------------
-- decimation filter ----------------------------------------------------------
-------------------------------------------------------------------------------
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.mt_filter.all;
use work.usbrx.all;
entity usbrx_decimate is
port (
-- common
clk : in std_logic;
reset : in std_logic;
-- config
config : in usbrx_fil_config_t;
-- input
in_clk : in std_logic;
in_i : in signed(15 downto 0);
in_q : in signed(15 downto 0);
-- output
out_clk : out std_logic;
out_i : out signed(15 downto 0);
out_q : out signed(15 downto 0)
);
end usbrx_decimate;
architecture rtl of usbrx_decimate is
-- config
signal active : std_logic_vector(5 downto 0);
-- adapted input
signal in_si : fir_dataword18;
signal in_sq : fir_dataword18;
-- filter input
signal fil_in_clk : std_logic_vector(5 downto 0);
signal fil_in_i : fir_databus18(5 downto 0);
signal fil_in_q : fir_databus18(5 downto 0);
-- filter output
signal fil_out_clk : std_logic_vector(5 downto 0);
signal fil_out_i : fir_databus18(5 downto 0);
signal fil_out_q : fir_databus18(5 downto 0);
-- unclipped output
signal nxt_clk : std_logic;
signal nxt_i : fir_dataword18;
signal nxt_q : fir_dataword18;
begin
-- convert input into 18bit signed
in_si <= signed(in_i) & "00";
in_sq <= signed(in_q) & "00";
-- control logic
process(clk)
variable tmp_i,tmp_q : fir_dataword18;
begin
if rising_edge(clk) then
-- get active stages
case to_integer(config.decim) is
when 0 => active <= "000000";
when 1 => active <= "000001";
when 2 => active <= "000011";
when 3 => active <= "000111";
when 4 => active <= "001111";
when 5 => active <= "011111";
when others => active <= "111111";
end case;
-- select output
case to_integer(config.decim) is
when 0 =>
nxt_clk <= in_clk;
nxt_i <= in_si;
nxt_q <= in_sq;
when 1 =>
nxt_clk <= fil_out_clk(0);
nxt_i <= fil_out_i(0);
nxt_q <= fil_out_q(0);
when 2 =>
nxt_clk <= fil_out_clk(1);
nxt_i <= fil_out_i(1);
nxt_q <= fil_out_q(1);
when 3 =>
nxt_clk <= fil_out_clk(2);
nxt_i <= fil_out_i(2);
nxt_q <= fil_out_q(2);
when 4 =>
nxt_clk <= fil_out_clk(3);
nxt_i <= fil_out_i(3);
nxt_q <= fil_out_q(3);
when 5 =>
nxt_clk <= fil_out_clk(4);
nxt_i <= fil_out_i(4);
nxt_q <= fil_out_q(4);
when others =>
nxt_clk <= fil_out_clk(5);
nxt_i <= fil_out_i(5);
nxt_q <= fil_out_q(5);
end case;
-- set output
out_clk <= nxt_clk;
if nxt_clk='1' then
tmp_i := nxt_i + 2;
tmp_q := nxt_q + 2;
out_i <= tmp_i(17 downto 2);
out_q <= tmp_q(17 downto 2);
end if;
-- handle reset
if reset='1' then
active <= (others=>'0');
nxt_clk <= '0';
nxt_i <= (others=>'0');
nxt_q <= (others=>'0');
out_clk <= '0';
out_i <= (others=>'0');
out_q <= (others=>'0');
end if;
end if;
end process;
process(in_clk,in_si,in_sq,fil_out_clk,fil_out_i,fil_out_q,active)
begin
-- feed first filter stage
fil_in_clk(0) <= in_clk and active(0);
fil_in_i(0) <= in_si;
fil_in_q(0) <= in_sq;
-- chain remaining filter stages
for i in 1 to 5 loop
fil_in_clk(i) <= fil_out_clk(i-1) and active(i-1);
fil_in_i(i) <= fil_out_i(i-1);
fil_in_q(i) <= fil_out_q(i-1);
end loop;
end process;
-- filter instance #1 (stage 0)
hbf1: entity usbrx_halfband
generic map (
N => 1
)
port map (
-- common
clk => clk,
reset => reset,
-- input
in_clk => fil_in_clk(0 downto 0),
in_i => fil_in_i(0 downto 0),
in_q => fil_in_q(0 downto 0),
-- output
out_clk => fil_out_clk(0 downto 0),
out_i => fil_out_i(0 downto 0),
out_q => fil_out_q(0 downto 0)
);
-- filter instance #2 (stage 1-5)
hbf2: entity usbrx_halfband
generic map (
N => 5
)
port map (
-- common
clk => clk,
reset => reset,
-- input
in_clk => fil_in_clk(5 downto 1),
in_i => fil_in_i(5 downto 1),
in_q => fil_in_q(5 downto 1),
-- output
out_clk => fil_out_clk(5 downto 1),
out_i => fil_out_i(5 downto 1),
out_q => fil_out_q(5 downto 1)
);
end rtl;

View File

@ -0,0 +1,105 @@
---------------------------------------------------------------------------------------------------
-- Filename : usbrx_halfband.vhd
-- Project : OsmoSDR FPGA Firmware
-- Purpose : Programmable sample value offset
---------------------------------------------------------------------------------------------------
-----------------------------------------------------------------------------------
-- 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_offset is
port (
-- common
clk : in std_logic;
reset : in std_logic;
-- config
config : in usbrx_off_config_t;
-- input
in_clk : in std_logic;
in_i : in unsigned(13 downto 0);
in_q : in unsigned(13 downto 0);
-- output
out_clk : out std_logic;
out_i : out signed(15 downto 0);
out_q : out signed(15 downto 0)
);
end usbrx_offset;
architecture rtl of usbrx_offset is
-- clip & saturate sample
function doClipValue(x : signed) return signed is
begin
if x >= 32768 then
-- overflow
return to_signed(+32767,16);
elsif x < -32768 then
-- underflow
return to_signed(-32768,16);
else
-- in range
return x(15 downto 0);
end if;
end doClipValue;
begin
-- control logic
process(clk)
variable s16i, s16q : signed(15 downto 0);
variable s17i, s17q : signed(16 downto 0);
begin
if rising_edge(clk) then
-- passthough clock
out_clk <= in_clk;
-- 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";
-- add offset
s17i := resize(s16i,17) + resize(config.ioff,17);
s17q := resize(s16q,17) + resize(config.qoff,17);
-- clip output
out_i <= doClipValue(s17i);
out_q <= doClipValue(s17q);
end if;
-- handle reset
if reset='1' then
out_clk <= '0';
out_i <= (others=>'0');
out_q <= (others=>'0');
end if;
end if;
end process;
end rtl;

View File

@ -0,0 +1,191 @@
---------------------------------------------------------------------------------------------------
-- Filename : usbrx_ssc.vhd
-- Project : OsmoSDR FPGA Firmware
-- Purpose : ATSAM3U SSC Interface
---------------------------------------------------------------------------------------------------
-----------------------------------------------------------------------------------
-- 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_ssc is
port(
-- common
clk : in std_logic;
reset : in std_logic;
-- config
config : in usbrx_ssc_config_t;
-- output
in_clk : in std_logic;
in_i : in signed(15 downto 0);
in_q : in signed(15 downto 0);
-- SSC interface
ssc_clk : out std_logic;
ssc_syn : out std_logic;
ssc_dat : out std_logic
);
end usbrx_ssc;
architecture rtl of usbrx_ssc is
-- CLK generator
signal cg_div : unsigned(7 downto 0);
signal cg_phase : std_logic;
signal cg_tick : std_logic;
-- shift register
signal sreg : std_logic_vector(31 downto 0);
signal remain : unsigned(5 downto 0);
signal nxtsyn : std_logic;
-- input latch
signal lreg : std_logic_vector(31 downto 0);
signal filled : std_logic;
-- helper function
function to_signed(x : unsigned) return signed is
begin
return signed((not x(x'left)) & x(x'left-1 downto 0));
end to_signed;
function pack(i,q : unsigned) return slv32_t is
variable res : slv32_t := (others=>'0');
begin
res(31 downto 32-i'length) := std_logic_vector(to_signed(i));
res(15 downto 16-q'length) := std_logic_vector(to_signed(q));
return res;
end pack;
function pack(i,q : signed) return slv32_t is
variable res : slv32_t := (others=>'0');
begin
res(31 downto 32-i'length) := std_logic_vector(i);
res(15 downto 16-q'length) := std_logic_vector(q);
return res;
end pack;
-- debug
signal counter1 : unsigned(15 downto 0);
signal counter2 : unsigned(15 downto 0);
begin
-- clock generator
process(clk)
begin
if rising_edge(clk) then
-- set default values
cg_tick <= '0';
-- update clock-divider
if cg_div=0 then
-- toggle phase
cg_phase <= not cg_phase;
cg_div <= config.clkdiv;
-- set 'tick'-flag when generating falling edge
if cg_phase='1' then
cg_tick <= '1';
end if;
else
-- stay in current phase
cg_div <= cg_div-1;
end if;
-- update output
ssc_clk <= cg_phase;
-- handle reset
if reset='1' then
cg_div <= (others=>'0');
cg_phase <= '0';
cg_tick <= '0';
ssc_clk <= '0';
end if;
end if;
end process;
-- output shift register
process(clk)
begin
if rising_edge(clk) then
-- wait for output-clock
if cg_tick='1' then
-- update output
ssc_dat <= sreg(sreg'left);
ssc_syn <= nxtsyn;
sreg <= sreg(sreg'left-1 downto 0) & '0';
nxtsyn <= '0';
-- consume bit
if remain > 0 then
remain <= remain - 1;
end if;
-- reload shift-register when possible
if filled='1' and remain<=1 then
filled <= '0';
remain <= to_unsigned(32, remain'length);
nxtsyn <= '1';
sreg <= lreg;
end if;
end if;
-- handle incoming samples
if in_clk='1' then
if filled='0' then
-- latch sample
lreg <= pack(in_i,in_q);
filled <= '1';
-- apply test-mode
if config.tmode='1' then
lreg <= pack(counter1,counter2);
counter1 <= counter1 + 1;
counter2 <= counter2 - 1;
end if;
else
--> overflow
report "usbrx_ssc: input too fast"
severity warning;
end if;
end if;
-- handle reset
if reset='1' then
sreg <= (others=>'0');
remain <= (others=>'0');
nxtsyn <= '0';
lreg <= (others=>'0');
filled <= '0';
ssc_syn <= '0';
ssc_dat <= '0';
counter1 <= (others=>'0');
counter2 <= (others=>'1');
end if;
end if;
end process;
end rtl;

View File

@ -0,0 +1,505 @@
---------------------------------------------------------------------------------------------------
-- Filename : usbrx_halfband.vhd
-- Project : OsmoSDR FPGA Firmware
-- Purpose : Multichannel Halfband Decimation Filter
---------------------------------------------------------------------------------------------------
-----------------------------------------------------------------------------------
-- 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/>. --
-----------------------------------------------------------------------------------
-------------------------------------------------------------------------------
-- halfband decimation filter - input cache/control ---------------------------
-------------------------------------------------------------------------------
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.mt_filter.all;
entity usbrx_halfband_ictrl is
generic (
N : natural := 3
);
port (
-- common
clk : in std_logic;
reset : in std_logic;
-- input
in_clk : in std_logic_vector(N-1 downto 0);
in_i : in fir_databus18(N-1 downto 0);
in_q : in fir_databus18(N-1 downto 0);
-- output
out_ready : in std_logic;
out_clk : out std_logic;
out_chan : out unsigned(log2(N)-1 downto 0);
out_i0 : out fir_dataword18;
out_i1 : out fir_dataword18;
out_q0 : out fir_dataword18;
out_q1 : out fir_dataword18
);
end usbrx_halfband_ictrl;
architecture rtl of usbrx_halfband_ictrl is
-- control
signal phase : std_logic_vector(N-1 downto 0);
signal tmp_i : fir_databus18(N-1 downto 0);
signal tmp_q : fir_databus18(N-1 downto 0);
signal oclk : std_logic;
-- output
signal pending : std_logic_vector(N-1 downto 0);
signal cache_i0 : fir_databus18(N-1 downto 0);
signal cache_i1 : fir_databus18(N-1 downto 0);
signal cache_q0 : fir_databus18(N-1 downto 0);
signal cache_q1 : fir_databus18(N-1 downto 0);
begin
-- control logic
process(clk)
variable found : std_logic;
begin
if rising_edge(clk) then
-- set default values
oclk <= '0';
-- check if we are allowed to output the next entry
if out_ready='1' and oclk='0' then
-- search for pending cache-entry
found := '0';
for i in 0 to N-1 loop
if found='0' and pending(i)='1' then
--> output entry
oclk <= '1';
out_chan <= to_unsigned(i,out_chan'length);
out_i0 <= cache_i0(i);
out_i1 <= cache_i1(i);
out_q0 <= cache_q0(i);
out_q1 <= cache_q1(i);
-- update status
pending(i) <= '0';
found := '1';
end if;
end loop;
end if;
-- handle incoming samples
for i in in_clk'range loop
if in_clk(i)='1' then
-- write sample into cache
if phase(i)='0' then
tmp_i(i) <= in_i(i);
tmp_q(i) <= in_q(i);
else
pending(i) <= '1';
cache_i0(i) <= tmp_i(i);
cache_q0(i) <= tmp_q(i);
cache_i1(i) <= in_i(i);
cache_q1(i) <= in_q(i);
end if;
phase(i) <= not phase(i);
-- debug check
assert phase(i)='0' or pending(i)='0'
report "usbrx_halfband_ictrl: input too fast"
severity error;
end if;
end loop;
-- handle reset
if reset='1' then
phase <= (others=>'0');
tmp_i <= (others=>(others=>'0'));
tmp_q <= (others=>(others=>'0'));
pending <= (others=>'0');
cache_i0 <= (others=>(others=>'0'));
cache_i1 <= (others=>(others=>'0'));
cache_q0 <= (others=>(others=>'0'));
cache_q1 <= (others=>(others=>'0'));
oclk <= '0';
out_chan <= (others=>'0');
out_i0 <= (others=>'0');
out_i1 <= (others=>'0');
out_q0 <= (others=>'0');
out_q1 <= (others=>'0');
end if;
end if;
end process;
-- connect output-clock
out_clk <= oclk;
end rtl;
-------------------------------------------------------------------------------
-- halfband decimation filter - output control --------------------------------
-------------------------------------------------------------------------------
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.mt_filter.all;
entity usbrx_halfband_octrl is
generic (
N : natural := 3
);
port (
-- common
clk : in std_logic;
reset : in std_logic;
-- input
in_clk : in std_logic;
in_chan : in unsigned(log2(2*N)-1 downto 0);
in_data : in fir_dataword18;
-- output
out_clk : out std_logic_vector(N-1 downto 0);
out_i : out fir_databus18(N-1 downto 0);
out_q : out fir_databus18(N-1 downto 0)
);
end usbrx_halfband_octrl;
architecture rtl of usbrx_halfband_octrl is
-- cache
signal tmp_i : fir_databus18(N-1 downto 0);
begin
-- control logic
process(clk)
variable sel : natural range 0 to N-1;
begin
if rising_edge(clk) then
-- set default values
out_clk <= (others=>'0');
-- handle input
if in_clk='1' then
sel := to_integer(in_chan)/2;
for i in out_clk'range loop
if sel=i then
if in_chan(0)='0' then
-- cache result
tmp_i(i) <= in_data;
else
-- output result
out_clk(i) <= '1';
out_i(i) <= tmp_i(i);
out_q(i) <= in_data;
end if;
end if;
end loop;
end if;
-- handle reset
if reset='1' then
tmp_i <= (others=>(others=>'0'));
out_clk <= (others=>'0');
out_i <= (others=>(others=>'0'));
out_q <= (others=>(others=>'0'));
end if;
end if;
end process;
end rtl;
-------------------------------------------------------------------------------
-- halfband decimation filter -------------------------------------------------
-------------------------------------------------------------------------------
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.mt_filter.all;
entity usbrx_halfband is
generic (
N : natural := 3
);
port (
-- common
clk : in std_logic;
reset : in std_logic;
-- input
in_clk : in std_logic_vector(N-1 downto 0);
in_i : in fir_databus18(N-1 downto 0);
in_q : in fir_databus18(N-1 downto 0);
-- output
out_clk : out std_logic_vector(N-1 downto 0);
out_i : out fir_databus18(N-1 downto 0);
out_q : out fir_databus18(N-1 downto 0)
);
end usbrx_halfband;
architecture rtl of usbrx_halfband is
-- internal types
type state_t is (S_IDLE, S_FILTER_I, S_FILTER_Q, S_COOLDOWN);
-- status
signal state : state_t;
-- input control
signal ic_ready : std_logic;
signal ic_clk : std_logic;
signal ic_chan : unsigned(log2(N)-1 downto 0);
signal ic_i0 : fir_dataword18;
signal ic_i1 : fir_dataword18;
signal ic_q0 : fir_dataword18;
signal ic_q1 : fir_dataword18;
-- next output
signal on_clk : std_logic;
signal on_chan : unsigned(log2(2*N)-1 downto 0);
signal on_dat1 : fir_dataword18;
signal on_dat2 : fir_dataword18;
-- output control
signal oc_iclk : std_logic;
signal oc_ichan : unsigned(log2(2*N)-1 downto 0);
signal oc_idata : fir_dataword18;
-- FIR input
signal fir_iclk : std_logic;
signal fir_iack : std_logic;
signal fir_idata : fir_dataword18;
signal fir_ichan : unsigned(log2(2*N)-1 downto 0);
-- FIR output
signal fir_oclk : std_logic;
signal fir_ochan : unsigned(log2(2*N)-1 downto 0);
signal fir_odata : fir_dataword18;
-- center samples
signal cent_i : fir_databus18(N-1 downto 0);
signal cent_q : fir_databus18(N-1 downto 0);
-- coefficients for 2x-FIR-interpolator
-- (halfband, order 48, wpass 0.40)
constant coeffs : fir_coefficients(0 to 11) := (
-52, 151, -354, 715,
-1307, 2227, -3614, 5691,
-8907, 14403, -26386, 82957
);
begin
-- control logic
process(clk)
variable sel : natural range 0 to N-1;
begin
if rising_edge(clk) then
-- set default values
fir_iclk <= '0';
oc_iclk <= '0';
on_clk <= '0';
-- filter control
case state is
when S_IDLE =>
-- wait for new sample-pair
if ic_clk='1' then
-- start filter (I)
fir_iclk <= '1';
fir_idata <= ic_i1;
fir_ichan <= resize(ic_chan & "0", fir_ichan'length);
-- update status
state <= S_FILTER_I;
end if;
when S_FILTER_I =>
-- wait until filtering is done
if fir_iack='1' then
-- start filter (Q)
fir_iclk <= '1';
fir_idata <= ic_q1;
fir_ichan <= resize(ic_chan & "1", fir_ichan'length);
-- update status
state <= S_FILTER_Q;
end if;
when S_FILTER_Q =>
-- wait until filtering is done
if fir_iack='1' then
-- update status
state <= S_COOLDOWN;
end if;
when S_COOLDOWN =>
-- TODO: get rid of state
if fir_oclk='1' then
state <= S_IDLE;
end if;
end case;
-- fetch FIR result and corresonding center-sample
if fir_oclk='1' then
on_clk <= '1';
on_chan <= fir_ochan;
on_dat1 <= fir_odata;
sel := to_integer(fir_ochan)/2;
if fir_ochan(0)='0'
then on_dat2 <= cent_i(sel);
else on_dat2 <= cent_q(sel);
end if;
end if;
-- create final result
if on_clk='1' then
oc_iclk <= '1';
oc_ichan <= on_chan;
oc_idata <= resize((resize(on_dat1,19) + resize(on_dat2,19)) / 2,18);
end if;
-- handle reset
if reset='1' then
state <= S_IDLE;
fir_iclk <= '0';
fir_idata <= (others=>'0');
fir_ichan <= (others=>'0');
oc_iclk <= '0';
oc_ichan <= (others=>'0');
oc_idata <= (others=>'0');
on_clk <= '0';
on_chan <= (others=>'0');
on_dat1 <= (others=>'0');
on_dat2 <= (others=>'0');
end if;
end if;
end process;
-- create ready-flag
ic_ready <= '1' when state=S_IDLE else '0';
-- shift register for center-sample
sreg: for i in 0 to N-1 generate
subtype entry_t is signed(35 downto 0);
type sreg_t is array(natural range<>) of entry_t;
signal sreg : sreg_t(11 downto 0) := (others=>(others=>'0'));
begin
-- infer shift-register
process(clk)
variable temp : entry_t;
begin
if rising_edge(clk) then
if ic_clk='1' and to_integer(ic_chan)=i then
temp := ic_q0 & ic_i0;
sreg <= sreg(sreg'left-1 downto 0) & temp;
end if;
end if;
end process;
-- output center-sample
cent_i(i) <= sreg(sreg'left)(17 downto 0);
cent_q(i) <= sreg(sreg'left)(35 downto 18);
end generate;
-- input control
ic: entity usbrx_halfband_ictrl
generic map (
N => N
)
port map (
-- common
clk => clk,
reset => reset,
-- input
in_clk => in_clk,
in_i => in_i,
in_q => in_q,
-- output
out_ready => ic_ready,
out_clk => ic_clk,
out_chan => ic_chan,
out_i0 => ic_i0,
out_i1 => ic_i1,
out_q0 => ic_q0,
out_q1 => ic_q1
);
-- FIR filter core
fir: entity mt_fir_symmetric_slow
generic map (
CHANNELS => 2*N,
TAPS => 12,
COEFFS => coeffs,
RAMSTYLE => "block_ram",
ROMSTYLE => "logic"
)
port map (
-- common
clk => clk,
reset => reset,
-- input port
in_clk => fir_iclk,
in_ack => fir_iack,
in_data => fir_idata,
in_chan => fir_ichan,
-- output port
out_clk => fir_oclk,
out_chan => fir_ochan,
out_data => fir_odata
);
-- output control
oc: entity usbrx_halfband_octrl
generic map (
N => N
)
port map (
-- common
clk => clk,
reset => reset,
-- input
in_clk => oc_iclk,
in_chan => oc_ichan,
in_data => oc_idata,
-- output
out_clk => out_clk,
out_i => out_i,
out_q => out_q
);
end rtl;

View File

@ -0,0 +1,165 @@
---------------------------------------------------------------------------------------------------
-- Filename : usbrx_clkgen.vhd
-- Project : OsmoSDR FPGA Firmware
-- Purpose : Clock Management
---------------------------------------------------------------------------------------------------
-----------------------------------------------------------------------------------
-- 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.std_logic_misc.all;
use ieee.numeric_std.all;
library xp2;
use xp2.all;
use xp2.components.all;
library work;
use work.all;
use work.mt_toolbox.all;
entity usbrx_clkgen is
port(
-- clock input
clk_30_pclk : in std_logic; -- 30MHz
ext_rst : in std_logic; -- external reset
-- system clock
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
);
end usbrx_clkgen;
architecture rtl of usbrx_clkgen is
-- reset generation
signal rst_pll : std_logic; -- reset signal for PLLs
signal pll_locked : std_logic; -- PLLs locked
signal reset_i : std_logic; -- reset-signal
-- system clock management
signal clk_80_pll : std_logic;
-- enusure that signal-names are kept (important for timing contraints)
attribute syn_keep of clk_80_pll : signal is true;
-- component declaration
component EPLLD1
generic (CLKOK_BYPASS : in String; CLKOS_BYPASS : in String;
CLKOP_BYPASS : in String; DUTY : in Integer;
PHASEADJ : in String; PHASE_CNTL : in String;
CLKOK_DIV : in Integer; CLKFB_DIV : in Integer;
CLKOP_DIV : in Integer; CLKI_DIV : in Integer;
FIN : in String);
port (CLKI: in std_logic; CLKFB: in std_logic; RST: in std_logic;
RSTK: in std_logic; DPAMODE: in std_logic; DRPAI3: in std_logic;
DRPAI2: in std_logic; DRPAI1: in std_logic; DRPAI0: in std_logic;
DFPAI3: in std_logic; DFPAI2: in std_logic; DFPAI1: in std_logic;
DFPAI0: in std_logic; PWD: in std_logic; CLKOP: out std_logic;
CLKOS: out std_logic; CLKOK: out std_logic; LOCK: out std_logic;
CLKINTFB: out std_logic);
end component;
begin
--
-- reset generation
--
-- generate asynchronous reset-signal
rg: entity mt_reset_gen
port map (
clk => clk_30_pclk,
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
);
-- sync reset to clock-domains
rs30: entity mt_reset_sync
port map (
clk => clk_30_pclk,
rst_in => reset_i,
rst_out => rst_30
);
rs80: entity mt_reset_sync
port map (
clk => clk_80_pll,
rst_in => reset_i,
rst_out => rst_80
);
--
-- system clock
--
-- PLL for system-clock
pll : EPLLD1
generic map (
FIN => "30.0",
CLKOK_BYPASS => "DISABLED",
CLKOS_BYPASS => "DISABLED",
CLKOP_BYPASS => "DISABLED",
PHASE_CNTL => "STATIC",
DUTY => 8,
PHASEADJ => "0.0",
CLKOK_DIV => 2,
CLKOP_DIV => 8,
CLKFB_DIV => 8,
CLKI_DIV => 3
)
port map (
CLKI => clk_30_pclk,
CLKFB => clk_80_pll,
RST => rst_pll,
RSTK => '0',
DPAMODE => '0',
DRPAI3 => '0',
DRPAI2 => '0',
DRPAI1 => '0',
DRPAI0 => '0',
DFPAI3 => '0',
DFPAI2 => '0',
DFPAI1 => '0',
DFPAI0 => '0',
PWD => '0',
CLKOP => clk_80_pll,
CLKOS => open,
CLKOK => open,
LOCK => pll_locked,
CLKINTFB=> open
);
-- output clocks
clk_30 <= clk_30_pclk;
clk_80 <= clk_80_pll;
end rtl;

View File

@ -0,0 +1,100 @@
---------------------------------------------------------------------------------------------------
-- Filename : usbrx_pwm.vhd
-- Project : OsmoSDR FPGA Firmware
-- Purpose : PWM Generator
---------------------------------------------------------------------------------------------------
-----------------------------------------------------------------------------------
-- 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_pwm is
port(
-- common
clk : in std_logic;
reset : in std_logic;
-- config
config : in usbrx_pwm_config_t;
-- PWM output
pwm0 : out std_logic;
pwm1 : out std_logic
);
end usbrx_pwm;
architecture rtl of usbrx_pwm is
-- status
signal counter0 : unsigned(15 downto 0);
signal counter1 : unsigned(15 downto 0);
signal out0 : std_logic;
signal out1 : std_logic;
begin
process(clk)
begin
if rising_edge(clk) then
-- update counter #0
counter0 <= counter0 - 1;
if counter0 = 0 then
counter0 <= config.freq0;
end if;
-- update counter #1
counter1 <= counter1 - 1;
if counter1 = 0 then
counter1 <= config.freq1;
end if;
-- update output #0
if counter0 < config.duty0
then out0 <= '1';
else out0 <= '0';
end if;
-- update output #1
if counter1 < config.duty1
then out1 <= '1';
else out1 <= '0';
end if;
-- output register
pwm0 <= out0;
pwm1 <= out1;
-- handle reset
if reset='1' then
counter0 <= (others=>'0');
counter1 <= (others=>'0');
out0 <= '0';
out1 <= '0';
pwm0 <= '0';
pwm1 <= '0';
end if;
end if;
end process;
end rtl;

View File

@ -0,0 +1,194 @@
---------------------------------------------------------------------------------------------------
-- Filename : usbrx_regbank.vhd
-- Project : OsmoSDR FPGA Firmware
-- Purpose : Registerbank
---------------------------------------------------------------------------------------------------
-----------------------------------------------------------------------------------
-- 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_regbank is
port(
-- common
clk : in std_logic;
reset : in std_logic;
-- config
cfg_pwm : out usbrx_pwm_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);
-- SPI interface
spi_ncs : in std_logic;
spi_sclk : in std_logic;
spi_mosi : in std_logic;
spi_miso : out std_logic
);
end usbrx_regbank;
architecture rtl of usbrx_regbank is
-- bus interface
signal bus_rena : std_logic;
signal bus_wena : std_logic;
signal bus_addr : unsigned(6 downto 0);
signal bus_rdata : std_logic_vector(31 downto 0);
signal bus_wdata : std_logic_vector(31 downto 0);
-- registers
signal reg_pwm1 : std_logic_vector(31 downto 0);
signal reg_pwm2 : std_logic_vector(31 downto 0);
signal reg_adc : std_logic_vector(15 downto 0);
signal reg_ssc1 : std_logic_vector(0 downto 0);
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);
-- avoid block-ram inference
attribute syn_romstyle : string;
attribute syn_romstyle of rtl : architecture is "logic";
begin
-- SPI slave
spi: entity usbrx_spi
port map (
-- common
clk => clk,
reset => reset,
-- SPI interface
spi_ncs => spi_ncs,
spi_sclk => spi_sclk,
spi_mosi => spi_mosi,
spi_miso => spi_miso,
-- bus interface
bus_rena => bus_rena,
bus_wena => bus_wena,
bus_addr => bus_addr,
bus_rdata => bus_rdata,
bus_wdata => bus_wdata
);
-- handle requests
process(reset, clk)
begin
if reset = '1' then
bus_rdata <= (others=>'0');
reg_pwm1 <= x"17701F3F";
reg_pwm2 <= x"07D01F3F";
reg_adc <= x"0401";
reg_ssc1 <= "0";
reg_ssc2 <= x"01";
reg_fil <= "011";
reg_off <= x"00000000";
elsif rising_edge(clk) then
-- output zeros by default
bus_rdata <= (others=>'0');
-- handle requests
case to_integer(bus_addr) is
when 0 =>
-- identification
bus_rdata <= x"DEADBEEF";
when 1 =>
-- PWM #1
bus_rdata <= reg_pwm1;
if bus_wena='1' then
reg_pwm1 <= bus_wdata(31 downto 0);
end if;
when 2 =>
-- PWM #2
bus_rdata <= reg_pwm2;
if bus_wena='1' then
reg_pwm2 <= bus_wdata(31 downto 0);
end if;
when 3 =>
-- ADC interface
bus_rdata <= to_slv32(reg_adc);
if bus_wena='1' then
reg_adc <= bus_wdata(15 downto 0);
end if;
when 4 =>
-- SSC interface
bus_rdata( 0 downto 0) <= reg_ssc1;
bus_rdata(15 downto 8) <= reg_ssc2;
if bus_wena='1' then
reg_ssc1 <= bus_wdata( 0 downto 0);
reg_ssc2 <= bus_wdata(15 downto 8);
end if;
when 5 =>
-- ADC Quickhack
bus_rdata(15 downto 0) <= to_slv16(adc_i);
bus_rdata(31 downto 16) <= to_slv16(adc_q);
when 6 =>
-- decimation filter
bus_rdata <= to_slv32(reg_fil);
if bus_wena='1' then
reg_fil <= bus_wdata(2 downto 0);
end if;
when 7 =>
-- offset stage
bus_rdata <= reg_off;
if bus_wena='1' then
reg_off <= bus_wdata(31 downto 0);
end if;
when others =>
-- invalid address
null;
end case;
end if;
end process;
-- map registers to config
cfg_pwm.freq0 <= unsigned(reg_pwm1(15 downto 0));
cfg_pwm.freq1 <= unsigned(reg_pwm2(15 downto 0));
cfg_pwm.duty0 <= unsigned(reg_pwm1(31 downto 16));
cfg_pwm.duty1 <= unsigned(reg_pwm2(31 downto 16));
cfg_adc.clkdiv <= unsigned(reg_adc( 7 downto 0));
cfg_adc.acqlen <= unsigned(reg_adc(15 downto 8));
cfg_ssc.tmode <= reg_ssc1(0);
cfg_ssc.clkdiv <= unsigned(reg_ssc2);
cfg_fil.decim <= unsigned(reg_fil);
cfg_fil.decim <= unsigned(reg_fil);
cfg_off.ioff <= signed(reg_off(15 downto 0));
cfg_off.qoff <= signed(reg_off(31 downto 16));
end rtl;

View File

@ -0,0 +1,215 @@
---------------------------------------------------------------------------------------------------
-- Filename : usbrx_spi.vhd
-- Project : OsmoSDR FPGA Firmware
-- Purpose : SPI Slave Implementation
---------------------------------------------------------------------------------------------------
-----------------------------------------------------------------------------------
-- 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;
entity usbrx_spi is
port(
-- common
clk : in std_logic;
reset : in std_logic;
-- SPI interface
spi_ncs : in std_logic;
spi_sclk : in std_logic;
spi_mosi : in std_logic;
spi_miso : out std_logic;
-- bus interface
bus_rena : out std_logic;
bus_wena : out std_logic;
bus_addr : out unsigned(6 downto 0);
bus_rdata : in std_logic_vector(31 downto 0);
bus_wdata : out std_logic_vector(31 downto 0)
);
end usbrx_spi;
architecture rtl of usbrx_spi is
-- internal types
type state_t is (S_COMMAND, S_WRITE, S_READ2, S_READ3, S_READ4);
-- IO-registers
signal iob_ncs : std_logic;
signal iob_sclk : std_logic;
signal iob_mosi : std_logic;
-- synchronized inputs
signal sync_ncs : std_logic;
signal sync_sclk : std_logic;
signal sync_mosi : std_logic;
-- edge detection
signal last_sclk : std_logic;
signal last_re : std_logic;
signal last_fe : std_logic;
-- SPI slave
signal state : state_t;
signal remain : unsigned(5 downto 0);
signal sireg : std_logic_vector(31 downto 0);
signal soreg : std_logic_vector(32 downto 0);
signal addr : unsigned(6 downto 0);
begin
-- IOBs
process(clk)
begin
if rising_edge(clk) then
iob_ncs <= spi_ncs;
iob_sclk <= spi_sclk;
iob_mosi <= spi_mosi;
if iob_ncs='0'
then spi_miso <= soreg(32);
else spi_miso <= '1';
end if;
end if;
end process;
-- input synchronizer
process(clk,reset)
begin
if reset = '1' then
sync_ncs <= '1';
sync_sclk <= '0';
sync_mosi <= '0';
elsif rising_edge(clk) then
sync_ncs <= iob_ncs;
sync_sclk <= iob_sclk;
sync_mosi <= iob_mosi;
end if;
end process;
-- SPI slave
process(clk,reset)
variable re,fe : std_logic;
begin
if reset = '1' then
last_sclk <= '0';
last_re <= '0';
last_fe <= '0';
state <= S_COMMAND;
remain <= (others=>'0');
sireg <= (others=>'1');
soreg <= (others=>'1');
addr <= (others=>'0');
bus_rena <= '0';
bus_wena <= '0';
bus_addr <= (others=>'0');
bus_wdata <= (others=>'0');
elsif rising_edge(clk) then
-- set default values
bus_rena <= '0';
bus_wena <= '0';
-- detect edges on clock line
last_sclk <= sync_sclk;
re := sync_sclk and (not last_sclk);
fe := (not sync_sclk) and last_sclk;
last_re <= re;
last_fe <= fe;
-- update shift-registers
if re='1' then
sireg <= sireg(30 downto 0) & sync_mosi;
end if;
if fe='1' then
soreg <= soreg(31 downto 0) & '1';
end if;
-- check state of chip-select
if sync_ncs='1' then
--> CS deasserted, reset slave
state <= S_COMMAND;
remain <= to_unsigned(7,6);
else
--> CS asserted, tick state-machine
case state is
when S_COMMAND =>
-- wait until 8 bits were received
if last_re='1' then
remain <= remain - 1;
if remain=0 then
--> got 8 bits, decode address & direction
addr <= unsigned(sireg(6 downto 0));
remain <= to_unsigned(31,6);
if sireg(7)='1' then
state <= S_READ2;
bus_rena <= '1';
bus_addr <= unsigned(sireg(6 downto 0));
else
state <= S_WRITE;
end if;
end if;
end if;
when S_WRITE =>
-- wait until 32 bits were received
if last_re='1' then
remain <= remain - 1;
if remain=0 then
-- issue write-request
bus_wena <= '1';
bus_addr <= addr;
bus_wdata <= sireg;
-- continue with next word
addr <= addr + 1;
remain <= to_unsigned(31,6);
end if;
end if;
when S_READ2 =>
-- wait-state
state <= S_READ3;
when S_READ3 =>
-- load shift-register
soreg <= soreg(32) & bus_rdata;
state <= S_READ4;
remain <= to_unsigned(31,6);
when S_READ4 =>
-- wait until 32 bits were transmitted
if fe='1' then
remain <= remain - 1;
if remain=0 then
-- continue with next word
bus_rena <= '1';
bus_addr <= addr + 1;
addr <= addr + 1;
state <= S_READ2;
end if;
end if;
end case;
end if;
end if;
end process;
end rtl;

View File

@ -0,0 +1,331 @@
---------------------------------------------------------------------------------------------------
-- Filename : usbrx_toplevel.vhd
-- Project : OsmoSDR FPGA Firmware
-- Purpose : Toplevel component
---------------------------------------------------------------------------------------------------
-----------------------------------------------------------------------------------
-- 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.std_logic_misc.all;
use ieee.numeric_std.all;
library work;
use work.all;
use work.mt_toolbox.all;
use work.usbrx.all;
entity usbrx_toplevel is
port (
-- common
clk_in_pclk : in std_logic;
-- special control
dings : in std_logic;
dingsrst : in std_logic;
-- ADC interface
adc_cs : out std_logic;
adc_sck : out std_logic;
adc_sd1 : in std_logic;
adc_sd2 : in std_logic;
-- control SPI
ctl_int : out std_logic;
ctl_cs : in std_logic;
ctl_sck : in std_logic;
ctl_mosi : in std_logic;
ctl_miso : out std_logic;
-- data SPIs
rx_clk : out std_logic;
rx_syn : out std_logic;
rx_dat : out std_logic;
-- data SPIs
tx_clk : in std_logic;
tx_syn : in std_logic;
tx_dat : in std_logic;
-- gain PWMs
gain0 : out std_logic;
gain1 : out std_logic;
-- GPS
gps_1pps : in std_logic;
gps_10k : in std_logic;
-- gpios
gpio : inout std_logic_vector(9 downto 0);
-- virtual GNDs/VCCs
vgnd : out std_logic_vector(11 downto 0);
vcc33 : inout std_logic_vector(11 downto 0);
vcc12 : inout std_logic_vector(4 downto 0)
);
end usbrx_toplevel;
architecture rtl of usbrx_toplevel is
-- clocks
signal clk_30 : std_logic;
signal clk_80 : std_logic;
signal rst_30 : std_logic;
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;
-- ADC <-> offset
signal adc_off_clk : std_logic;
signal adc_off_i : unsigned(13 downto 0);
signal adc_off_q : unsigned(13 downto 0);
-- offset <-> filter
signal off_fil_clk : std_logic;
signal off_fil_i : signed(15 downto 0);
signal off_fil_q : signed(15 downto 0);
-- filter <-> output
signal fil_out_clk : std_logic;
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
cg: entity usbrx_clkgen
port map (
-- clock input
clk_30_pclk => clk_in_pclk,
ext_rst => dingsrst,
-- system clock
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
);
-- register bank
rb: entity usbrx_regbank
port map (
-- common
clk => clk_80,
reset => rst_80,
-- config
cfg_pwm => cfg_pwm,
cfg_adc => cfg_adc,
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,
-- SPI interface
spi_ncs => ctl_cs,
spi_sclk => ctl_sck,
spi_mosi => ctl_mosi,
spi_miso => ctl_miso
);
-- gain PWMs
pwm: entity usbrx_pwm
port map (
-- common
clk => clk_80,
reset => rst_80,
-- config
config => cfg_pwm,
-- PWM output
pwm0 => gain0,
pwm1 => gain1
);
-- A/D interface
adc: entity usbrx_ad7357
port map (
-- common
clk => clk_80,
reset => rst_80,
-- config
config => cfg_adc,
-- ADC interface
adc_cs => adc_cs,
adc_sck => adc_sck,
adc_sd1 => adc_sd1,
adc_sd2 => adc_sd2,
-- output
out_clk => adc_off_clk,
out_i => adc_off_i,
out_q => adc_off_q
);
-- offset stage
off: entity usbrx_offset
port map (
-- common
clk => clk_80,
reset => rst_80,
-- config
config => cfg_off,
-- input
in_clk => adc_off_clk,
in_i => adc_off_i,
in_q => adc_off_q,
-- output
out_clk => off_fil_clk,
out_i => off_fil_i,
out_q => off_fil_q
);
-- decimation filter
fil: entity usbrx_decimate
port map (
-- common
clk => clk_80,
reset => rst_80,
-- config
config => cfg_fil,
-- input
in_clk => off_fil_clk,
in_i => off_fil_i,
in_q => off_fil_q,
-- output
out_clk => fil_out_clk,
out_i => fil_out_i,
out_q => fil_out_q
);
-- SSC output
ssc: entity usbrx_ssc
port map (
-- common
clk => clk_80,
reset => rst_80,
-- config
config => cfg_ssc,
-- output
in_clk => fil_out_clk,
in_i => fil_out_i,
in_q => fil_out_q,
-- SSC interface
ssc_clk => rx_clk,
ssc_syn => rx_syn,
ssc_dat => rx_dat
);
-- TODO
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');
vcc12 <= (others=>'Z');
vcc33 <= (others=>'1');
end rtl;

View File

@ -0,0 +1,66 @@
---------------------------------------------------------------------------------------------------
-- Filename : usbrx.vhd
-- Project : OsmoSDR FPGA Firmware
-- Purpose : OsmoSDR package
---------------------------------------------------------------------------------------------------
-----------------------------------------------------------------------------------
-- 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;
package usbrx is
-- PWM config
type usbrx_pwm_config_t is record
freq0 : unsigned(15 downto 0);
freq1 : unsigned(15 downto 0);
duty0 : unsigned(15 downto 0);
duty1 : unsigned(15 downto 0);
end record;
-- ADC interface config
type usbrx_adc_config_t is record
clkdiv : unsigned(7 downto 0);
acqlen : unsigned(7 downto 0);
end record;
-- SSC interface config
type usbrx_ssc_config_t is record
clkdiv : unsigned(7 downto 0);
tmode : std_logic;
end record;
-- offset stage
type usbrx_off_config_t is record
ioff : signed(15 downto 0);
qoff : signed(15 downto 0);
end record;
-- decimation filter config
type usbrx_fil_config_t is record
decim : unsigned(2 downto 0);
end record;
end usbrx;
package body usbrx is
-- nothing so far
end usbrx;

View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<XML>
<document type="stimulators" version="1">
<set name="ASDB Stimulators" active="1"/>
</document>
</XML>

View File

@ -0,0 +1 @@
i<>.\src\usbrx\toplevel\usbrx_toplevel.vhd

149
fpga/hw-v2/usbrx_vhdl.adf Normal file
View File

@ -0,0 +1,149 @@
[Project]
Current Flow=Generic
VCS=0
version=3
Current Config=compile
[Configurations]
compile=usbrx_vhdl
[Library]
usbrx_vhdl=.\usbrx_vhdl.LIB
[Settings]
AccessRead=0
AccessReadWrite=0
AccessACCB=0
AccessACCR=0
AccessReadWriteSLP=0
AccessReadTopLevel=1
DisableC=1
ENABLE_ADV_DATAFLOW=0
FLOW_TYPE=HDL
LANGUAGE=VHDL
REFRESH_FLOW=1
FAMILY=Lattice XP2
fileopeninsrc=1
fileopenfolder=C:\
IMPL_TOOL=
SYNTH_TOOL=
NoWarningsSDF=0
SDFErrorLimit=0
EnableSDFErrorLimit=0
ChangeSDFErrorToWarning=0
NoTchkMsg=0
NoTimingChecks=0
HESPrepare=0
EnableXtrace=0
SplitNetVectors=0
StackMemorySize=32
RetvalMemorySize=32
VsimAdditionalOptions=
DisableVitalMsg=0
VitalAccel=1
VitalGlitches=0
DisableIEEEWarnings=0
[LocalVerilogSets]
EnableSLP=1
EnableDebug=0
[LocalVhdlSets]
CompileWithDebug=1
DisableVHDL87Key=0
EnableVHDL93Key=0
EnableVHDL2002Key=1
EnableVHDL2006Key=0
EnableVHDL2008Key=0
NetlistCompilation=1
Syntax RelaxLRM=0
MaxErrorsKey=100
OptimizationLevel=3
DisableRangeChecks=0
ProtectLevel=0
AdditionalOptions=
IncrementalCompilation=0
[$LibMap$]
usbrx_vhdl=.
Active_lib=
[HierarchyViewer]
SortInfo=u
HierarchyInformation=
ShowHide=ShowTopLevel
Selected=
[Folders]
Name3=Makefiles
Directory3=C:\
Extension3=mak
Name4=Memory
Directory4=C:\
Extension4=mem;mif;hex
Name5=Dll Libraries
Directory5=C:\
Extension5=dll
Name6=PDF
Directory6=C:\
Extension6=pdf
Name7=HTML
Directory7=C:\
Extension7=
[sdf.c.structure_con]
[sdf.ea.tb_usbrx-rtl]
0=src\testbench\usbrx_vhdl_usbrx_vhdl_vho.sdf| /tb_usbrx/uut, Average, No
[Groups]
mt_toolbox=1
mt_filter=1
usbrx=1
usbrx\filter=1
usbrx\datapath=1
usbrx\toplevel=1
testbench=1
[Files]
mt_toolbox/mt_toolbox.vhd=-1
mt_toolbox/mt_clktools.vhd=-1
mt_filter/mt_filter.vhd=-1
mt_filter/mt_fil_storage_slow.vhd=-1
mt_filter/mt_fil_mac_slow.vhd=-1
mt_filter/mt_fir_symmetric_slow.vhd=-1
usbrx/usbrx.vhd=-1
usbrx\filter/usbrx_halfband.vhd=-1
usbrx\datapath/usbrx_ad7357.vhd=-1
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_spi.vhd=-1
usbrx\toplevel/usbrx_regbank.vhd=-1
usbrx\toplevel/usbrx_pwm.vhd=-1
usbrx\toplevel/usbrx_toplevel.vhd=-1
testbench/tb_filter.vhd=-1
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_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
.\src\mt_filter\mt_fir_symmetric_slow.vhd=VHDL Source Code
.\src\usbrx\usbrx.vhd=VHDL Source Code
.\src\usbrx\filter\usbrx_halfband.vhd=VHDL Source Code
.\src\usbrx\datapath\usbrx_ad7357.vhd=VHDL Source Code
.\src\usbrx\datapath\usbrx_offset.vhd=VHDL Source Code
.\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_spi.vhd=VHDL Source Code
.\src\usbrx\toplevel\usbrx_regbank.vhd=VHDL Source Code
.\src\usbrx\toplevel\usbrx_pwm.vhd=VHDL Source Code
.\src\usbrx\toplevel\usbrx_toplevel.vhd=VHDL Source Code
.\src\testbench\tb_filter.vhd=VHDL Source Code
.\src\testbench\tb_usbrx.vhd=VHDL Test Bench

15
fpga/hw-v2/usbrx_vhdl.aws Normal file
View File

@ -0,0 +1,15 @@
[Version]
Version=8.3
[Designs]
usbrx_vhdl=.\usbrx_vhdl.adf
[Settings]
Active=usbrx_vhdl
[Browser]
sort=type
mode=none
[Order]
order=1
macro=
[Expand]
usbrx_vhdl=1
timingsim=0

63
fpga/hw-v2/usbrx_vhdl.wsp Normal file
View File

@ -0,0 +1,63 @@
[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