summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHoernchen <la@tfc-server.de>2013-01-22 18:18:52 +0100
committerHoernchen <la@tfc-server.de>2013-01-22 18:21:31 +0100
commit4349afe1f6f4cb4941bf8ba58d72dd8fb45a2745 (patch)
tree7a76050c254d5c6017b1e5fadba340c6d527cd1d
parenta5a3280178cd01a9e6d709a7ea43ccc788442657 (diff)
add current VHDL source
-rw-r--r--fpga/hw-v2-mci/Edfmap.ini1340
-rw-r--r--fpga/hw-v2-mci/bde.set125
-rw-r--r--fpga/hw-v2-mci/compilation.order30
-rw-r--r--fpga/hw-v2-mci/compile.cfg68
-rw-r--r--fpga/hw-v2-mci/deploy/.gitattributes2
-rw-r--r--fpga/hw-v2-mci/deploy/usbrx.xcf49
-rw-r--r--fpga/hw-v2-mci/deploy/usbrx_data.vmebin133669 -> 133826 bytes
-rw-r--r--fpga/hw-v2-mci/diamond/.run_manager.ini9
-rw-r--r--fpga/hw-v2-mci/diamond/.setting.ini4
-rw-r--r--fpga/hw-v2-mci/diamond/Strategy1.sty7
-rw-r--r--fpga/hw-v2-mci/diamond/reportview.xml10
-rw-r--r--fpga/hw-v2-mci/diamond/usbrx_vhdl.ldf95
-rw-r--r--fpga/hw-v2-mci/diamond/usbrx_vhdl.lpf133
-rw-r--r--fpga/hw-v2-mci/diamond/usbrx_vhdl.pty3
-rw-r--r--fpga/hw-v2-mci/library.cfg2
-rw-r--r--fpga/hw-v2-mci/projlib.cfg1
-rw-r--r--fpga/hw-v2-mci/src/mt_filter/mt_fil_mac_slow.vhd146
-rw-r--r--fpga/hw-v2-mci/src/mt_filter/mt_fil_storage_slow.vhd403
-rw-r--r--fpga/hw-v2-mci/src/mt_filter/mt_filter.vhd46
-rw-r--r--fpga/hw-v2-mci/src/mt_filter/mt_fir_symmetric_slow.vhd219
-rw-r--r--fpga/hw-v2-mci/src/mt_toolbox/mt_clktools.vhd141
-rw-r--r--fpga/hw-v2-mci/src/mt_toolbox/mt_synctools.vhd135
-rw-r--r--fpga/hw-v2-mci/src/mt_toolbox/mt_toolbox.vhd202
-rw-r--r--fpga/hw-v2-mci/src/sdio/sdio_cmd.vhd589
-rw-r--r--fpga/hw-v2-mci/src/sdio/sdio_dat.vhd247
-rw-r--r--fpga/hw-v2-mci/src/sdio/sdio_top.vhd286
-rw-r--r--fpga/hw-v2-mci/src/sdio/sdio_txctrl.vhd119
-rw-r--r--fpga/hw-v2-mci/src/sdio/sdio_txfifo.vhd135
-rw-r--r--fpga/hw-v2-mci/src/testbench/tb_filter.vhd131
-rw-r--r--fpga/hw-v2-mci/src/testbench/tb_sdio.vhd409
-rw-r--r--fpga/hw-v2-mci/src/testbench/tb_sdio_stim.vhd362
-rw-r--r--fpga/hw-v2-mci/src/testbench/tb_usbrx.vhd399
-rw-r--r--fpga/hw-v2-mci/src/usbrx/datapath/usbrx_ad7357.vhd312
-rw-r--r--fpga/hw-v2-mci/src/usbrx/datapath/usbrx_decimate.vhd213
-rw-r--r--fpga/hw-v2-mci/src/usbrx/datapath/usbrx_offset.vhd126
-rw-r--r--fpga/hw-v2-mci/src/usbrx/datapath/usbrx_sdio.vhd133
-rw-r--r--fpga/hw-v2-mci/src/usbrx/datapath/usbrx_ssc.vhd191
-rw-r--r--fpga/hw-v2-mci/src/usbrx/filter/usbrx_halfband.vhd505
-rw-r--r--fpga/hw-v2-mci/src/usbrx/toplevel/usbrx_clkgen.vhd154
-rw-r--r--fpga/hw-v2-mci/src/usbrx/toplevel/usbrx_clkref.vhd158
-rw-r--r--fpga/hw-v2-mci/src/usbrx/toplevel/usbrx_gpio.vhd72
-rw-r--r--fpga/hw-v2-mci/src/usbrx/toplevel/usbrx_pwm.vhd100
-rw-r--r--fpga/hw-v2-mci/src/usbrx/toplevel/usbrx_regbank.vhd240
-rw-r--r--fpga/hw-v2-mci/src/usbrx/toplevel/usbrx_spi.vhd215
-rw-r--r--fpga/hw-v2-mci/src/usbrx/toplevel/usbrx_toplevel.vhd323
-rw-r--r--fpga/hw-v2-mci/src/usbrx/usbrx.vhd86
-rw-r--r--fpga/hw-v2-mci/stimulators.set6
-rw-r--r--fpga/hw-v2-mci/synthesis.order5
-rw-r--r--fpga/hw-v2-mci/usbrx_vhdl.adf172
-rw-r--r--fpga/hw-v2-mci/usbrx_vhdl.aws15
50 files changed, 8873 insertions, 0 deletions
diff --git a/fpga/hw-v2-mci/Edfmap.ini b/fpga/hw-v2-mci/Edfmap.ini
new file mode 100644
index 0000000..527585e
--- /dev/null
+++ b/fpga/hw-v2-mci/Edfmap.ini
@@ -0,0 +1,1340 @@
+
+[$GENERAL$]
+INIT=Z
+prefix=EDF_
+user_names=no
+edif2sdf_mapfile=
+logfile=efd2vhd.log
+
+[$EXPORT$]
+FMAP=NO
+HMAP=NO
+
+[$properties$]
+CYMODE=
+INIT=
+FD INIT=integer
+FDC INIT=integer
+FDCE INIT=integer
+FDCE_1 INIT=integer
+FDCP INIT=integer
+FDCPE INIT=integer
+FDCPE_1 INIT=integer
+FDCP_1 INIT=integer
+FDC_1 INIT=integer
+FDD INIT=integer
+FDDC INIT=integer
+FDDCE INIT=integer
+FDDCP INIT=integer
+FDDCPE INIT=integer
+FDDP INIT=integer
+FDDPE INIT=integer
+FDDRCPE INIT=integer
+FDDRRSE INIT=integer
+FDE INIT=integer
+FDE_1 INIT=integer
+FDP INIT=integer
+FDPE INIT=integer
+FDPE_1 INIT=integer
+FDP_1 INIT=integer
+FDR INIT=integer
+FDRE INIT=integer
+FDRE_1 INIT=integer
+FDRS INIT=integer
+FDRSE INIT=integer
+FDRSE_1 INIT=integer
+FDRS_1 INIT=integer
+FDR_1 INIT=integer
+FDS INIT=integer
+FDSE INIT=integer
+FDSE_1 INIT=integer
+FDS_1 INIT=integer
+FD_1 INIT=integer
+FJKC INIT=integer
+FJKCE INIT=integer
+FJKP INIT=integer
+FJKPE INIT=integer
+FJKRSE INIT=integer
+FJKSRE INIT=integer
+FTC INIT=integer
+FTCE INIT=integer
+FTCLE INIT=integer
+FTCLEX INIT=integer
+FTP INIT=integer
+FTPE INIT=integer
+FTPLE INIT=integer
+FTRSE INIT=integer
+FTRSLE INIT=integer
+FTSRE INIT=integer
+FTSRLE INIT=integer
+FTCP INIT=integer
+GTPA1_DUAL RXPRBSERR_LOOPBACK_0=integer
+GTPA1_DUAL RXPRBSERR_LOOPBACK_1=integer
+GTXE1 RXPRBSERR_LOOPBACK=integer
+IDDR INIT_Q1=integer
+IDDR INIT_Q2=integer
+IDDR2 INIT_Q0=integer
+IDDR2 INIT_Q1=integer
+IDDR_2CLK INIT_Q1=integer
+IDDR_2CLK INIT_Q2=integer
+IFD INIT=integer
+IFD_1 INIT=integer
+IFDI INIT=integer
+IFDI_1 INIT=integer
+IFDX INIT=integer
+IFDX_1 INIT=integer
+IFDXI INIT=integer
+IFDXI_1 INIT=integer
+ILD INIT=integer
+ILD_1 INIT=integer
+ILDI INIT=integer
+ILDI_1 INIT=integer
+ILDX INIT=integer
+ILDX_1 INIT=integer
+ILDXI INIT=integer
+ILDXI_1 INIT=integer
+ISERDES INIT_Q1=integer
+ISERDES INIT_Q2=integer
+ISERDES INIT_Q3=integer
+ISERDES INIT_Q4=integer
+ISERDES SRVAL_Q1=integer
+ISERDES SRVAL_Q2=integer
+ISERDES SRVAL_Q3=integer
+ISERDES SRVAL_Q4=integer
+ISERDES_NODELAY INIT_Q1=integer
+ISERDES_NODELAY INIT_Q2=integer
+ISERDES_NODELAY INIT_Q3=integer
+ISERDES_NODELAY INIT_Q4=integer
+ISERDES_NODELAY SRVAL_Q1=integer
+ISERDES_NODELAY SRVAL_Q2=integer
+ISERDES_NODELAY SRVAL_Q3=integer
+ISERDES_NODELAY SRVAL_Q4=integer
+LD INIT=integer
+LDC INIT=integer
+LDCE INIT=integer
+LDCE_1 INIT=integer
+LDCP INIT=integer
+LDCPE INIT=integer
+LDCPE_1 INIT=integer
+LDCP_1 INIT=integer
+LDC_1 INIT=integer
+LDE INIT=integer
+LDE_1 INIT=integer
+LDG INIT=integer
+LDP INIT=integer
+LDPE INIT=integer
+LDPE_1 INIT=integer
+LDP_1 INIT=integer
+LD_1 INIT=integer
+ODDR INIT=integer
+ODDR2 INIT=integer
+OFD INIT=integer
+OFD_1 INIT=integer
+OFDE INIT=integer
+OFDE_1 INIT=integer
+OFDI INIT=integer
+OFDI_1 INIT=integer
+OFDT INIT=integer
+OFDT_1 INIT=integer
+OFDX INIT=integer
+OFDX_1 INIT=integer
+OFDXI INIT=integer
+OFDXI_1 INIT=integer
+OSERDES INIT_OQ=integer
+OSERDES SRVAL_OQ=integer
+OSERDES INIT_TQ=integer
+OSERDES SRVAL_TQ=integer
+OSERDES INIT_OQ=integer
+OSERDES INIT_TQ=integer
+OSERDES SRVAL_OQ=integer
+OSERDES SRVAL_TQ=integer
+lut_function=
+eqn=
+INIT_00=
+INIT_01=
+INIT_02=
+INIT_03=
+INIT_04=
+INIT_05=
+INIT_06=
+INIT_07=
+INIT_08=
+INIT_09=
+INIT_0A=
+INIT_0B=
+INIT_0C=
+INIT_0D=
+INIT_0E=
+INIT_0F=
+
+INIT_10=
+INIT_11=
+INIT_12=
+INIT_13=
+INIT_14=
+INIT_15=
+INIT_16=
+INIT_17=
+INIT_18=
+INIT_19=
+INIT_1A=
+INIT_1B=
+INIT_1C=
+INIT_1D=
+INIT_1E=
+INIT_1F=
+
+INIT_20=
+INIT_21=
+INIT_22=
+INIT_23=
+INIT_24=
+INIT_25=
+INIT_26=
+INIT_27=
+INIT_28=
+INIT_29=
+INIT_2A=
+INIT_2B=
+INIT_2C=
+INIT_2D=
+INIT_2E=
+INIT_2F=
+
+INIT_30=
+INIT_31=
+INIT_32=
+INIT_33=
+INIT_34=
+INIT_35=
+INIT_36=
+INIT_37=
+INIT_38=
+INIT_39=
+INIT_3A=
+INIT_3B=
+INIT_3C=
+INIT_3D=
+INIT_3E=
+INIT_3F=
+
+INIT_40=
+INIT_41=
+INIT_42=
+INIT_43=
+INIT_44=
+INIT_45=
+INIT_46=
+INIT_47=
+INIT_48=
+INIT_49=
+INIT_4A=
+INIT_4B=
+INIT_4C=
+INIT_4D=
+INIT_4E=
+INIT_4F=
+
+INIT_50=
+INIT_51=
+INIT_52=
+INIT_53=
+INIT_54=
+INIT_55=
+INIT_56=
+INIT_57=
+INIT_58=
+INIT_59=
+INIT_5A=
+INIT_5B=
+INIT_5C=
+INIT_5D=
+INIT_5E=
+INIT_5F=
+
+INIT_60=
+INIT_61=
+INIT_62=
+INIT_63=
+INIT_64=
+INIT_65=
+INIT_66=
+INIT_67=
+INIT_68=
+INIT_69=
+INIT_6A=
+INIT_6B=
+INIT_6C=
+INIT_6D=
+INIT_6E=
+INIT_6F=
+
+INITP_00=
+INITP_01=
+INITP_02=
+INITP_03=
+INITP_04=
+INITP_05=
+INITP_06=
+INITP_07=
+
+LPM_TYPE=
+LPM_WIDTH=integer
+LPM_DIRECTION=
+P_WIDTH=
+P_OFFSET=
+CLKDV_DIVIDE=real
+DUTY_CYCLE_CORRECTION=bool
+WIDTH=integer
+DIVIDE1_BY=integer
+DIVIDE2_BY=integer
+TimingChecksOn=bool
+Xon=bool
+MsgOn=bool
+SEL_F500K=bool
+SEL_F16K=bool
+SEL_F490=bool
+SEL_F15=bool
+
+;added for virtex4 library
+CLKFX_DIVIDE=integer
+CLKFX_MULTIPLY=integer
+CLKIN_DIVIDE_BY_2=bool
+CLKIN_PERIOD=real
+CLKOUT_PHASE_SHIFT=
+CLK_FEEDBACK=
+DCM_PERFORMANCE_MODE=
+DESKEW_ADJUST=
+DFS_FREQUENCY_MODE=
+DLL_FREQUENCY_MODE=
+FACTORY_JF=
+STARTUP_WAIT=bool
+PHASE_SHIFT=integer
+MONITOR_MODE=
+SIM_MONITOR_FILE=
+JTAG_CHAIN=integer
+INIT_OUT=integer
+PRESELECT_I0=bool
+PRESELECT_I1=bool
+BUFR_DIVIDE=
+DSS_MODE=
+AREG=integer
+B_INPUT=
+BREG=integer
+CARRYINREG=integer
+CARRYINSELREG=integer
+CREG=integer
+LEGACY_MODE=
+MREG=integer
+OPMODEREG=integer
+PREG=integer
+SUBTRACTREG=integer
+ALMOST_FULL_OFFSET=
+ALMOST_EMPTY_OFFSET=
+DATA_WIDTH=integer
+FIRST_WORD_FALL_THROUGH=bool
+REFCLKSEL=
+SYNCLK1OUTEN=
+SYNCLK2OUTEN=
+CAPACITANCE=
+IOSTANDARD=
+DIFF_TERM=bool
+ICAP_WIDTH=
+DDR_CLK_EDGE=
+INIT_Q1=
+INIT_Q2=
+INIT_Q3=
+INIT_Q4=
+SRTYPE=
+IOBDELAY=
+IOBDELAY_TYPE=
+IOBDELAY_VALUE=integer
+DRIVE=integer
+SLEW=
+INIT_BITSLIPCNT=
+;INIT_CE= ;2 elems bit_vector
+;INIT_RANK1_PARTIAL= ;5 elems bit_vector
+;INIT_RANK2= ;6 elems bit_vector
+;INIT_RANK3= ;6 elems bit_vector
+BITSLIP_ENABLE=bool
+DATA_RATE=
+INTERFACE_TYPE=
+NUM_CE=integer
+SERDES_MODE=
+SRVAL_Q1=
+SRVAL_Q2=
+SRVAL_Q3=
+SRVAL_Q4=
+INIT_LOADCNT=
+SERDES_MODE=
+DATA_RATE_OQ=
+INIT_OQ=
+;INIT_ORANK1= ;6 elems bit_vector
+INIT_ORANK2_PARTIAL=
+DATA_RATE_TQ=
+TRISTATE_WIDTH=integer
+INIT_TQ=
+INIT_TRANK1=
+SRVAL_OQ=
+SRVAL_TQ=
+EN_REL=bool
+RST_DEASSERT_CLK=
+DOA_REG=integer
+DOB_REG=integer
+INIT_A=
+INIT_B=
+INVERT_CLK_DOA_REG=bool
+INVERT_CLK_DOB_REG=bool
+RAM_EXTENSION_A=
+RAM_EXTENSION_B=
+READ_WIDTH_A=integer
+READ_WIDTH_B=integer
+SIM_COLLISION_CHECK=
+SRVAL_A=
+SRVAL_B=
+WRITE_MODE_A=
+WRITE_MODE_B=
+WRITE_WIDTH_A=integer
+WRITE_WIDTH_B=integer
+SRVAL=
+WRITE_MODE=
+DISABLE_COLLISION_CHECK=bool
+ALIGN_COMMA_WORD=integer
+BANDGAPSEL=bool
+CCCB_ARBITRATOR_DISABLE=bool
+CHAN_BOND_LIMIT=integer
+CHAN_BOND_MODE=
+CHAN_BOND_ONE_SHOT=bool
+;CHAN_BOND_SEQ_1_1= ;11 elems bit_vector
+;CHAN_BOND_SEQ_1_2= ;11 elems bit_vector
+;CHAN_BOND_SEQ_1_3= ;11 elems bit_vector
+;CHAN_BOND_SEQ_1_4= ;11 elems bit_vector
+CHAN_BOND_SEQ_1_MASK=
+;CHAN_BOND_SEQ_2_1= ;11 elems bit_vector
+;CHAN_BOND_SEQ_2_2= ;11 elems bit_vector
+;CHAN_BOND_SEQ_2_3= ;11 elems bit_vector
+;CHAN_BOND_SEQ_2_4= ;11 elems bit_vector
+CHAN_BOND_SEQ_2_MASK=
+CHAN_BOND_SEQ_2_USE=bool
+CHAN_BOND_SEQ_LEN=integer
+CLK_CORRECT_USE=bool
+CLK_COR_8B10B_DE=bool
+CLK_COR_MAX_LAT=integer
+CLK_COR_MIN_LAT=integer
+;CLK_COR_SEQ_1_2= ;11 elems bit_vector
+;CLK_COR_SEQ_1_3= ;11 elems bit_vector
+;CLK_COR_SEQ_1_4= ;11 elems bit_vector
+CLK_COR_SEQ_1_MASK=
+;CLK_COR_SEQ_2_1= ;11 elems bit_vector
+;CLK_COR_SEQ_2_2= ;11 elems bit_vector
+;CLK_COR_SEQ_2_3= ;11 elems bit_vector
+;CLK_COR_SEQ_2_4= ;11 elems bit_vector
+CLK_COR_SEQ_2_MASK=
+CLK_COR_SEQ_2_USE=bool
+CLK_COR_SEQ_DROP=bool
+CLK_COR_SEQ_LEN=integer
+COMMA32=bool
+;COMMA_10B_MASK= ;10 elems bit_vector
+;CYCLE_LIMIT_SEL= ;2 elems bit_vector
+;DCDR_FILTER= ;3 elems bit_vector
+DEC_MCOMMA_DETECT=bool
+DEC_PCOMMA_DETECT=bool
+DEC_VALID_COMMA_ONLY=bool
+;DIGRX_FWDCLK= ;2 elems bit_vector
+DIGRX_SYNC_MODE=bool
+ENABLE_DCDR=bool
+;FDET_HYS_CAL= ;3 elems bit_vector
+;FDET_HYS_SEL= ;3 elems bit_vector
+;FDET_LCK_CAL= ;3 elems bit_vector
+;FDET_LCK_SEL= ;3 elems bit_vector
+;LOOPCAL_WAIT= ;2 elems bit_vector
+MCOMMA_32B_VALUE=
+MCOMMA_DETECT=bool
+OPPOSITE_SELECT=bool
+PCOMMA_32B_VALUE=
+PCOMMA_DETECT=bool
+PCS_BIT_SLIP=bool
+PMACLKENABLE=bool
+PMACOREPWRENABLE=bool
+PMA_BIT_SLIP=bool
+POWER_ENABLE=bool
+REPEATER=bool
+;RXAFEEQ= ;9 elems bit_vector
+;RXASYNCDIVIDE= ;2 elems bit_vector
+RXBY_32=bool
+;RXCDRLOS= ;6 elems bit_vector
+RXCLK0_FORCE_PMACLK=bool
+;RXCLKMODE= ;6 elems bit_vector
+RXCPSEL=bool
+RXCRCCLOCKDOUBLE=bool
+RXCRCENABLE=bool
+RXCRCINITVAL=
+RXCRCINVERTGEN=bool
+RXCRCSAMECLOCK=bool
+;RXCYCLE_LIMIT_SEL= ;2 elems bit_vector
+;RXDATA_SEL= ;2 elems bit_vector
+RXDCCOUPLE=bool
+RXDIGRESET=bool
+RXDIGRX=bool
+RXENABLE=bool
+RXEQ=
+RXFDCAL_CLOCK_DIVIDE=
+;RXFDET_HYS_CAL= ;3 elems bit_vector
+;RXFDET_HYS_SEL= ;3 elems bit_vector
+;RXFDET_LCK_CAL= ;3 elems bit_vector
+;RXFDET_LCK_SEL= ;3 elems bit_vector
+RXLB=bool
+;RXLKADJ= ;5 elems bit_vector
+;RXLOOPCAL_WAIT= ;2 elems bit_vector
+RXLOOPFILT=
+RXOUTDIV2SEL_A=
+RXOUTDIV2SEL_B=
+RXPD=bool
+RXPLLNDIVSEL=
+RXPMACLKSEL=
+;RXRCPADJ= ;3 elems bit_vector
+RXRECCLK1_USE_SYNC=bool
+;RXSLOWDOWN_CAL= ;2 elems bit_vector
+RXTADJ=bool
+RXUSRDIVISOR=integer
+;RXVCODAC_INIT= ;10 elems bit_vector
+RXVCO_CTRL_ENABLE=bool
+RX_BUFFER_USE=bool
+;RX_CLOCK_DIVIDER= ;2 elems bit_vector
+RX_LOS_INVALID_INCR=integer
+RX_LOS_THRESHOLD=integer
+SAMPLE_8X=bool
+SH_CNT_MAX=integer
+SH_INVALID_CNT_MAX=integer
+;SLOWDOWN_CAL= ;2 elems bit_vector
+TXABPMACLKSEL=
+;TXASYNCDIVIDE= ;2 elems bit_vector
+TXCLK0_FORCE_PMACLK=bool
+TXCLKMODE=
+TXCPSEL=bool
+TXCRCCLOCKDOUBLE=bool
+TXCRCENABLE=bool
+TXCRCINITVAL=
+TXCRCINVERTGEN=bool
+TXCRCSAMECLOCK=bool
+;TXDATA_SEL= ;2 elems bit_vector
+;TXDAT_PRDRV_DAC= ;3 elems bit_vector
+;TXDAT_TAP_DAC= ;5 elems bit_vector
+TXENABLE=bool
+TXFDCAL_CLOCK_DIVIDE=
+TXHIGHSIGNALEN=bool
+TXLOOPFILT=
+TXOUTCLK1_USE_SYNC=bool
+TXOUTDIV2SEL=
+TXPD=bool
+TXPHASESEL=bool
+TXPLLNDIVSEL=
+;TXPOST_PRDRV_DAC= ;3 elems bit_vector
+;TXPOST_TAP_DAC= ;5 elems bit_vector
+TXPOST_TAP_PD=bool
+;TXPRE_PRDRV_DAC= ;3 elems bit_vector
+;TXPRE_TAP_DAC= ;5 elems bit_vector
+TXPRE_TAP_PD=bool
+TXSLEWRATE=bool
+TXTERMTRIM=
+TX_BUFFER_USE=bool
+;TX_CLOCK_DIVIDER= ;2 elems bit_vector
+;VCODAC_INIT= ;10 elems bit_vector
+VCO_CTRL_ENABLE=bool
+
+
+;added for virtex5 library
+A_INPUT=
+ACASCREG=integer
+ALUMODEREG=integer
+AUTORESET_PATTERN_DETEC=boolean
+AUTORESET_PATTERN_DETECT_OPTINV=
+BANDWIDTH=
+BCASCREG=integer
+CLKFBOUT_MULT=integer
+CLKFBOUT_PHASE=real
+CLKIN1_PERIOD=real
+CLKIN2_PERIOD=real
+CLKOUT0_DIVIDE=integer
+CLKOUT0_DUTY_CYCLE=real
+CLKOUT0_PHASE=real
+CLKOUT1_DIVIDE=integer
+CLKOUT1_DUTY_CYCLE=real
+CLKOUT1_PHASE=real
+CLKOUT2_DIVIDE=integer
+CLKOUT2_DUTY_CYCLE=real
+CLKOUT2_PHASE=real
+CLKOUT3_DIVIDE=integer
+CLKOUT3_DUTY_CYCLE=real
+CLKOUT3_PHASE=real
+CLKOUT4_DIVIDE=integer
+CLKOUT4_DUTY_CYCLE=real
+CLKOUT4_PHASE=real
+CLKOUT5_DIVIDE=integer
+CLKOUT5_DUTY_CYCLE=real
+CLKOUT5_PHASE=real
+COMPENSATION=
+CRC_INIT=
+DELAY_SRC=
+DIVCLK_DIVIDE=integer
+DO_REG=integer
+EN_ECC_READ=boolean
+EN_ECC_SCRUB=boolean
+EN_ECC_WRITE=boolean
+EN_SYN=boolean
+IDELAY_TYPE=
+IDELAY_VALUE=integer
+INIT_70=
+INIT_71=
+INIT_72=
+INIT_73=
+INIT_74=
+INIT_75=
+INIT_76=
+INIT_77=
+INIT_78=
+INIT_79=
+INIT_7A=
+INIT_7B=
+INIT_7C=
+INIT_7D=
+INIT_7E=
+INIT_7F=
+INIT_C=
+INIT_D=
+INITP_08=
+INITP_09=
+INITP_0A=
+INITP_0B=
+INITP_0C=
+INITP_0D=
+INITP_0E=
+INITP_0F=
+MASK=
+MULTCARRYINREG=integer
+ODELAY_VALUE=integer
+PATTERN=
+PLL_PMCD_MODE=boolean
+POLYNOMIAL=
+REF_JITTER=real
+RESET_ON_LOSS_OF_LOCK=boolean
+SEL_MASK=
+SEL_PATTERN=
+SEL_ROUNDING_MASK=
+USE_MULT=
+USE_PATTERN_DETECT=
+USE_SIMD=
+;end of virtex5
+
+;added for virtex5 (ise9.1i sp2)
+CLKFBOUT_DESKEW_ADJUST=
+CLKOUT0_DESKEW_ADJUST=
+CLKOUT1_DESKEW_ADJUST=
+CLKOUT2_DESKEW_ADJUST=
+CLKOUT3_DESKEW_ADJUST=
+CLKOUT4_DESKEW_ADJUST=
+CLKOUT5_DESKEW_ADJUST=
+;end of virtex5 (ise9.1i sp2)
+
+;added for virtex5 (ise9.2i sp1)
+PCS_COM_CFG=
+SIGNAL_PATTERN=
+INIT_FILE=
+;end of virtex5 (ise9.2i sp1)
+
+;added for virtex5 (ise 10.1i)
+SIM_MODE=
+;end
+
+;added for spartan6, virtex6 (ise 11.2)
+A0REG=integer
+A1REG=integer
+AC_CAP_DIS_0=boolean
+AC_CAP_DIS_1=boolean
+ADREG=integer
+AUTORESET_PATDET=
+B0REG=integer
+B1REG=integer
+BUFFER_TYPE=
+BYPASS_GCLK_FF=boolean
+CARRYINSEL=
+CARRYOUTREG=integer
+CHAN_BOND_2_MAX_SKEW_0=integer
+CINVCTRL_SEL=boolean
+CLK_SEL_TYPE=
+CLKCM_CFG=boolean
+CLKFBOUT_MULT_F=real
+CLKFXDV_DIVIDE=integer
+CLKFX_MD_MAX=real
+CLKFBOUT_USE_FINE_PS=boolean
+CLKOUT0_DIVIDE_F=real
+CLKOUT0_USE_FINE_PS=boolean
+CLKOUT1_USE_FINE_PS=boolean
+CLKOUT2_USE_FINE_PS=boolean
+CLKOUT3_USE_FINE_PS=boolean
+CLKOUT4_CASCADE=boolean
+CLKOUT4_USE_FINE_PS=boolean
+CLKOUT5_USE_FINE_PS=boolean
+CLKOUT6_DIVIDE=integer
+CLKOUT6_DUTY_CYCLE=real
+CLKOUT6_PHASE=real
+CLKOUT6_USE_FINE_PS=boolean
+CLKRCV_TRST=boolean
+CLOCK_HOLD=boolean
+COUNTER_WRAPAROUND=
+DATA_RATE_OT=
+DDR3_DATA=integer
+DISABLE_JTAG=boolean
+DIVIDE_BYPASS=boolean
+DIVIDE=integer
+DFS_BANDWIDTH=
+DQSMASK_ENABLE=boolean
+DYN_CLK_INV_EN=boolean
+DYN_CLKDIV_INV_EN=boolean
+EN_RSTRAM_A=boolean
+EN_RSTRAM_B=boolean
+FARSRC=
+HIGH_PERFORMANCE_MODE=boolean
+I_INVERT=boolean
+IBUF_DELAY_VALUE=
+IBUF_LOW_PWR=boolean
+IDELAY2_VALUE=integer
+IDELAY_MODE=
+IFD_DELAY_VALUE=
+ISERDESE1 INIT_Q1=integer
+ISERDESE1 INIT_Q2=integer
+ISERDESE1 INIT_Q3=integer
+ISERDESE1 INIT_Q4=integer
+OSERDESE1 INIT_OQ=integer
+OSERDESE1 INIT_TQ=integer
+INMODEREG=integer
+InstancePath=
+ODELAY_TYPE=
+OFB_USED=boolean
+ONESHOT=boolean
+OUTPUT_MODE=
+PROG_MD_BANDWIDTH=
+PROG_USR=boolean
+RAM_MODE=
+REF_JITTER1=real
+REF_JITTER2=real
+REFCLK_FREQUENCY=real
+;REFCLKOUT_DLY= ;10 elems bit_vector
+RST_PRIORITY_A=
+RST_PRIORITY_B=
+RSTREG_PRIORITY_A=
+RSTREG_PRIORITY_B=
+RSTTYPE=
+SETUP_ALL=
+SIM_DEVICE=
+SIM_EFUSE_VALUE=
+SIM_TAPDELAY_VALUE=integer
+SPREAD_SPECTRUM=
+ISERDESE1 SRVAL_Q1=integer
+ISERDESE1 SRVAL_Q2=integer
+ISERDESE1 SRVAL_Q3=integer
+ISERDESE1 SRVAL_Q4=integer
+OSERDESE1 SRVAL_OQ=integer
+OSERDESE1 SRVAL_TQ=integer
+TRAIN_PATTERN=integer
+USE_DOUBLER=boolean
+USE_DPORT=boolean
+;end of spartan6, virtex6 (ise 11.2)
+
+; added for virtex6 (ise 11.3)
+TX_PMADATA_OPT=integer
+ENABLE_SYNC=bool
+;end of virtex6 (ise 11.3)
+
+[$LIBMAP$]
+work=.
+xilinx=xabelsim
+xilinxun=
+simprims=simprim
+DESIGNS=
+
+;FPGA Express
+VIRTEXE=VIRTEX
+COOLRUNNER=XC9500
+COOLRUNNER2=COOLRUNNERII
+SPARTAN2E=SPARTAN2E
+SPARTAN3=SPARTAN3
+SPARTAN3A=SPARTAN3A
+SPARTAN3E=SPARTAN3E
+SPARTANXL=SPARTANX
+XC3000A=XC3000
+XC3000L=XC3000
+XC3100A=XC3000
+XC3100L=XC3000
+XC4000EX=XC4000X
+XC4000L=XC4000E
+XC4000XL=XC4000X
+XC4000XLA=XC4000X
+XC4000XV=XC4000X
+XC9500XL=XC9500
+XC9500XV=XC9500
+
+;Synplify
+COOLRUNNERII=COOLRUNNERII
+Unilib=unisim
+XC4000=unisim
+XC5000=unisim
+
+;Exemplar
+xcv=unisim
+xcv2=unisim
+xcv2p=unisim
+xcve=unisim
+xi3=unisim
+xi31=unisim
+xi31a=unisim
+xi3a=unisim
+xi3l=unisim
+xi3t=unisim
+xi4=unisim
+xi4a=unisim
+xi4e=unisim
+xi4et=unisim
+xi4ex=unisim
+xi4h=unisim
+xi4l=unisim
+xi4t=unisim
+xi4xl=unisim
+xi4xla=unisim
+xi4xv=unisim
+xi5=unisim
+xi5t=unisim
+xi72a=unisim
+xi73=unisim
+xi7t=unisim
+xi95=unisim
+xi95xl=unisim
+xi95xv=unisim
+xis=unisim
+xis2=unisim
+xis2e=unisim
+xis3=unisim
+xisxl=unisim
+Active_lib=
+UnlinkedDesignLibrary=
+
+[$GSRGTS$]
+GSR=
+GR=
+GTS=
+PRLD=
+
+[$INCLUDE$]
+line1=library IEEE;
+line2=use IEEE.std_logic_1164.all;
+line3=library UNISIM;
+line4=use UNISIM.vcomponents.all;
+line5=library SIMPRIM;
+line6=use SIMPRIM.vcomponents.all;
+
+[TBUF]
+.=BUFT
+
+[VCC]
+VCC=P
+
+[GND]
+ground=G
+
+[X_FF]
+IN=I
+OUT=O
+
+;[OPAD]
+;OPAD=I
+;PAD=I
+
+;[IPAD]
+;IPAD=I
+;PAD=I
+
+;[IOPAD]
+;IOPAD=I
+;PAD=I
+
+[X_PU]
+OUT=O
+
+[X_LATCH]
+IN=I
+OUT=O
+
+[X_LATCHE]
+IN=I
+OUT=O
+
+[x_tri]
+IN=I
+OUT=O
+
+[x_buf]
+IN=I
+OUT=O
+
+[x_zero]
+OUT=O
+[x_one]
+OUT=O
+
+[x_and2]
+OUT=O
+IN1=I1
+IN0=I0
+
+[x_inv]
+IN=I
+OUT=O
+
+[x_or2]
+IN0=I0
+IN1=I1
+OUT=O
+
+[x_ckbuf]
+IN=I
+OUT=O
+
+[x_and3]
+IN0=I0
+IN1=I1
+IN2=I2
+OUT=O
+
+[x_and4]
+IN0=I0
+IN1=I1
+IN2=I2
+IN3=I3
+OUT=O
+
+[x_and5]
+IN0=I0
+IN1=I1
+IN2=I2
+IN3=I3
+IN4=I4
+OUT=O
+
+[x_and6]
+IN0=I0
+IN1=I1
+IN2=I2
+IN3=I3
+IN4=I4
+IN5=I5
+OUT=O
+
+[x_and7]
+IN0=I0
+IN1=I1
+IN2=I2
+IN3=I3
+IN4=I4
+IN5=I5
+IN6=I6
+OUT=O
+
+[x_and8]
+IN0=I0
+IN1=I1
+IN2=I2
+IN3=I3
+IN4=I4
+IN5=I5
+IN6=I6
+IN7=I7
+OUT=O
+
+[x_and16]
+IN0=I0
+IN1=I1
+IN2=I2
+IN3=I3
+IN4=I4
+IN5=I5
+IN6=I6
+IN7=I7
+IN8=I8
+IN9=I9
+IN10=I10
+IN11=I11
+IN12=I12
+IN13=I13
+IN14=I14
+IN15=I15
+OUT=O
+
+[x_or2]
+IN0=I0
+IN1=I1
+OUT=O
+
+[x_or3]
+IN0=I0
+IN1=I1
+IN2=I2
+OUT=O
+
+[x_or4]
+IN0=I0
+IN1=I1
+IN2=I2
+IN3=I3
+OUT=O
+
+[x_or5]
+IN0=I0
+IN1=I1
+IN2=I2
+IN3=I3
+IN4=I4
+OUT=O
+
+[x_or6]
+IN0=I0
+IN1=I1
+IN2=I2
+IN3=I3
+IN4=I4
+IN5=I5
+OUT=O
+
+[x_or7]
+IN0=I0
+IN1=I1
+IN2=I2
+IN3=I3
+IN4=I4
+IN5=I5
+IN6=I6
+OUT=O
+
+
+[x_or8]
+IN0=I0
+IN1=I1
+IN2=I2
+IN3=I3
+IN4=I4
+IN5=I5
+IN6=I6
+IN7=I7
+OUT=O
+
+[x_or16]
+IN0=I0
+IN1=I1
+IN2=I2
+IN3=I3
+IN4=I4
+IN5=I5
+IN6=I6
+IN7=I7
+IN8=I8
+IN9=I9
+IN10=I10
+IN11=I11
+IN12=I12
+IN13=I13
+IN14=I14
+IN15=I15
+OUT=O
+
+[x_xor2]
+IN0=I0
+IN1=I1
+IN2=I2
+OUT=O
+
+[x_xor3]
+IN0=I0
+IN1=I1
+IN2=I2
+OUT=O
+
+[x_xor4]
+IN0=I0
+IN1=I1
+IN2=I2
+IN3=I3
+OUT=O
+
+[x_xor5]
+IN0=I0
+IN1=I1
+IN2=I2
+IN3=I3
+IN4=I4
+OUT=O
+
+
+[x_lut2]
+OUT=O
+
+[x_lut3]
+OUT=O
+
+[x_lut4]
+OUT=O
+
+[x_RAM16]
+OUT=O
+IN=I
+
+[x_RAM32]
+OUT=O
+IN=I
+
+[x_RAMS16]
+OUT=O
+IN=I
+
+[x_RAMS32]
+OUT=O
+IN=I
+
+[x_RAMD16]
+OUT=O
+IN=I
+
+[x_RAMD32]
+OUT=O
+IN=I
+
+[x_MUX2]
+OUT=O
+INA=IA
+INB=IB
+
+[x_OR32]
+IN0=I0
+IN1=I1
+IN2=I2
+IN3=I3
+IN4=I4
+IN5=I5
+IN6=I6
+IN7=I7
+IN8=I8
+IN9=I9
+IN10=I10
+IN11=I11
+IN12=I12
+IN13=I13
+IN14=I14
+IN15=I15
+IN16=I16
+IN17=I17
+IN18=I18
+IN19=I19
+IN20=I20
+IN21=I21
+IN22=I22
+IN23=I23
+IN24=I24
+IN25=I25
+IN26=I26
+IN27=I27
+IN28=I28
+IN29=I29
+IN30=I30
+IN31=I31
+OUT=O
+
+[x_PD]
+OUT=O
+
+[x_XOR16]
+IN0=I0
+IN1=I1
+IN2=I2
+IN3=I3
+IN4=I4
+IN5=I5
+IN6=I6
+IN7=I7
+IN8=I8
+IN9=I9
+IN10=I10
+IN11=I11
+IN12=I12
+IN13=I13
+IN14=I14
+IN15=I15
+OUT=O
+
+[x_XOR32]
+IN0=I0
+IN1=I1
+IN2=I2
+IN3=I3
+IN4=I4
+IN5=I5
+IN6=I6
+IN7=I7
+IN8=I8
+IN9=I9
+IN10=I10
+IN11=I11
+IN12=I12
+IN13=I13
+IN14=I14
+IN15=I15
+IN16=I16
+IN17=I17
+IN18=I18
+IN19=I19
+IN20=I20
+IN21=I21
+IN22=I22
+IN23=I23
+IN24=I24
+IN25=I25
+IN26=I26
+IN27=I27
+IN28=I28
+IN29=I29
+IN30=I30
+IN31=I31
+OUT=O
+
+[x_AND32]
+IN0=I0
+IN1=I1
+IN2=I2
+IN3=I3
+IN4=I4
+IN5=I5
+IN6=I6
+IN7=I7
+IN8=I8
+IN9=I9
+IN10=I10
+IN11=I11
+IN12=I12
+IN13=I13
+IN14=I14
+IN15=I15
+IN16=I16
+IN17=I17
+IN18=I18
+IN19=I19
+IN20=I20
+IN21=I21
+IN22=I22
+IN23=I23
+IN24=I24
+IN25=I25
+IN26=I26
+IN27=I27
+IN28=I28
+IN29=I29
+IN30=I30
+IN31=I31
+OUT=O
+
+[x_XOR6]
+IN0=I0
+IN1=I1
+IN2=I2
+IN3=I3
+IN4=I4
+IN5=I5
+OUT=O
+
+[x_XOR7]
+IN0=I0
+IN1=I1
+IN2=I2
+IN3=I3
+IN4=I4
+IN5=I5
+IN6=I6
+OUT=O
+
+[x_XOR8]
+IN0=I0
+IN1=I1
+IN2=I2
+IN3=I3
+IN4=I4
+IN5=I5
+IN6=I6
+IN7=I7
+OUT=O
+
+[X_SFF]
+IN=I
+OUT=O
+
+[X_SUH]
+IN=I
+
+[FDCE]
+GSR=$HIDDEN$
+[FDPE]
+GSR=$HIDDEN$
+[IFDX]
+GSR=$HIDDEN$
+[IFDXI]
+GSR=$HIDDEN$
+[ILDX_1]
+GSR=$HIDDEN$
+GTS=$HIDDEN$
+[ILDXI_1]
+GSR=$HIDDEN$
+GTS=$HIDDEN$
+[ILFFX]
+GSR=$HIDDEN$
+[ILFFXI]
+GSR=$HIDDEN$
+[ILFLX_1]
+GSR=$HIDDEN$
+GTS=$HIDDEN$
+[ILFLXI_1]
+GSR=$HIDDEN$
+GTS=$HIDDEN$
+[LDCE_1]
+GSR=$HIDDEN$
+GTS=$HIDDEN$
+[LDPE]
+GSR=$HIDDEN$
+GTS=$HIDDEN$
+[LDPE_1]
+GSR=$HIDDEN$
+GTS=$HIDDEN$
+[OAND2]
+GTS=$HIDDEN$
+[OBUF]
+GTS=$HIDDEN$
+[OBUFT]
+GTS=$HIDDEN$
+[OFDTX]
+GSR=$HIDDEN$
+GTS=$HIDDEN$
+[OFDTXI]
+GSR=$HIDDEN$
+GTS=$HIDDEN$
+[OFDX]
+GSR=$HIDDEN$
+GTS=$HIDDEN$
+[OFDXI]
+GTS=$HIDDEN$
+GSR=$HIDDEN$
+[OMUX2]
+GTS=$HIDDEN$
+[ONAND2]
+GTS=$HIDDEN$
+[ONOR2]
+GTS=$HIDDEN$
+[OOR2]
+GTS=$HIDDEN$
+[OXNOR2]
+GTS=$HIDDEN$
+[OXOR2]
+GTS=$HIDDEN$
diff --git a/fpga/hw-v2-mci/bde.set b/fpga/hw-v2-mci/bde.set
new file mode 100644
index 0000000..1d97a71
--- /dev/null
+++ b/fpga/hw-v2-mci/bde.set
@@ -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
diff --git a/fpga/hw-v2-mci/compilation.order b/fpga/hw-v2-mci/compilation.order
new file mode 100644
index 0000000..da3acce
--- /dev/null
+++ b/fpga/hw-v2-mci/compilation.order
@@ -0,0 +1,30 @@
+.\src\mt_toolbox\mt_toolbox.vhd
+.\src\mt_toolbox\mt_clktools.vhd
+.\src\mt_toolbox\mt_synctools.vhd
+.\src\mt_filter\mt_filter.vhd
+.\src\mt_filter\mt_fil_storage_slow.vhd
+.\src\mt_filter\mt_fil_mac_slow.vhd
+.\src\mt_filter\mt_fir_symmetric_slow.vhd
+.\src\sdio\sdio_txfifo.vhd
+.\src\sdio\sdio_txctrl.vhd
+.\src\sdio\sdio_cmd.vhd
+.\src\sdio\sdio_dat.vhd
+.\src\sdio\sdio_top.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\datapath\usbrx_sdio.vhd
+.\src\usbrx\toplevel\usbrx_clkgen.vhd
+.\src\usbrx\toplevel\usbrx_clkref.vhd
+.\src\usbrx\toplevel\usbrx_gpio.vhd
+.\src\usbrx\toplevel\usbrx_spi.vhd
+.\src\usbrx\toplevel\usbrx_regbank.vhd
+.\src\usbrx\toplevel\usbrx_pwm.vhd
+.\src\usbrx\toplevel\usbrx_toplevel.vhd
+.\src\testbench\tb_sdio.vhd
+.\src\testbench\tb_sdio_stim.vhd
+.\src\testbench\tb_filter.vhd
+.\src\testbench\tb_usbrx.vhd
diff --git a/fpga/hw-v2-mci/compile.cfg b/fpga/hw-v2-mci/compile.cfg
new file mode 100644
index 0000000..c94c037
--- /dev/null
+++ b/fpga/hw-v2-mci/compile.cfg
@@ -0,0 +1,68 @@
+[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\usbrx.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
+[file:.\src\usbrx\toplevel\usbrx_clkref.vhd]
+Enabled=1
+[file:.\src\mt_toolbox\mt_synctools.vhd]
+Enabled=1
+[file:.\src\usbrx\toplevel\usbrx_gpio.vhd]
+Enabled=1
+[file:.\src\sdio\sdio_top.vhd]
+Enabled=1
+[file:.\src\testbench\tb_sdio.vhd]
+Enabled=1
+[file:.\src\sdio\sdio_cmd.vhd]
+Enabled=1
+[file:.\src\usbrx\datapath\usbrx_ad7357.vhd]
+Enabled=1
+[file:.\src\usbrx\datapath\usbrx_offset.vhd]
+Enabled=1
+[file:.\src\usbrx\datapath\usbrx_decimate.vhd]
+Enabled=1
+[file:.\src\usbrx\datapath\usbrx_ssc.vhd]
+Enabled=1
+[file:.\src\sdio\sdio_dat.vhd]
+Enabled=1
+[file:.\src\sdio\sdio_txctrl.vhd]
+Enabled=1
+[file:.\src\sdio\sdio_txfifo.vhd]
+Enabled=1
+[file:.\src\usbrx\datapath\usbrx_sdio.vhd]
+Enabled=1
+[file:.\src\testbench\tb_sdio_stim.vhd]
+Enabled=1
diff --git a/fpga/hw-v2-mci/deploy/.gitattributes b/fpga/hw-v2-mci/deploy/.gitattributes
new file mode 100644
index 0000000..4a1f4b3
--- /dev/null
+++ b/fpga/hw-v2-mci/deploy/.gitattributes
@@ -0,0 +1,2 @@
+*.vme -crlf -diff
+
diff --git a/fpga/hw-v2-mci/deploy/usbrx.xcf b/fpga/hw-v2-mci/deploy/usbrx.xcf
new file mode 100644
index 0000000..e67c635
--- /dev/null
+++ b/fpga/hw-v2-mci/deploy/usbrx.xcf
@@ -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>
diff --git a/fpga/hw-v2-mci/deploy/usbrx_data.vme b/fpga/hw-v2-mci/deploy/usbrx_data.vme
index 44efbaf..887e981 100644
--- a/fpga/hw-v2-mci/deploy/usbrx_data.vme
+++ b/fpga/hw-v2-mci/deploy/usbrx_data.vme
Binary files differ
diff --git a/fpga/hw-v2-mci/diamond/.run_manager.ini b/fpga/hw-v2-mci/diamond/.run_manager.ini
new file mode 100644
index 0000000..bf1b20d
--- /dev/null
+++ b/fpga/hw-v2-mci/diamond/.run_manager.ini
@@ -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
diff --git a/fpga/hw-v2-mci/diamond/.setting.ini b/fpga/hw-v2-mci/diamond/.setting.ini
new file mode 100644
index 0000000..180a0c1
--- /dev/null
+++ b/fpga/hw-v2-mci/diamond/.setting.ini
@@ -0,0 +1,4 @@
+[General]
+PAR.auto_tasks=PARTrace, IOTiming
+Map.auto_tasks=@Invalid()
+Export.auto_tasks=TimingSimFileVHD, Bitgen
diff --git a/fpga/hw-v2-mci/diamond/Strategy1.sty b/fpga/hw-v2-mci/diamond/Strategy1.sty
new file mode 100644
index 0000000..5c3e268
--- /dev/null
+++ b/fpga/hw-v2-mci/diamond/Strategy1.sty
@@ -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>
diff --git a/fpga/hw-v2-mci/diamond/reportview.xml b/fpga/hw-v2-mci/diamond/reportview.xml
new file mode 100644
index 0000000..c1a5034
--- /dev/null
+++ b/fpga/hw-v2-mci/diamond/reportview.xml
@@ -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>
diff --git a/fpga/hw-v2-mci/diamond/usbrx_vhdl.ldf b/fpga/hw-v2-mci/diamond/usbrx_vhdl.ldf
new file mode 100644
index 0000000..5c95a84
--- /dev/null
+++ b/fpga/hw-v2-mci/diamond/usbrx_vhdl.ldf
@@ -0,0 +1,95 @@
+<?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="../src/sdio/sdio_top.vhd" type="VHDL" type_short="VHDL">
+ <Options/>
+ </Source>
+ <Source name="../src/usbrx/toplevel/usbrx_clkref.vhd" type="VHDL" type_short="VHDL">
+ <Options/>
+ </Source>
+ <Source name="../src/usbrx/toplevel/usbrx_gpio.vhd" type="VHDL" type_short="VHDL">
+ <Options/>
+ </Source>
+ <Source name="../src/mt_toolbox/mt_synctools.vhd" type="VHDL" type_short="VHDL">
+ <Options/>
+ </Source>
+ <Source name="../src/sdio/sdio_cmd.vhd" type="VHDL" type_short="VHDL">
+ <Options/>
+ </Source>
+ <Source name="../src/sdio/sdio_dat.vhd" type="VHDL" type_short="VHDL">
+ <Options/>
+ </Source>
+ <Source name="../src/sdio/sdio_txctrl.vhd" type="VHDL" type_short="VHDL">
+ <Options/>
+ </Source>
+ <Source name="../src/sdio/sdio_txfifo.vhd" type="VHDL" type_short="VHDL">
+ <Options/>
+ </Source>
+ <Source name="../src/usbrx/datapath/usbrx_sdio.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>
diff --git a/fpga/hw-v2-mci/diamond/usbrx_vhdl.lpf b/fpga/hw-v2-mci/diamond/usbrx_vhdl.lpf
new file mode 100644
index 0000000..0ef2ce6
--- /dev/null
+++ b/fpga/hw-v2-mci/diamond/usbrx_vhdl.lpf
@@ -0,0 +1,133 @@
+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 "led" SITE "M7" ;
+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 ;
+IOBUF PORT "gpio_0" IO_TYPE=LVCMOS33 DRIVE=4 SLEWRATE=SLOW;
+IOBUF PORT "gpio_1" IO_TYPE=LVCMOS33 DRIVE=4 SLEWRATE=SLOW;
+IOBUF PORT "gpio_2" IO_TYPE=LVCMOS33 DRIVE=4 SLEWRATE=SLOW;
+IOBUF PORT "gpio_3" IO_TYPE=LVCMOS33 DRIVE=4 SLEWRATE=SLOW;
+IOBUF PORT "gpio_4" IO_TYPE=LVCMOS33 DRIVE=4 SLEWRATE=SLOW;
+IOBUF PORT "gpio_5" IO_TYPE=LVCMOS33 DRIVE=4 SLEWRATE=SLOW;
+IOBUF PORT "gpio_6" IO_TYPE=LVCMOS33 DRIVE=4 SLEWRATE=SLOW;
+IOBUF PORT "gpio_7" IO_TYPE=LVCMOS33 DRIVE=4 SLEWRATE=SLOW;
+IOBUF PORT "gpio_8" IO_TYPE=LVCMOS33 DRIVE=4 SLEWRATE=SLOW;
+IOBUF PORT "gpio_9" IO_TYPE=LVCMOS33 DRIVE=4 SLEWRATE=SLOW;
+IOBUF PORT "led" IO_TYPE=LVCMOS33 DRIVE=4 ;
+IOBUF PORT "vgnd_0" IO_TYPE=LVCMOS33 DRIVE=4 ;
+IOBUF PORT "vgnd_1" IO_TYPE=LVCMOS33 DRIVE=4 ;
+IOBUF PORT "vgnd_2" IO_TYPE=LVCMOS33 DRIVE=4 ;
+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 "gpio_4" 50.000000 MHz ;
+FREQUENCY PORT "clk_in_pclk" 30.000000 MHz ;
+FREQUENCY NET "clk_80_c" 80.000000 MHz ;
+SYSCONFIG INBUF=OFF ;
diff --git a/fpga/hw-v2-mci/diamond/usbrx_vhdl.pty b/fpga/hw-v2-mci/diamond/usbrx_vhdl.pty
new file mode 100644
index 0000000..537921f
--- /dev/null
+++ b/fpga/hw-v2-mci/diamond/usbrx_vhdl.pty
@@ -0,0 +1,3 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE strategy>
+<Strategy version="1.0" predefined="0" description="" label=""/>
diff --git a/fpga/hw-v2-mci/library.cfg b/fpga/hw-v2-mci/library.cfg
new file mode 100644
index 0000000..f78211c
--- /dev/null
+++ b/fpga/hw-v2-mci/library.cfg
@@ -0,0 +1,2 @@
+$include = "$VSIMSALIBRARYCFG"
+usbrx_vhdl = "./usbrx_vhdl.LIB" 1322060719953
diff --git a/fpga/hw-v2-mci/projlib.cfg b/fpga/hw-v2-mci/projlib.cfg
new file mode 100644
index 0000000..23f76a5
--- /dev/null
+++ b/fpga/hw-v2-mci/projlib.cfg
@@ -0,0 +1 @@
+usbrx_vhdl = "./usbrx_vhdl.LIB" 1322060719655
diff --git a/fpga/hw-v2-mci/src/mt_filter/mt_fil_mac_slow.vhd b/fpga/hw-v2-mci/src/mt_filter/mt_fil_mac_slow.vhd
new file mode 100644
index 0000000..603b72a
--- /dev/null
+++ b/fpga/hw-v2-mci/src/mt_filter/mt_fil_mac_slow.vhd
@@ -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;
diff --git a/fpga/hw-v2-mci/src/mt_filter/mt_fil_storage_slow.vhd b/fpga/hw-v2-mci/src/mt_filter/mt_fil_storage_slow.vhd
new file mode 100644
index 0000000..05f4eae
--- /dev/null
+++ b/fpga/hw-v2-mci/src/mt_filter/mt_fil_storage_slow.vhd
@@ -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;
diff --git a/fpga/hw-v2-mci/src/mt_filter/mt_filter.vhd b/fpga/hw-v2-mci/src/mt_filter/mt_filter.vhd
new file mode 100644
index 0000000..bfdbdb4
--- /dev/null
+++ b/fpga/hw-v2-mci/src/mt_filter/mt_filter.vhd
@@ -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;
+
diff --git a/fpga/hw-v2-mci/src/mt_filter/mt_fir_symmetric_slow.vhd b/fpga/hw-v2-mci/src/mt_filter/mt_fir_symmetric_slow.vhd
new file mode 100644
index 0000000..fcb6ff6
--- /dev/null
+++ b/fpga/hw-v2-mci/src/mt_filter/mt_fir_symmetric_slow.vhd
@@ -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;
diff --git a/fpga/hw-v2-mci/src/mt_toolbox/mt_clktools.vhd b/fpga/hw-v2-mci/src/mt_toolbox/mt_clktools.vhd
new file mode 100644
index 0000000..1a1d47e
--- /dev/null
+++ b/fpga/hw-v2-mci/src/mt_toolbox/mt_clktools.vhd
@@ -0,0 +1,141 @@
+---------------------------------------------------------------------------------------------------
+-- 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
+ );
+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;
+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;
diff --git a/fpga/hw-v2-mci/src/mt_toolbox/mt_synctools.vhd b/fpga/hw-v2-mci/src/mt_toolbox/mt_synctools.vhd
new file mode 100644
index 0000000..722eaca
--- /dev/null
+++ b/fpga/hw-v2-mci/src/mt_toolbox/mt_synctools.vhd
@@ -0,0 +1,135 @@
+-----------------------------------------------------------------------------------
+-- Filename : mt_synctools.vhd
+-- Project : maintech IP-Core toolbox
+-- Purpose : Basic tools for clock-domain-crossings
+--
+-----------------------------------------------------------------------------------
+
+-----------------------------------------------------------------------------------
+-- Copyright (C) 2012 maintech GmbH, Otto-Hahn-Str. 15, 97204 Hoechberg, Germany --
+-- written by Matthias Kleffel --
+-- --
+-- This program is free software; you can redistribute it and/or modify --
+-- it under the terms of the GNU General Public License as published by --
+-- the Free Software Foundation as version 3 of the License, or --
+-- --
+-- This program is distributed in the hope that it will be useful, --
+-- but WITHOUT ANY WARRANTY; without even the implied warranty of --
+-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the --
+-- GNU General Public License V3 for more details. --
+-- --
+-- You should have received a copy of the GNU General Public License --
+-- along with this program. If not, see <http://www.gnu.org/licenses/>. --
+-----------------------------------------------------------------------------------
+
+
+------------------------------------------------------------------------------
+-- mt_sync_dualff (dual flip-flop synchronizer) -------------------------------
+-------------------------------------------------------------------------------
+
+library ieee;
+ use ieee.std_logic_1164.all;
+library work;
+ use work.mt_toolbox.all;
+
+entity mt_sync_dualff is
+ port(
+ -- input
+ i_data : in std_logic;
+
+ -- output
+ o_clk : in std_logic;
+ o_data : out std_logic
+ );
+end mt_sync_dualff;
+
+architecture rtl of mt_sync_dualff is
+ -- signals
+ signal sreg : std_logic := '0';
+ signal oreg : std_logic := '0';
+
+ -- no SRL16s here...
+ attribute shreg_extract of sreg : signal is "no";
+ attribute shreg_extract of oreg : signal is "no";
+
+begin
+ process(o_clk)
+ begin
+ if rising_edge(o_clk) then
+ sreg <= i_data;
+ oreg <= sreg;
+ end if;
+ end process;
+ o_data <= oreg;
+end rtl;
+
+
+-------------------------------------------------------------------------------
+-- mt_sync_feedback (feedback synchronizer) -----------------------------------
+-------------------------------------------------------------------------------
+
+library ieee;
+ use ieee.std_logic_1164.all;
+library work;
+ use work.mt_toolbox.all;
+
+entity mt_sync_feedback is
+ port(
+ -- input
+ i_clk : in std_logic;
+ i_data : in std_logic;
+
+ -- output
+ o_clk : in std_logic;
+ o_data : out std_logic
+ );
+end mt_sync_feedback;
+
+architecture rtl of mt_sync_feedback is
+
+ signal flip_i : std_logic := '0';
+ signal flip_s1 : std_logic := '0';
+ signal flip_s2 : std_logic := '0';
+ signal flip_s3 : std_logic := '0';
+ signal oreg : std_logic := '0';
+
+ attribute syn_keep of flip_i : signal is true;
+ attribute syn_keep of flip_s1 : signal is true;
+ attribute syn_keep of flip_s2 : signal is true;
+ attribute syn_keep of flip_s3 : signal is true;
+ attribute syn_keep of oreg : signal is true;
+
+begin
+
+ process(i_clk)
+ begin
+ if rising_edge(i_clk) then
+ -- update flip-bit on request
+ if i_data='1' then
+ flip_i <= not flip_i;
+ end if;
+
+ -- debug check
+ assert not (i_data='1' and flip_s1/=flip_i)
+ report "mt_sync_feedback: pulses too close, failed to synchronize"
+ severity failure;
+ end if;
+ end process;
+
+ process(o_clk)
+ begin
+ if rising_edge(o_clk) then
+ -- synchronize flip-bit
+ flip_s1 <= flip_i;
+ flip_s2 <= flip_s1;
+ flip_s3 <= flip_s2;
+
+ -- create output-request
+ oreg <= flip_s3 xor flip_s2;
+ end if;
+ end process;
+
+ -- set output
+ o_data <= oreg;
+
+end rtl;
diff --git a/fpga/hw-v2-mci/src/mt_toolbox/mt_toolbox.vhd b/fpga/hw-v2-mci/src/mt_toolbox/mt_toolbox.vhd
new file mode 100644
index 0000000..2644d87
--- /dev/null
+++ b/fpga/hw-v2-mci/src/mt_toolbox/mt_toolbox.vhd
@@ -0,0 +1,202 @@
+---------------------------------------------------------------------------------------------------
+-- 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;
+ function bin2gray(x : unsigned) return unsigned;
+ function gray2bin(x : unsigned) return unsigned;
+
+ --
+ -- 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;
+ attribute shreg_extract : 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;
+
+ -- convert binary number to gray code
+ function bin2gray(x : unsigned) return unsigned is
+ begin
+ return x xor ('0' & x(x'high downto 1));
+ end bin2gray;
+
+ -- convert gray code to binary number
+ function gray2bin(x : unsigned) return unsigned is
+ variable res : unsigned(x'range);
+ begin
+ res(x'high) := x(x'high);
+ for i in x'high-1 downto 0 loop
+ res(i) := x(i) xor res(i+1);
+ end loop;
+ return res;
+ end gray2bin;
+end mt_toolbox;
+
diff --git a/fpga/hw-v2-mci/src/sdio/sdio_cmd.vhd b/fpga/hw-v2-mci/src/sdio/sdio_cmd.vhd
new file mode 100644
index 0000000..84d849c
--- /dev/null
+++ b/fpga/hw-v2-mci/src/sdio/sdio_cmd.vhd
@@ -0,0 +1,589 @@
+
+-----------------------------------------------------------------------------------
+-- Copyright (C) 2013 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 sdio_cmd_rx is
+ port(
+ -- common
+ clk : in std_logic;
+ reset : in std_logic;
+
+ -- SDIO interface
+ sd_clk : in std_logic;
+ sd_cmd_i : in std_logic;
+
+ -- control/status
+ tx_active : in std_logic;
+
+ -- 'event' output
+ cmd_ok : out std_logic;
+ cmd_err : out std_logic;
+
+ -- command data
+ cmd_ind : out unsigned(5 downto 0);
+ cmd_arg : out std_logic_vector(31 downto 0)
+ );
+end sdio_cmd_rx;
+
+architecture rtl of sdio_cmd_rx is
+
+ -- state
+ type state_t is (
+ S_IDLE,
+ S_CMD_DIR,
+ S_CMD_IND,
+ S_CMD_ARG,
+ S_CMD_CRC,
+ S_CMD_DONE);
+
+ -- status
+ signal state : state_t;
+ signal remain : unsigned(4 downto 0);
+
+ -- shift-register
+ signal tmp_ind : std_logic_vector(5 downto 0);
+ signal tmp_arg : std_logic_vector(31 downto 0);
+
+ -- CRC
+ signal crc7 : std_logic_vector(6 downto 0);
+
+begin
+
+ -- command receiver
+ process(sd_clk,reset)
+ begin
+ if reset='1' then
+ state <= S_IDLE;
+ remain <= (others=>'0');
+ tmp_ind <= (others=>'0');
+ tmp_arg <= (others=>'0');
+ crc7 <= (others=>'0');
+ cmd_ok <= '0';
+ cmd_err <= '0';
+ cmd_ind <= (others=>'0');
+ cmd_arg <= (others=>'0');
+ elsif rising_edge(sd_clk) then
+ -- set default values;
+ cmd_ok <= '0';
+ cmd_err <= '0';
+
+ -- update CRC
+ if sd_cmd_i /= crc7(6)
+ then crc7 <= (crc7(5 downto 0) & "0") xor "0001001";
+ else crc7 <= (crc7(5 downto 0) & "0");
+ end if;
+
+ -- update state
+ case state is
+ when S_IDLE =>
+ -- wait for start-bit
+ if sd_cmd_i='0' then
+ --> start receiving
+ state <= S_CMD_DIR;
+ crc7 <= (others=>'0');
+ end if;
+
+ when S_CMD_DIR =>
+ -- check direction-bit
+ if sd_cmd_i='1' then
+ --> start receiving command-index
+ state <= S_CMD_IND;
+ remain <= to_unsigned(6-1,5);
+ else
+ --> should not happen
+ state <= S_IDLE;
+ end if;
+
+ when S_CMD_IND =>
+ -- latch bit
+ tmp_ind <= tmp_ind(tmp_ind'left-1 downto 0) & sd_cmd_i;
+
+ -- update status
+ remain <= remain-1;
+ if remain=0 then
+ state <= S_CMD_ARG;
+ remain <= to_unsigned(32-1,5);
+ end if;
+
+ when S_CMD_ARG =>
+ -- latch bit
+ tmp_arg <= tmp_arg(tmp_arg'left-1 downto 0) & sd_cmd_i;
+
+ -- update status
+ remain <= remain-1;
+ if remain=0 then
+ state <= S_CMD_CRC;
+ remain <= to_unsigned(7-1,5);
+ end if;
+
+ when S_CMD_CRC =>
+ -- update status
+ remain <= remain-1;
+ if remain=0 then
+ state <= S_CMD_DONE;
+ end if;
+
+ when S_CMD_DONE =>
+ -- verify CRC
+ if crc7="0000000" then
+ --> CRC ok
+ cmd_ok <= '1';
+ cmd_ind <= unsigned(tmp_ind);
+ cmd_arg <= tmp_arg;
+ else
+ --> CRC error
+ cmd_err <= '1';
+ end if;
+
+ -- return to idle state
+ state <= S_IDLE;
+ end case;
+
+ -- always return to idle state when transmitter is active
+ if tx_active='1' then
+ state <= S_IDLE;
+ end if;
+
+ end if;
+ end process;
+
+end rtl;
+
+-------------------------------------------------------------------------------
+
+library ieee;
+ use ieee.std_logic_1164.all;
+ use ieee.numeric_std.all;
+library work;
+ use work.all;
+ use work.mt_toolbox.all;
+
+entity sdio_cmd_tx is
+ port(
+ -- common
+ clk : in std_logic;
+ reset : in std_logic;
+
+ -- SDIO interface
+ sd_clk : in std_logic;
+ sd_cmd_oe : out std_logic;
+ sd_cmd_o : out std_logic;
+
+ -- control/status
+ tx_active : out std_logic;
+
+ -- response control
+ res_start : in std_logic;
+ res_done : out std_logic;
+
+ -- response data
+ res_ind : in unsigned(5 downto 0);
+ res_arg : in std_logic_vector(31 downto 0)
+ );
+
+ attribute syn_useioff : boolean;
+ attribute syn_useioff of sd_cmd_oe : signal is true;
+ attribute syn_useioff of sd_cmd_o : signal is true;
+
+end sdio_cmd_tx;
+
+architecture rtl of sdio_cmd_tx is
+
+ -- state
+ type state_t is (
+ S_IDLE,
+ S_RES_DIR,
+ S_RES_IND,
+ S_RES_ARG,
+ S_RES_CRC,
+ S_RES_DONE
+ );
+
+ -- status
+ signal state : state_t;
+ signal remain : unsigned(4 downto 0);
+
+ -- shift-register
+ signal sreg : std_logic_vector(31 downto 0);
+
+ -- CRC
+ signal crc7 : std_logic_vector(6 downto 0);
+
+begin
+
+ -- command receiver
+ process(sd_clk,reset)
+ begin
+ if reset='1' then
+ state <= S_IDLE;
+ remain <= (others=>'0');
+ sreg <= (others=>'1');
+ crc7 <= (others=>'0');
+ sd_cmd_oe <= '0';
+ sd_cmd_o <= '0';
+ res_done <= '0';
+ tx_active <= '0';
+ elsif rising_edge(sd_clk) then
+ -- set default values;
+ sd_cmd_oe <= '0';
+ sd_cmd_o <= '0';
+ res_done <= '0';
+
+ -- update state
+ case state is
+ when S_IDLE =>
+ -- wait for start-request
+ if res_start='1' then
+ --> start transmitting
+ state <= S_RES_DIR;
+
+ -- write start-bit
+ sd_cmd_oe <= '1';
+ sd_cmd_o <= '0';
+ end if;
+
+ when S_RES_DIR =>
+ -- write direction-bit
+ sd_cmd_oe <= '1';
+ sd_cmd_o <= '0';
+
+ -- prepare writing command-index
+ sreg(31 downto 26) <= std_logic_vector(res_ind);
+
+ -- update status
+ state <= S_RES_IND;
+ remain <= to_unsigned(6-1,5);
+
+ when S_RES_IND =>
+ -- write next bit
+ sd_cmd_oe <= '1';
+ sd_cmd_o <= sreg(31);
+
+ -- update shift-register
+ sreg <= sreg(30 downto 0) & '1';
+
+ -- update status
+ remain <= remain-1;
+ if remain=0 then
+ sreg <= res_arg;
+ state <= S_RES_ARG;
+ remain <= to_unsigned(32-1,5);
+ end if;
+
+ when S_RES_ARG =>
+ -- write next bit
+ sd_cmd_oe <= '1';
+ sd_cmd_o <= sreg(31);
+
+ -- update shift-register
+ sreg <= sreg(30 downto 0) & '1';
+
+ -- update status
+ remain <= remain-1;
+ if remain=0 then
+ state <= S_RES_CRC;
+ remain <= to_unsigned(7-1,5);
+ end if;
+
+ when S_RES_CRC =>
+ -- write CRC bit
+ sd_cmd_oe <= '1';
+ sd_cmd_o <= crc7(6);
+
+ -- update status
+ remain <= remain-1;
+ if remain=0 then
+ state <= S_RES_DONE;
+ end if;
+
+ when S_RES_DONE =>
+ -- write end-bit
+ sd_cmd_oe <= '1';
+ sd_cmd_o <= '1';
+
+ -- return to idle state
+ res_done <= '1';
+ state <= S_IDLE;
+ end case;
+
+ -- update CRC
+ if state=S_IDLE then
+ crc7 <= (others=>'0');
+ elsif state=S_RES_IND or state=S_RES_ARG then
+ if sreg(31) /= crc7(6)
+ then crc7 <= (crc7(5 downto 0) & "0") xor "0001001";
+ else crc7 <= (crc7(5 downto 0) & "0");
+ end if;
+ elsif state=S_RES_CRC then
+ crc7 <= (crc7(5 downto 0) & "0");
+ end if;
+
+ -- create active-flag
+ if state/=S_IDLE
+ then tx_active <= '1';
+ else tx_active <= '0';
+ end if;
+ end if;
+ end process;
+end rtl;
+
+-------------------------------------------------------------------------------
+
+library ieee;
+ use ieee.std_logic_1164.all;
+ use ieee.numeric_std.all;
+library work;
+ use work.all;
+ use work.mt_toolbox.all;
+
+entity sdio_cmd_handler is
+ port(
+ -- common
+ clk : in std_logic;
+ reset : in std_logic;
+ sd_clk : in std_logic;
+
+ -- status
+ dtx_active : in std_logic;
+
+ -- command receiver
+ cmd_ok : in std_logic;
+ cmd_err : in std_logic;
+ cmd_ind : in unsigned(5 downto 0);
+ cmd_arg : in std_logic_vector(31 downto 0);
+
+ -- response transmitter
+ res_start : out std_logic;
+ res_done : in std_logic;
+ res_ind : out unsigned(5 downto 0);
+ res_arg : out std_logic_vector(31 downto 0);
+
+ -- function0 - register-interface
+ fn0_rena : out std_logic;
+ fn0_wena : out std_logic;
+ fn0_addr : out unsigned(16 downto 0);
+ fn0_oor : in std_logic;
+ fn0_rdat : in std_logic_vector(7 downto 0);
+ fn0_wdat : out std_logic_vector(7 downto 0);
+
+ -- function1 - control
+ fn1_start : out std_logic;
+ fn1_count : out unsigned(8 downto 0)
+ );
+end sdio_cmd_handler;
+
+architecture rtl of sdio_cmd_handler is
+
+ -- state
+ type state_t is (
+ S_IDLE,
+ S_REG_READ1,
+ S_REG_READ2,
+ S_REG_WRITE1,
+ S_REG_WRITE2,
+ S_REG_RAW,
+ S_DUMMY_RESPONSE
+ );
+
+ -- status
+ signal state : state_t;
+
+ -- status flags
+ signal flags : std_logic_vector(7 downto 0);
+ signal flag_crc : std_logic; -- COM_CRC_ERROR
+ signal flag_cmd : std_logic; -- ILLEGAL_COMMAND
+ signal flag_err : std_logic; -- ERROR
+ signal flag_fun : std_logic; -- FUNCTION_NUMBER
+ signal flag_oor : std_logic; -- OUT_OF_RANGE
+
+begin
+
+ -- assemble status-flags
+ flags(7) <= flag_crc;
+ flags(6) <= flag_cmd;
+ flags(5) <= dtx_active;
+ flags(4) <= '0';
+ flags(3) <= flag_err;
+ flags(2) <= '0';
+ flags(1) <= flag_fun;
+ flags(0) <= flag_oor;
+
+ -- control logic
+ process(sd_clk,reset)
+ variable func : unsigned(2 downto 0);
+ begin
+ if reset='1' then
+ res_start <= '0';
+ res_ind <= (others=>'0');
+ res_arg <= (others=>'0');
+ state <= S_IDLE;
+ flag_crc <= '0';
+ flag_cmd <= '0';
+ flag_err <= '0';
+ flag_fun <= '0';
+ flag_oor <= '0';
+ fn0_rena <= '0';
+ fn0_wena <= '0';
+ fn0_addr <= (others=>'0');
+ fn0_wdat <= (others=>'0');
+ fn1_start <= '0';
+ fn1_count <= (others=>'0');
+ elsif rising_edge(sd_clk) then
+ -- set default-values
+ res_start <= '0';
+ fn1_start <= '0';
+
+ -- react on command
+ if cmd_ok='1' then
+ -- clear error-flags by default
+ flag_fun <= '0';
+ flag_oor <= '0';
+ flag_err <= '0';
+
+ -- check command-index
+ if cmd_ind=52 then
+ --> IO_RW_DIRECT
+
+ -- get function
+ func := unsigned(cmd_arg(30 downto 28));
+ if func=0 then
+ -- decode rest of argument
+ fn0_addr <= unsigned(cmd_arg(25 downto 9));
+ fn0_wdat <= cmd_arg(7 downto 0);
+ fn0_rena <= not cmd_arg(31);
+ fn0_wena <= cmd_arg(31);
+
+ -- update status
+ if cmd_arg(31)='0' then
+ state <= S_REG_READ1;
+ elsif cmd_arg(27)='0' then
+ state <= S_REG_WRITE1;
+ else
+ state <= S_REG_RAW;
+ end if;
+ else
+ -- invalid function number
+ flag_fun <= '1';
+ state <= S_DUMMY_RESPONSE;
+ end if;
+ elsif cmd_ind=53 then
+ --> IO_RW_EXTENDED
+
+ -- get function
+ func := unsigned(cmd_arg(30 downto 28));
+ if func=1 then
+ -- check direction
+ if cmd_arg(31)='0' and cmd_arg(27)='1' then
+ -- decode rest of argument
+ fn1_start <= '1';
+ fn1_count <= unsigned(cmd_arg(8 downto 0));
+
+ -- create response
+ state <= S_DUMMY_RESPONSE;
+ else
+ -- unsupported mode
+ flag_err <= '1';
+ state <= S_DUMMY_RESPONSE;
+ end if;
+ else
+ -- invalid function number
+ flag_fun <= '1';
+ state <= S_DUMMY_RESPONSE;
+ end if;
+ else
+ -- unknown command -> ignore
+ flag_cmd <= '1';
+ end if;
+ elsif cmd_err='1' then
+ --> error
+ flag_crc <= '1';
+ end if;
+
+ -- update status
+ case state is
+ when S_IDLE =>
+ null;
+
+ when S_REG_READ1 =>
+ -- wait-state
+ state <= S_REG_READ2;
+
+ when S_REG_WRITE1 =>
+ -- wait-state
+ state <= S_REG_READ2;
+
+ when S_REG_READ2 =>
+ if fn0_oor='0' then
+ -- assemble response with read-data
+ res_start <= '1';
+ res_ind <= cmd_ind;
+ res_arg(31 downto 16) <= x"0000";
+ res_arg(15 downto 8) <= flags;
+ res_arg( 7 downto 0) <= fn0_rdat;
+ state <= S_IDLE;
+ else
+ -- invalid address, report error
+ flag_oor <= '1';
+ state <= S_DUMMY_RESPONSE;
+ end if;
+
+ when S_REG_WRITE2 =>
+ if fn0_oor='0' then
+ -- assemble response with write-data
+ res_start <= '1';
+ res_ind <= cmd_ind;
+ res_arg(31 downto 16) <= x"0000";
+ res_arg(15 downto 8) <= flags;
+ res_arg( 7 downto 0) <= cmd_arg(7 downto 0);
+ state <= S_IDLE;
+ else
+ -- invalid address, report error
+ flag_oor <= '1';
+ state <= S_DUMMY_RESPONSE;
+ end if;
+
+ when S_REG_RAW =>
+ -- read-after-write -> issue read-request now
+ fn0_rena <= '1';
+ state <= S_REG_READ1;
+
+ when S_DUMMY_RESPONSE =>
+ -- assemble dummy-response (==> only flags)
+ res_start <= '1';
+ res_ind <= cmd_ind;
+ res_arg(31 downto 16) <= x"0000";
+ res_arg(15 downto 8) <= flags;
+ res_arg( 7 downto 0) <= x"00";
+ state <= S_IDLE;
+
+ end case;
+
+ -- clear some status-flags after response was transmitter
+ if res_done='1' then
+ flag_crc <= '0';
+ flag_cmd <= '0';
+ end if;
+ end if;
+ end process;
+end rtl;
diff --git a/fpga/hw-v2-mci/src/sdio/sdio_dat.vhd b/fpga/hw-v2-mci/src/sdio/sdio_dat.vhd
new file mode 100644
index 0000000..bd4ae93
--- /dev/null
+++ b/fpga/hw-v2-mci/src/sdio/sdio_dat.vhd
@@ -0,0 +1,247 @@
+
+-----------------------------------------------------------------------------------
+-- Copyright (C) 2013 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 sdio_dat_tx is
+ port(
+ -- common
+ clk : in std_logic;
+ reset : in std_logic;
+
+ -- control
+ start : in std_logic;
+ abort : in std_logic;
+ bcount : in unsigned(8 downto 0);
+ bsize : in unsigned(15 downto 0);
+
+ -- status
+ active : out std_logic;
+
+ -- input data
+ in_ready : in std_logic;
+ in_sync : out std_logic;
+ in_clk : out std_logic;
+ in_dat : in std_logic_vector(7 downto 0);
+
+ -- SDIO interface
+ sd_clk : in std_logic;
+ sd_dat_oe : out std_logic;
+ sd_dat_o : out std_logic_vector(3 downto 0)
+ );
+
+ attribute syn_useioff : boolean;
+ attribute syn_useioff of sd_dat_oe : signal is true;
+ attribute syn_useioff of sd_dat_o : signal is true;
+
+end sdio_dat_tx;
+
+architecture rtl of sdio_dat_tx is
+
+ -- state
+ type state_t is (
+ S_INACTIVE,
+ S_IDLE,
+ S_START,
+ S_DATA_H,
+ S_DATA_L,
+ S_CRC,
+ S_STOP
+ );
+
+ -- status
+ signal state : state_t;
+ signal bremain : unsigned(8 downto 0);
+ signal remain : unsigned(11 downto 0);
+ signal lsb : std_logic_vector(3 downto 0);
+
+ -- CRCs
+ signal crc0 : std_logic_vector(15 downto 0);
+ signal crc1 : std_logic_vector(15 downto 0);
+ signal crc2 : std_logic_vector(15 downto 0);
+ signal crc3 : std_logic_vector(15 downto 0);
+
+ -- update CRC16
+ function crc16_update(crc : std_logic_vector; dat : std_logic) return std_logic_vector is
+ begin
+ if dat /= crc(15)
+ then return (crc(14 downto 0) & "0") xor x"1021";
+ else return (crc(14 downto 0) & "0");
+ end if;
+ end crc16_update;
+
+begin
+
+ -- control logic
+ process(sd_clk,reset)
+ begin
+ if reset='1' then
+ state <= S_INACTIVE;
+ bremain <= (others=>'0');
+ remain <= (others=>'0');
+ lsb <= (others=>'0');
+ crc0 <= (others=>'0');
+ crc1 <= (others=>'0');
+ crc2 <= (others=>'0');
+ crc3 <= (others=>'0');
+ in_clk <= '0';
+ in_sync <= '0';
+ sd_dat_oe <= '0';
+ sd_dat_o <= "0000";
+ elsif rising_edge(sd_clk) then
+ -- set default values;
+ in_clk <= '0';
+ in_sync <= '0';
+ sd_dat_oe <= '0';
+
+ -- update state
+ case state is
+ when S_INACTIVE =>
+ -- wait for start-request
+ if start='1' then
+ bremain <= bcount;
+ state <= S_IDLE;
+ end if;
+
+ when S_IDLE =>
+ -- wait until input is ready
+ if in_ready='1' then
+ -- request first byte
+ in_clk <= '1';
+ in_sync <= '1';
+
+ -- update status
+ remain <= resize(bsize-1,12);
+ state <= S_START;
+ end if;
+
+ when S_START =>
+ -- output start-bits
+ sd_dat_oe <= '1';
+ sd_dat_o <= "0000";
+
+ -- update status
+ state <= S_DATA_H;
+
+ when S_DATA_H =>
+ -- output MSBs
+ sd_dat_oe <= '1';
+ sd_dat_o <= in_dat(7 downto 4);
+
+ -- latch rest of byte & request next-byte
+ lsb <= in_dat(3 downto 0);
+ if remain>0 then
+ in_clk <= '1';
+ end if;
+
+ -- update status
+ state <= S_DATA_L;
+
+ when S_DATA_L =>
+ -- output LSBs
+ sd_dat_oe <= '1';
+ sd_dat_o <= lsb;
+
+ -- update status
+ remain <= remain-1;
+ if remain>0 then
+ --> continue with next byte
+ state <= S_DATA_H;
+ else
+ --> continue with CRC
+ state <= S_CRC;
+ remain <= to_unsigned(15,12);
+ end if;
+
+ when S_CRC =>
+ -- output CRC-bits
+ sd_dat_oe <= '1';
+ sd_dat_o(0) <= crc0(15);
+ sd_dat_o(1) <= crc1(15);
+ sd_dat_o(2) <= crc2(15);
+ sd_dat_o(3) <= crc3(15);
+
+ -- update status
+ remain <= remain-1;
+ if remain=0 then
+ --> done
+ state <= S_STOP;
+ end if;
+
+ when S_STOP =>
+ -- output end-bits
+ sd_dat_oe <= '1';
+ sd_dat_o <= "1111";
+
+ -- update status
+ if bremain=0 then
+ --> continious read
+ state <= S_IDLE;
+ elsif bremain>1 then
+ --> continue limited read
+ bremain <= bremain - 1;
+ state <= S_IDLE;
+ else
+ --> limited read done
+ state <= S_INACTIVE;
+ end if;
+ end case;
+
+ -- handle abort-request
+ if abort='1' then
+ state <= S_INACTIVE;
+ end if;
+
+ -- update CRC
+ if state=S_IDLE then
+ -- reset CRCs
+ crc0 <= x"0000";
+ crc1 <= x"0000";
+ crc2 <= x"0000";
+ crc3 <= x"0000";
+ elsif state=S_DATA_H then
+ -- update CRCs
+ crc0 <= crc16_update(crc0, in_dat(4));
+ crc1 <= crc16_update(crc1, in_dat(5));
+ crc2 <= crc16_update(crc2, in_dat(6));
+ crc3 <= crc16_update(crc3, in_dat(7));
+ elsif state=S_DATA_L then
+ -- update CRCs
+ crc0 <= crc16_update(crc0, lsb(0));
+ crc1 <= crc16_update(crc1, lsb(1));
+ crc2 <= crc16_update(crc2, lsb(2));
+ crc3 <= crc16_update(crc3, lsb(3));
+ elsif state=S_CRC then
+ -- shift CRCs
+ crc0 <= (crc0(14 downto 0) & "0");
+ crc1 <= (crc1(14 downto 0) & "0");
+ crc2 <= (crc2(14 downto 0) & "0");
+ crc3 <= (crc3(14 downto 0) & "0");
+ end if;
+ end if;
+ end process;
+
+ -- create stats-flag
+ active <= '1' when (state/=S_INACTIVE) else '0';
+
+end rtl;
diff --git a/fpga/hw-v2-mci/src/sdio/sdio_top.vhd b/fpga/hw-v2-mci/src/sdio/sdio_top.vhd
new file mode 100644
index 0000000..6997f8f
--- /dev/null
+++ b/fpga/hw-v2-mci/src/sdio/sdio_top.vhd
@@ -0,0 +1,286 @@
+
+-----------------------------------------------------------------------------------
+-- Copyright (C) 2013 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 sdio_top is
+ port (
+ -- common
+ clk : in std_logic;
+ reset : in std_logic;
+
+ -- input
+ in_clk : in std_logic;
+ in_data : in std_logic_vector(31 downto 0);
+
+ -- SDIO interface
+ sd_clk : in std_logic;
+ sd_cmd : inout std_logic;
+ sd_dat : inout std_logic_vector(3 downto 0)
+ );
+end sdio_top;
+
+architecture rtl of sdio_top is
+
+ -- spitted tristate pads
+ signal sd_cmd_i : std_logic;
+ signal sd_cmd_o : std_logic;
+ signal sd_cmd_oe : std_logic;
+ signal sd_dat_i : std_logic_vector(3 downto 0);
+ signal sd_dat_o : std_logic_vector(3 downto 0);
+ signal sd_dat_oe : std_logic;
+
+ -- status/control
+ signal ctx_active : std_logic;
+ signal dtx_active : std_logic;
+
+ -- command receiver
+ signal cmd_ok : std_logic;
+ signal cmd_err : std_logic;
+ signal cmd_ind : unsigned(5 downto 0);
+ signal cmd_arg : std_logic_vector(31 downto 0);
+
+ -- response transmitter
+ signal res_start : std_logic;
+ signal res_done : std_logic;
+ signal res_ind : unsigned(5 downto 0);
+ signal res_arg : std_logic_vector(31 downto 0);
+
+ -- bus-interface
+ signal bus_rena : std_logic;
+ signal bus_wena : std_logic;
+ signal bus_addr : unsigned(16 downto 0);
+ signal bus_oor : std_logic;
+ signal bus_rdat : std_logic_vector(7 downto 0);
+ signal bus_wdat : std_logic_vector(7 downto 0);
+
+ -- registers
+ signal fn1_start : std_logic;
+ signal fn1_abort : std_logic;
+ signal fn1_count : unsigned(8 downto 0);
+ signal fn1_bsize : unsigned(15 downto 0);
+
+ -- TX-control <-> TX-core
+ signal tx_ready : std_logic;
+ signal tx_sync : std_logic;
+ signal tx_clk : std_logic;
+ signal tx_dat : std_logic_vector(7 downto 0);
+
+begin
+
+ -- create tristate pads
+ sd_cmd_i <= to_X01(sd_cmd);
+ sd_dat_i <= to_X01(sd_dat);
+ sd_cmd <= sd_cmd_o when sd_cmd_oe='1' else 'Z';
+ sd_dat <= sd_dat_o when sd_dat_oe='1' else "ZZZZ";
+
+
+ --
+ -- control logic
+ --
+
+ process(sd_clk,reset)
+ begin
+ if reset='1' then
+ bus_oor <= '0';
+ bus_rdat <= x"00";
+ fn1_bsize <= x"0200";
+ fn1_abort <= '0';
+ elsif rising_edge(sd_clk) then
+ -- set default values
+ bus_oor <= '0';
+ bus_rdat <= x"00";
+ fn1_abort <= '0';
+
+ -- handle request
+ case to_integer(bus_addr) is
+ -- some random static registers
+ when 0 =>
+ bus_rdat <= x"43";
+ when 1 =>
+ bus_rdat <= x"03";
+
+ -- IO Abort
+ when 6 =>
+ if bus_wena='1' and bus_wdat(2 downto 0)="001" then
+ fn1_abort <= '1';
+ end if;
+
+ -- FN1 blocksize
+ when 16#110# =>
+ bus_rdat <= to_slv8(fn1_bsize(7 downto 0));
+ if bus_wena='1' then
+ fn1_bsize(7 downto 0) <= unsigned(bus_wdat);
+ end if;
+ when 16#111# =>
+ bus_rdat <= to_slv8(fn1_bsize(15 downto 8));
+ if bus_wena='1' then
+ fn1_bsize(15 downto 8) <= unsigned(bus_wdat);
+ end if;
+
+ when others =>
+ -- unknown register
+ bus_oor <= '1';
+ end case;
+ end if;
+ end process;
+
+
+ --
+ -- components
+ --
+
+ -- command receiver
+ crx: entity sdio_cmd_rx
+ port map (
+ -- common
+ clk => clk,
+ reset => reset,
+
+ -- SDIO interface
+ sd_clk => sd_clk,
+ sd_cmd_i => sd_cmd_i,
+
+ -- status/control
+ tx_active => ctx_active,
+
+ -- 'event' output
+ cmd_ok => cmd_ok,
+ cmd_err => cmd_err,
+
+ -- command data
+ cmd_ind => cmd_ind,
+ cmd_arg => cmd_arg
+ );
+
+ -- response transmitter
+ ctx: entity sdio_cmd_tx
+ port map (
+ -- common
+ clk => clk,
+ reset => reset,
+
+ -- SDIO interface
+ sd_clk => sd_clk,
+ sd_cmd_oe => sd_cmd_oe,
+ sd_cmd_o => sd_cmd_o,
+
+ -- status/control
+ tx_active => ctx_active,
+
+ -- response control
+ res_start => res_start,
+ res_done => res_done,
+
+ -- response data
+ res_ind => res_ind,
+ res_arg => res_arg
+ );
+
+ -- command handler
+ cmd: entity sdio_cmd_handler
+ port map (
+ -- common
+ clk => clk,
+ reset => reset,
+ sd_clk => sd_clk,
+
+ -- status
+ dtx_active => dtx_active,
+
+ -- command receiver
+ cmd_ok => cmd_ok,
+ cmd_err => cmd_err,
+ cmd_ind => cmd_ind,
+ cmd_arg => cmd_arg,
+
+ -- response transmitter
+ res_start => res_start,
+ res_done => res_done,
+ res_ind => res_ind,
+ res_arg => res_arg,
+
+ -- function0 - register-interface
+ fn0_rena => bus_rena,
+ fn0_wena => bus_wena,
+ fn0_addr => bus_addr,
+ fn0_oor => bus_oor,
+ fn0_rdat => bus_rdat,
+ fn0_wdat => bus_wdat,
+
+ -- function1 - control
+ fn1_start => fn1_start,
+ fn1_count => fn1_count
+ );
+
+ -- data transmitter
+ dtx: entity sdio_dat_tx
+ port map (
+ -- common
+ clk => clk,
+ reset => reset,
+
+ -- control
+ start => fn1_start,
+ abort => fn1_abort,
+ bcount => fn1_count,
+ bsize => fn1_bsize,
+
+ -- status
+ active => dtx_active,
+
+ -- input data
+ in_ready => tx_ready,
+ in_sync => tx_sync,
+ in_clk => tx_clk,
+ in_dat => tx_dat,
+
+ -- SDIO interface
+ sd_clk => sd_clk,
+ sd_dat_oe => sd_dat_oe,
+ sd_dat_o => sd_dat_o
+ );
+
+ -- TX data control/fifo
+ txctl: entity sdio_txctrl
+ port map (
+ -- clocks
+ clk_sys => clk,
+ rst_sys => reset,
+ sd_clk => sd_clk,
+
+ -- config
+ cfg_bsize => fn1_bsize,
+
+ -- input
+ in_clk => in_clk,
+ in_data => in_data,
+
+ -- output
+ out_ready => tx_ready,
+ out_sync => tx_sync,
+ out_clk => tx_clk,
+ out_dat => tx_dat
+ );
+
+end rtl; \ No newline at end of file
diff --git a/fpga/hw-v2-mci/src/sdio/sdio_txctrl.vhd b/fpga/hw-v2-mci/src/sdio/sdio_txctrl.vhd
new file mode 100644
index 0000000..7da0df7
--- /dev/null
+++ b/fpga/hw-v2-mci/src/sdio/sdio_txctrl.vhd
@@ -0,0 +1,119 @@
+
+-----------------------------------------------------------------------------------
+-- Copyright (C) 2013 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.mt_toolbox.all;
+ use work.all;
+
+entity sdio_txctrl is
+ port(
+ -- clocks
+ clk_sys : in std_logic;
+ rst_sys : in std_logic;
+ sd_clk : in std_logic;
+
+ -- config
+ cfg_bsize : in unsigned(15 downto 0);
+
+ -- input
+ in_clk : in std_logic;
+ in_data : in std_logic_vector(31 downto 0);
+
+ -- output
+ out_ready : out std_logic;
+ out_sync : in std_logic;
+ out_clk : in std_logic;
+ out_dat : out std_logic_vector(7 downto 0)
+ );
+end sdio_txctrl;
+
+architecture rtl of sdio_txctrl is
+
+
+ -- FIFO output
+ signal fifo_fill : unsigned(10 downto 0);
+ signal fifo_oclk : std_logic;
+ signal fifo_odata : std_logic_vector(31 downto 0);
+
+ -- output control
+ signal ophase : unsigned(1 downto 0);
+ signal obuf : std_logic_vector(23 downto 0);
+
+begin
+
+ -- control logic
+ process(sd_clk,rst_sys)
+ begin
+ if rst_sys='1' then
+ fifo_oclk <= '0';
+ out_ready <= '0';
+ out_dat <= (others=>'0');
+ ophase <= (others=>'0');
+ obuf <= (others=>'0');
+ elsif rising_edge(sd_clk) then
+ -- set default values
+ fifo_oclk <= '0';
+
+ -- create output-redy-flag
+ if fifo_fill >= (cfg_bsize/4)
+ then out_ready <= '1';
+ else out_ready <= '0';
+ end if;
+
+ -- handle output-request
+ if out_clk='1' then
+ if out_sync='1' or ophase=0 then
+ out_dat <= fifo_odata( 7 downto 0);
+ obuf <= fifo_odata(31 downto 8);
+ ophase <= "11";
+ fifo_oclk <= '1';
+ else
+ out_dat <= obuf( 7 downto 0);
+ obuf <= x"00" & obuf(23 downto 8);
+ ophase <= ophase-1;
+ end if;
+ end if;
+ end if;
+ end process;
+
+ -- big data fifo
+ fifo: entity sdio_txfifo
+ port map (
+ -- system clock
+ clk_sys => clk_sys,
+ rst_sys => rst_sys,
+
+ -- SDC-clock
+ clk_sdc => sd_clk,
+ rst_sdc => rst_sys,
+
+ -- input
+ in_clk => in_clk,
+ in_data => in_data,
+
+ -- output ('clk_sdc')
+ out_fill => fifo_fill,
+ out_clk => fifo_oclk,
+ out_data => fifo_odata
+ );
+
+end rtl;
diff --git a/fpga/hw-v2-mci/src/sdio/sdio_txfifo.vhd b/fpga/hw-v2-mci/src/sdio/sdio_txfifo.vhd
new file mode 100644
index 0000000..c1ec72c
--- /dev/null
+++ b/fpga/hw-v2-mci/src/sdio/sdio_txfifo.vhd
@@ -0,0 +1,135 @@
+
+-----------------------------------------------------------------------------------
+-- Copyright (C) 2013 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.mt_toolbox.all;
+ use work.all;
+
+entity sdio_txfifo is
+ port(
+ -- system clock
+ clk_sys : in std_logic;
+ rst_sys : in std_logic;
+
+ -- SDC-clock
+ clk_sdc : in std_logic;
+ rst_sdc : in std_logic;
+
+ -- input ('clk_sys')
+ in_clk : in std_logic;
+ in_data : in slv32_t;
+
+ -- output ('clk_sdc')
+ out_fill : out unsigned(10 downto 0);
+ out_clk : in std_logic;
+ out_data : out slv32_t
+ );
+end sdio_txfifo;
+
+architecture rtl of sdio_txfifo is
+
+ -- fifo pointers
+ signal wptr : unsigned(10 downto 0) := (others=>'0');
+ signal wptr_s1 : unsigned(10 downto 0) := (others=>'0');
+ signal wptr_s2 : unsigned(10 downto 0) := (others=>'0');
+ signal rptr : unsigned(10 downto 0) := (others=>'0');
+ signal rptr_s1 : unsigned(10 downto 0) := (others=>'0');
+ signal rptr_s2 : unsigned(10 downto 0) := (others=>'0');
+
+ -- create fifo
+ type memory_t is array (0 to 2047) of slv32_t;
+ signal mem : memory_t;
+
+begin
+
+ -- input control
+ process(clk_sys, rst_sys)
+ variable fill : unsigned(10 downto 0);
+ begin
+ if rst_sys='1' then
+ rptr_s1 <= (others=>'0');
+ rptr_s2 <= (others=>'0');
+ wptr <= (others=>'0');
+ elsif rising_edge(clk_sys) then
+ -- synchronize read-pointer
+ rptr_s1 <= rptr;
+ rptr_s2 <= rptr_s1;
+
+ -- get current fill-count
+ fill := gray2bin(wptr) - gray2bin(rptr_s2);
+
+ -- wait for incoming data
+ if in_clk='1' then
+ -- store entry in info
+ mem(to_integer(wptr)) <= in_data;
+
+ -- update write-pointer
+ if fill/=2047 then
+ --> increment pointer
+ wptr <= bin2gray(gray2bin(wptr)+1);
+ else
+ --> overflow
+ report "sdio_txfifo: fifo overflow"
+ severity error;
+ end if;
+ end if;
+ end if;
+ end process;
+
+ -- output control
+ process(clk_sdc, rst_sdc)
+ variable fill : unsigned(10 downto 0);
+ begin
+ if rst_sdc='1' then
+ wptr_s1 <= (others=>'0');
+ wptr_s2 <= (others=>'0');
+ rptr <= (others=>'0');
+ out_fill <= (others=>'0');
+-- out_data <= (others=>'0');
+ elsif rising_edge(clk_sdc) then
+ -- synchronize write-pointer
+ wptr_s1 <= wptr;
+ wptr_s2 <= wptr_s1;
+
+ -- get current fill-count
+ fill := gray2bin(wptr_s2) - gray2bin(rptr);
+ out_fill <= fill;
+
+ -- read entry from info
+ out_data <= mem(to_integer(rptr));
+
+ -- update read-pointer
+ if out_clk='1' then
+ if fill/=0 then
+ --> increment pointer
+ rptr <= bin2gray(gray2bin(rptr)+1);
+ else
+ --> overflow
+ report "sdio_txfifo: fifo underflow"
+ severity error;
+ end if;
+ end if;
+ end if;
+ end process;
+
+
+end rtl;
diff --git a/fpga/hw-v2-mci/src/testbench/tb_filter.vhd b/fpga/hw-v2-mci/src/testbench/tb_filter.vhd
new file mode 100644
index 0000000..275c429
--- /dev/null
+++ b/fpga/hw-v2-mci/src/testbench/tb_filter.vhd
@@ -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;
+
+
diff --git a/fpga/hw-v2-mci/src/testbench/tb_sdio.vhd b/fpga/hw-v2-mci/src/testbench/tb_sdio.vhd
new file mode 100644
index 0000000..f8287ee
--- /dev/null
+++ b/fpga/hw-v2-mci/src/testbench/tb_sdio.vhd
@@ -0,0 +1,409 @@
+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;
+
+entity tb_sdio is
+end tb_sdio;
+
+architecture rtl of tb_sdio is
+
+ --
+ -- signals
+ --
+
+ -- system clock
+ signal clk_sys : std_logic := '1';
+ signal rst_sys : std_logic := '1';
+
+ -- SDIO lines
+ signal sd_clk : std_logic := '1';
+ signal sd_cmd : std_logic;
+ signal sd_dat : std_logic_vector(3 downto 0);
+
+ -- input samples
+ signal smp_clk : std_logic;
+ signal smp_raw : std_logic_vector(31 downto 0);
+ signal smp_i : signed(15 downto 0);
+ signal smp_q : signed(15 downto 0);
+
+ --
+ -- procedures
+ --
+
+ -- CRC7
+ procedure crc7_update(
+ crc: inout std_logic_vector(6 downto 0);
+ dat: in std_logic) is
+ begin
+ if dat /= crc(6)
+ then crc := (crc(5 downto 0) & "0") xor "0001001";
+ else crc := (crc(5 downto 0) & "0");
+ end if;
+ end procedure;
+ procedure crc7_update(
+ crc: inout std_logic_vector(6 downto 0);
+ dat: in std_logic_vector) is
+ begin
+ for i in dat'range loop
+ crc7_update(crc,dat(i));
+ end loop;
+ end procedure;
+ procedure crc7_compute(
+ crc: out std_logic_vector(6 downto 0);
+ dat: in std_logic_vector)
+ is
+ variable tmp : std_logic_vector(6 downto 0) := (others=>'0');
+ begin
+ crc7_update(tmp,dat);
+ crc := tmp;
+ end procedure;
+
+ -- CRC16
+ procedure crc16_update(
+ crc: inout std_logic_vector(15 downto 0);
+ dat: in std_logic) is
+ begin
+ if dat /= crc(15)
+ then crc := (crc(14 downto 0) & "0") xor x"1021";
+ else crc := (crc(14 downto 0) & "0");
+ end if;
+ end procedure;
+ procedure crc16_update(
+ crc: inout std_logic_vector(15 downto 0);
+ dat: in std_logic_vector) is
+ begin
+ for i in dat'range loop
+ crc16_update(crc,dat(i));
+ end loop;
+ end procedure;
+
+begin
+
+ -- generate system-clock
+ clk_sys <= not clk_sys after 500ns / 80.0;
+ rst_sys <= '1', '0' after 100ns;
+
+ -- generate SD-clock
+ sd_clk <= not sd_clk after 500ns / 25.0;
+
+ -- pull-ups
+ sd_cmd <= 'H';
+ sd_dat <= "HHHH";
+
+ -- test #1
+ process
+
+ --
+ -- low-level helper
+ --
+
+ -- send command
+ procedure send_command (
+ cmd : natural;
+ arg : std_logic_vector(31 downto 0)
+ ) is
+ variable msg : std_logic_vector(47 downto 0);
+ begin
+ -- compose message
+ msg(47) := '0';
+ msg(46) := '1';
+ msg(45 downto 40) := std_logic_vector(to_unsigned(cmd,6));
+ msg(39 downto 8) := arg;
+ crc7_compute(msg(7 downto 1),msg(47 downto 8));
+ msg(0) := '1';
+
+ -- transmit message
+ for i in 47 downto 0 loop
+ wait until falling_edge(sd_clk);
+ sd_cmd <= msg(i);
+ end loop;
+
+ -- release bus
+ wait until falling_edge(sd_clk);
+ sd_cmd <= 'Z';
+ end procedure;
+
+ -- receive response
+ procedure receive_response (
+ cmd : out natural;
+ arg : out std_logic_vector(31 downto 0);
+ err : out std_logic
+ ) is
+ variable msg : std_logic_vector(46 downto 0);
+ variable crc1 : std_logic_vector(6 downto 0);
+ variable crc2 : std_logic_vector(6 downto 0);
+ begin
+ -- wait for start-bit
+ wait until rising_edge(sd_clk) and sd_cmd='0';
+
+ -- receive message
+ for i in 46 downto 0 loop
+ wait until rising_edge(sd_clk);
+ msg(i) := sd_cmd;
+ end loop;
+
+ -- decode message
+ cmd := to_integer(unsigned(msg(45 downto 40)));
+ arg := msg(39 downto 8);
+ crc1 := msg(7 downto 1);
+
+ -- verify CRC
+ crc7_compute(crc2,msg(46 downto 8));
+ if crc1=crc2
+ then err := '0';
+ else err := '1';
+ end if;
+ end procedure;
+
+ --
+ -- mid-level helper
+ --
+
+ -- send command #52
+ procedure send_cmd52 (
+ rw : std_logic;
+ fun : natural;
+ raw : std_logic;
+ adr : natural;
+ dat : std_logic_vector(7 downto 0)
+ ) is
+ variable arg : std_logic_vector(31 downto 0);
+ begin
+ -- compose argument
+ arg(31) := rw;
+ arg(30 downto 28) := std_logic_vector(to_unsigned(fun,3));
+ arg(27) := raw;
+ arg(26) := '1';
+ arg(25 downto 9) := std_logic_vector(to_unsigned(adr,17));
+ arg(8) := '1';
+ arg(7 downto 0) := dat;
+
+ -- send command
+ send_command(52,arg);
+ end procedure;
+
+ -- send command #53
+ procedure send_cmd53 (
+ rw : std_logic;
+ fun : natural;
+ blk : std_logic;
+ opc : std_logic;
+ adr : natural;
+ cnt : natural
+ ) is
+ variable arg : std_logic_vector(31 downto 0);
+ begin
+ -- compose argument
+ arg(31) := rw;
+ arg(30 downto 28) := std_logic_vector(to_unsigned(fun,3));
+ arg(27) := blk;
+ arg(26) := opc;
+ arg(25 downto 9) := std_logic_vector(to_unsigned(adr,17));
+ arg(8 downto 0) := std_logic_vector(to_unsigned(cnt,9));
+
+ -- send command
+ send_command(53,arg);
+ end procedure;
+
+
+ --
+ -- high-level helper
+ --
+
+ -- write single register
+ procedure write_reg (
+ adr : in natural;
+ idat : in std_logic_vector(7 downto 0);
+ odat : out std_logic_vector(7 downto 0);
+ stat : out std_logic_vector(7 downto 0);
+ err : out std_logic
+ ) is
+ variable res_cmd : natural;
+ variable res_arg : std_logic_vector(31 downto 0);
+ variable res_err : std_logic;
+ begin
+ -- send command
+ send_cmd52('1',0,'0',adr,idat);
+
+ -- get response
+ receive_response(res_cmd,res_arg,res_err);
+ if res_err='1' or res_cmd/=52 then
+ err := '1';
+ odat := x"00";
+ stat := x"00";
+ else
+ err := '0';
+ stat := res_arg(15 downto 8);
+ odat := res_arg( 7 downto 0);
+ end if;
+ end procedure;
+
+ -- read single register
+ procedure read_reg (
+ adr : in natural;
+ odat : out std_logic_vector(7 downto 0);
+ stat : out std_logic_vector(7 downto 0);
+ err : out std_logic
+ ) is
+ variable res_cmd : natural;
+ variable res_arg : std_logic_vector(31 downto 0);
+ variable res_err : std_logic;
+ begin
+ -- send command
+ send_cmd52('0',0,'0',adr,x"00");
+
+ -- get response
+ receive_response(res_cmd,res_arg,res_err);
+ if res_err='1' or res_cmd/=52 then
+ err := '1';
+ odat := x"00";
+ stat := x"00";
+ else
+ err := '0';
+ stat := res_arg(15 downto 8);
+ odat := res_arg( 7 downto 0);
+ end if;
+ end procedure;
+
+ -- helper vars
+ variable my_odat : std_logic_vector(7 downto 0);
+ variable my_stat : std_logic_vector(7 downto 0);
+ variable my_err : std_logic;
+
+ begin
+
+ -- init signals
+ sd_cmd <= 'Z';
+ sd_dat <= "ZZZZ";
+ wait for 200ns;
+
+ -- request data-stream
+ send_cmd53('0',1,'1','0',1234,0);
+
+ -- wait some time
+ wait for 2960us;
+
+ -- abort data-stream
+ write_reg(6,x"01",my_odat,my_stat,my_err);
+
+
+ -- TODO
+-- read_reg(1,my_odat,my_stat,my_err);
+
+ wait;
+ end process;
+
+ -- test #2
+ process
+ variable msg : slv8_array_t(0 to 511);
+ variable crc_rx : slv16_array_t(0 to 3);
+ variable crc_ref : slv16_array_t(0 to 3);
+ variable blk_ok : std_logic := '0';
+ variable blk_err : std_logic := '0';
+ begin
+ loop
+ -- wait for start-bit
+ wait until rising_edge(sd_clk) and sd_dat(0)='0';
+
+ -- reset CRCs
+ crc_ref := (others=>x"0000");
+
+ -- receive message
+ for i in 0 to 511 loop
+ wait until rising_edge(sd_clk);
+ msg(i)(7 downto 4) := sd_dat;
+ crc16_update(crc_ref(0), sd_dat(0));
+ crc16_update(crc_ref(1), sd_dat(1));
+ crc16_update(crc_ref(2), sd_dat(2));
+ crc16_update(crc_ref(3), sd_dat(3));
+
+ wait until rising_edge(sd_clk);
+ msg(i)(3 downto 0) := sd_dat;
+ crc16_update(crc_ref(0), sd_dat(0));
+ crc16_update(crc_ref(1), sd_dat(1));
+ crc16_update(crc_ref(2), sd_dat(2));
+ crc16_update(crc_ref(3), sd_dat(3));
+ end loop;
+
+ -- receive CRCs
+ for i in 15 downto 0 loop
+ wait until rising_edge(sd_clk);
+ crc_rx(0)(i) := sd_dat(0);
+ crc_rx(1)(i) := sd_dat(1);
+ crc_rx(2)(i) := sd_dat(2);
+ crc_rx(3)(i) := sd_dat(3);
+ end loop;
+
+ -- check CRCs
+ if crc_rx=crc_ref
+ then blk_ok := '1';
+ else blk_err := '1';
+ end if;
+ wait until rising_edge(sd_clk);
+ blk_ok := '0';
+ blk_err := '0';
+ end loop;
+ wait;
+ end process;
+
+ -- input control
+ process
+ variable counter1 : signed(15 downto 0) := (others=>'0');
+ variable counter2 : signed(15 downto 0) := (others=>'0');
+ begin
+ smp_clk <= '0';
+ smp_i <= to_signed(0,16);
+ smp_q <= to_signed(0,16);
+ wait until rising_edge(clk_sys) and rst_sys='0';
+
+ loop
+ -- wait some time
+ for i in 0 to 78 loop
+ wait until rising_edge(clk_sys);
+ end loop;
+
+ -- update counter
+ counter1 := counter1 + 1;
+ counter2 := counter2 - 1;
+
+ -- get sample data
+ smp_i <= counter1;
+ smp_q <= counter2;
+
+ -- input sample
+ smp_clk <= '1';
+ wait until rising_edge(clk_sys);
+ smp_clk <= '0';
+ end loop;
+
+ wait;
+ end process;
+
+ -- pack input into 32 bit raw value
+ smp_raw <= std_logic_vector(smp_q & smp_i);
+
+ -- unit under test #1
+ uut1: entity sdio_top
+ port map (
+ -- common
+ clk => clk_sys,
+ reset => rst_sys,
+
+ -- data input
+ in_clk => smp_clk,
+ in_data => smp_raw,
+
+ -- SDIO interface
+ sd_clk => sd_clk,
+ sd_cmd => sd_cmd,
+ sd_dat => sd_dat
+ );
+
+end rtl;
+
+
diff --git a/fpga/hw-v2-mci/src/testbench/tb_sdio_stim.vhd b/fpga/hw-v2-mci/src/testbench/tb_sdio_stim.vhd
new file mode 100644
index 0000000..03451ba
--- /dev/null
+++ b/fpga/hw-v2-mci/src/testbench/tb_sdio_stim.vhd
@@ -0,0 +1,362 @@
+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;
+
+entity tb_sdio_stim is
+ port (
+ sd_clk : inout std_logic;
+ sd_cmd : inout std_logic;
+ sd_dat : inout std_logic_vector(3 downto 0)
+ );
+end tb_sdio_stim;
+
+architecture rtl of tb_sdio_stim is
+
+ --
+ -- signals
+ --
+
+ -- SDIO lines
+ signal ref_clk : std_logic := '1';
+
+ --
+ -- procedures
+ --
+
+ -- CRC7
+ procedure crc7_update(
+ crc: inout std_logic_vector(6 downto 0);
+ dat: in std_logic) is
+ begin
+ if dat /= crc(6)
+ then crc := (crc(5 downto 0) & "0") xor "0001001";
+ else crc := (crc(5 downto 0) & "0");
+ end if;
+ end procedure;
+ procedure crc7_update(
+ crc: inout std_logic_vector(6 downto 0);
+ dat: in std_logic_vector) is
+ begin
+ for i in dat'range loop
+ crc7_update(crc,dat(i));
+ end loop;
+ end procedure;
+ procedure crc7_compute(
+ crc: out std_logic_vector(6 downto 0);
+ dat: in std_logic_vector)
+ is
+ variable tmp : std_logic_vector(6 downto 0) := (others=>'0');
+ begin
+ crc7_update(tmp,dat);
+ crc := tmp;
+ end procedure;
+
+ -- CRC16
+ procedure crc16_update(
+ crc: inout std_logic_vector(15 downto 0);
+ dat: in std_logic) is
+ begin
+ if dat /= crc(15)
+ then crc := (crc(14 downto 0) & "0") xor x"1021";
+ else crc := (crc(14 downto 0) & "0");
+ end if;
+ end procedure;
+ procedure crc16_update(
+ crc: inout std_logic_vector(15 downto 0);
+ dat: in std_logic_vector) is
+ begin
+ for i in dat'range loop
+ crc16_update(crc,dat(i));
+ end loop;
+ end procedure;
+
+begin
+
+ -- generate SD-clock
+ ref_clk <= not ref_clk after 500ns / 25.0;
+ sd_clk <= ref_clk;
+
+ -- pull-ups
+ sd_cmd <= 'H';
+ sd_dat <= "HHHH";
+
+ -- test #1
+ process
+
+ --
+ -- low-level helper
+ --
+
+ -- send command
+ procedure send_command (
+ cmd : natural;
+ arg : std_logic_vector(31 downto 0)
+ ) is
+ variable msg : std_logic_vector(47 downto 0);
+ begin
+ -- compose message
+ msg(47) := '0';
+ msg(46) := '1';
+ msg(45 downto 40) := std_logic_vector(to_unsigned(cmd,6));
+ msg(39 downto 8) := arg;
+ crc7_compute(msg(7 downto 1),msg(47 downto 8));
+ msg(0) := '1';
+
+ -- transmit message
+ for i in 47 downto 0 loop
+ wait until falling_edge(ref_clk);
+ sd_cmd <= msg(i);
+ end loop;
+
+ -- release bus
+ wait until falling_edge(ref_clk);
+ sd_cmd <= 'Z';
+ end procedure;
+
+ -- receive response
+ procedure receive_response (
+ cmd : out natural;
+ arg : out std_logic_vector(31 downto 0);
+ err : out std_logic
+ ) is
+ variable msg : std_logic_vector(46 downto 0);
+ variable crc1 : std_logic_vector(6 downto 0);
+ variable crc2 : std_logic_vector(6 downto 0);
+ begin
+ -- wait for start-bit
+ wait until rising_edge(ref_clk) and sd_cmd='0';
+
+ -- receive message
+ for i in 46 downto 0 loop
+ wait until rising_edge(ref_clk);
+ msg(i) := sd_cmd;
+ end loop;
+
+ -- decode message
+ cmd := to_integer(unsigned(msg(45 downto 40)));
+ arg := msg(39 downto 8);
+ crc1 := msg(7 downto 1);
+
+ -- verify CRC
+ crc7_compute(crc2,msg(46 downto 8));
+ if crc1=crc2
+ then err := '0';
+ else err := '1';
+ end if;
+ end procedure;
+
+ --
+ -- mid-level helper
+ --
+
+ -- send command #52
+ procedure send_cmd52 (
+ rw : std_logic;
+ fun : natural;
+ raw : std_logic;
+ adr : natural;
+ dat : std_logic_vector(7 downto 0)
+ ) is
+ variable arg : std_logic_vector(31 downto 0);
+ begin
+ -- compose argument
+ arg(31) := rw;
+ arg(30 downto 28) := std_logic_vector(to_unsigned(fun,3));
+ arg(27) := raw;
+ arg(26) := '1';
+ arg(25 downto 9) := std_logic_vector(to_unsigned(adr,17));
+ arg(8) := '1';
+ arg(7 downto 0) := dat;
+
+ -- send command
+ send_command(52,arg);
+ end procedure;
+
+ -- send command #53
+ procedure send_cmd53 (
+ rw : std_logic;
+ fun : natural;
+ blk : std_logic;
+ opc : std_logic;
+ adr : natural;
+ cnt : natural
+ ) is
+ variable arg : std_logic_vector(31 downto 0);
+ begin
+ -- compose argument
+ arg(31) := rw;
+ arg(30 downto 28) := std_logic_vector(to_unsigned(fun,3));
+ arg(27) := blk;
+ arg(26) := opc;
+ arg(25 downto 9) := std_logic_vector(to_unsigned(adr,17));
+ arg(8 downto 0) := std_logic_vector(to_unsigned(cnt,9));
+
+ -- send command
+ send_command(53,arg);
+ end procedure;
+
+
+ --
+ -- high-level helper
+ --
+
+ -- write single register
+ procedure write_reg (
+ adr : in natural;
+ idat : in std_logic_vector(7 downto 0);
+ odat : out std_logic_vector(7 downto 0);
+ stat : out std_logic_vector(7 downto 0);
+ err : out std_logic
+ ) is
+ variable res_cmd : natural;
+ variable res_arg : std_logic_vector(31 downto 0);
+ variable res_err : std_logic;
+ begin
+ -- send command
+ send_cmd52('1',0,'0',adr,idat);
+
+ -- get response
+ receive_response(res_cmd,res_arg,res_err);
+ if res_err='1' or res_cmd/=52 then
+ err := '1';
+ odat := x"00";
+ stat := x"00";
+ else
+ err := '0';
+ stat := res_arg(15 downto 8);
+ odat := res_arg( 7 downto 0);
+ end if;
+ end procedure;
+
+ -- read single register
+ procedure read_reg (
+ adr : in natural;
+ odat : out std_logic_vector(7 downto 0);
+ stat : out std_logic_vector(7 downto 0);
+ err : out std_logic
+ ) is
+ variable res_cmd : natural;
+ variable res_arg : std_logic_vector(31 downto 0);
+ variable res_err : std_logic;
+ begin
+ -- send command
+ send_cmd52('0',0,'0',adr,x"00");
+
+ -- get response
+ receive_response(res_cmd,res_arg,res_err);
+ if res_err='1' or res_cmd/=52 then
+ err := '1';
+ odat := x"00";
+ stat := x"00";
+ else
+ err := '0';
+ stat := res_arg(15 downto 8);
+ odat := res_arg( 7 downto 0);
+ end if;
+ end procedure;
+
+ -- helper vars
+ variable my_odat : std_logic_vector(7 downto 0);
+ variable my_stat : std_logic_vector(7 downto 0);
+ variable my_err : std_logic;
+
+ begin
+
+ -- init signals
+ sd_cmd <= 'Z';
+ sd_dat <= "ZZZZ";
+ wait for 2000ns;
+
+
+ -- xxx
+-- wait for 5ms;
+
+ read_reg(0,my_odat,my_stat,my_err);
+
+ -- request data-stream
+ send_cmd53('0',1,'1','0',1234,0);
+
+ -- wait some time
+ wait for 2960us;
+
+ -- abort data-stream
+ write_reg(6,x"01",my_odat,my_stat,my_err);
+
+ wait;
+ end process;
+
+ -- test #2
+ process
+ variable msg : slv8_array_t(0 to 511);
+ variable crc_rx : slv16_array_t(0 to 3);
+ variable crc_ref : slv16_array_t(0 to 3);
+ variable blk_ok : std_logic := '0';
+ variable blk_err : std_logic := '0';
+
+ type smp_array_t is array(natural range<>) of signed(15 downto 0);
+ variable smp_i : smp_array_t(0 to 127);
+ variable smp_q : smp_array_t(0 to 127);
+
+ begin
+ loop
+ -- wait for start-bit
+ wait until rising_edge(ref_clk) and sd_dat(0)='0';
+
+ -- reset CRCs
+ crc_ref := (others=>x"0000");
+
+ -- receive message
+ for i in 0 to 511 loop
+ wait until rising_edge(ref_clk);
+ msg(i)(7 downto 4) := sd_dat;
+ crc16_update(crc_ref(0), sd_dat(0));
+ crc16_update(crc_ref(1), sd_dat(1));
+ crc16_update(crc_ref(2), sd_dat(2));
+ crc16_update(crc_ref(3), sd_dat(3));
+
+ wait until rising_edge(ref_clk);
+ msg(i)(3 downto 0) := sd_dat;
+ crc16_update(crc_ref(0), sd_dat(0));
+ crc16_update(crc_ref(1), sd_dat(1));
+ crc16_update(crc_ref(2), sd_dat(2));
+ crc16_update(crc_ref(3), sd_dat(3));
+ end loop;
+
+ -- receive CRCs
+ for i in 15 downto 0 loop
+ wait until rising_edge(ref_clk);
+ crc_rx(0)(i) := sd_dat(0);
+ crc_rx(1)(i) := sd_dat(1);
+ crc_rx(2)(i) := sd_dat(2);
+ crc_rx(3)(i) := sd_dat(3);
+ end loop;
+
+ -- check CRCs
+ if crc_rx=crc_ref
+ then blk_ok := '1';
+ else blk_err := '1';
+ end if;
+ wait until rising_edge(ref_clk);
+ blk_ok := '0';
+ blk_err := '0';
+
+ -- 'decode' message
+ for i in 0 to 127 loop
+ smp_i(i)( 7 downto 0) := signed(msg(4*i+0));
+ smp_i(i)(15 downto 8) := signed(msg(4*i+1));
+ smp_q(i)( 7 downto 0) := signed(msg(4*i+2));
+ smp_q(i)(15 downto 8) := signed(msg(4*i+3));
+ end loop;
+
+ end loop;
+ wait;
+ end process;
+
+end rtl;
+
+
diff --git a/fpga/hw-v2-mci/src/testbench/tb_usbrx.vhd b/fpga/hw-v2-mci/src/testbench/tb_usbrx.vhd
new file mode 100644
index 0000000..3da128c
--- /dev/null
+++ b/fpga/hw-v2-mci/src/testbench/tb_usbrx.vhd
@@ -0,0 +1,399 @@
+---------------------------------------------------------------------------------------------------
+-- 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);
+
+ -- SDIO
+ signal sd_clk : std_logic;
+ signal sd_cmd : std_logic;
+ signal sd_dat : std_logic_vector(3 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');
+
+ -- generate pps signal
+ -- (set every millisecond instead of every second
+ -- to speed to simulation time)
+ process
+ variable cnt : natural;
+ begin
+ gps_1pps <= '0';
+
+ cnt := 1;
+ loop
+ wait for (cnt * 1 ms) - now;
+ gps_1pps <= '1';
+ wait for 1us;
+ gps_1pps <= '0';
+ cnt := cnt+1;
+ end loop;
+
+ wait;
+ end process;
+
+ -- dummy ADC model
+ process
+-- constant word1 : unsigned(15 downto 0) := "0010000000000001";
+-- 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);
+ word2 := to_unsigned(0, 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 5.0ns;
+ adc_sd2 <= transport 'X', sreg2(15) after 5.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;
+
+ -- SDIO stimulus
+ stim: entity tb_sdio_stim
+ port map (
+ sd_clk => sd_clk,
+ sd_cmd => sd_cmd,
+ sd_dat => sd_dat
+ );
+
+ -- 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(0) => gpio(0),
+ gpio(1) => gpio(1),
+ gpio(2) => gpio(2),
+ gpio(3) => gpio(3),
+ gpio(4) => sd_clk,
+ gpio(5) => sd_cmd,
+ gpio(6) => sd_dat(0),
+ gpio(7) => sd_dat(1),
+ gpio(8) => sd_dat(2),
+ gpio(9) => sd_dat(3),
+
+ -- virtual GNDs/VCCs
+ vgnd => vgnd,
+ vcc33 => vcc33,
+ vcc12 => vcc12
+ );
+
+end rtl;
+
+
diff --git a/fpga/hw-v2-mci/src/usbrx/datapath/usbrx_ad7357.vhd b/fpga/hw-v2-mci/src/usbrx/datapath/usbrx_ad7357.vhd
new file mode 100644
index 0000000..2090934
--- /dev/null
+++ b/fpga/hw-v2-mci/src/usbrx/datapath/usbrx_ad7357.vhd
@@ -0,0 +1,312 @@
+---------------------------------------------------------------------------------------------------
+-- 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)
+ );
+
+ attribute syn_useioff : boolean;
+ attribute syn_useioff of adc_cs : signal is true;
+ attribute syn_useioff of adc_sck : signal is true;
+
+ attribute syn_preserve : boolean;
+ attribute syn_preserve of adc_cs : signal is true;
+ attribute syn_preserve of adc_sck : signal is true;
+
+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);
+ adc_cs <= 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';
+ adc_cs <= '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';
+ adc_cs <= '1';
+ end if;
+ end if;
+ end case;
+
+ -- handle reset
+ if reset='1' then
+ state <= S_ACQUISITION; -- TODO
+ counter <= (others=>'0');
+ css <= (others=>'1');
+-- adc_cs <= '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;
diff --git a/fpga/hw-v2-mci/src/usbrx/datapath/usbrx_decimate.vhd b/fpga/hw-v2-mci/src/usbrx/datapath/usbrx_decimate.vhd
new file mode 100644
index 0000000..d7e54a7
--- /dev/null
+++ b/fpga/hw-v2-mci/src/usbrx/datapath/usbrx_decimate.vhd
@@ -0,0 +1,213 @@
+---------------------------------------------------------------------------------------------------
+-- 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(4 downto 0);
+
+ -- adapted input
+ signal in_si : fir_dataword18;
+ signal in_sq : fir_dataword18;
+
+ -- filter input
+ signal fil_in_clk : std_logic_vector(4 downto 0);
+ signal fil_in_i : fir_databus18(4 downto 0);
+ signal fil_in_q : fir_databus18(4 downto 0);
+
+ -- filter output
+ signal fil_out_clk : std_logic_vector(4 downto 0);
+ signal fil_out_i : fir_databus18(4 downto 0);
+ signal fil_out_q : fir_databus18(4 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 <= "00000";
+ when 1 => active <= "00001";
+ when 2 => active <= "00011";
+ when 3 => active <= "00111";
+ when 4 => active <= "01111";
+ when others => active <= "11111";
+ 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 others =>
+ nxt_clk <= fil_out_clk(4);
+ nxt_i <= fil_out_i(4);
+ nxt_q <= fil_out_q(4);
+ 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 4 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 => 4
+ )
+ port map (
+ -- common
+ clk => clk,
+ reset => reset,
+
+ -- input
+ in_clk => fil_in_clk(4 downto 1),
+ in_i => fil_in_i(4 downto 1),
+ in_q => fil_in_q(4 downto 1),
+
+ -- output
+ out_clk => fil_out_clk(4 downto 1),
+ out_i => fil_out_i(4 downto 1),
+ out_q => fil_out_q(4 downto 1)
+ );
+
+end rtl;
diff --git a/fpga/hw-v2-mci/src/usbrx/datapath/usbrx_offset.vhd b/fpga/hw-v2-mci/src/usbrx/datapath/usbrx_offset.vhd
new file mode 100644
index 0000000..42ba8fc
--- /dev/null
+++ b/fpga/hw-v2-mci/src/usbrx/datapath/usbrx_offset.vhd
@@ -0,0 +1,126 @@
+---------------------------------------------------------------------------------------------------
+-- 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
+ variable xnorm : signed(x'length-1 downto 0) := x;
+ begin
+ if xnorm >= 32768 then
+ -- overflow
+ return to_signed(+32767,16);
+ elsif xnorm < -32768 then
+ -- underflow
+ return to_signed(-32768,16);
+ else
+ -- in range
+ return xnorm(15 downto 0);
+ end if;
+ end doClipValue;
+
+ -- multiplier input
+ signal mula_i, mula_q : signed(17 downto 0) := (others=>'0');
+ signal mulb_i, mulb_q : signed(17 downto 0) := (others=>'0');
+
+ -- multiplier output
+ signal mout_i, mout_q : signed(18 downto 0) := (others=>'0');
+
+begin
+
+ -- control logic
+ process(clk)
+ variable mtmp_i, mtmp_q : signed(35 downto 0);
+ variable atmp_i, atmp_q : signed(19 downto 0);
+ begin
+ if rising_edge(clk) then
+ -- passthough clock
+ out_clk <= in_clk;
+
+ -- handle data
+ if in_clk='1' then
+ -- apply swap-flag & convert input into 18bit signed
+ if config.swap='0' then
+ mula_i <= signed(in_i xor "10000000000000") & "0000";
+ mula_q <= signed(in_q xor "10000000000000") & "0000";
+ else
+ mula_i <= signed(in_q xor "10000000000000") & "0000";
+ mula_q <= signed(in_i xor "10000000000000") & "0000";
+ end if;
+
+ -- apply gain
+ mulb_i <= signed("00" & config.igain);
+ mulb_q <= signed("00" & config.qgain);
+ mtmp_i := mula_i * mulb_i;
+ mtmp_q := mula_q * mulb_q;
+ mout_i <= mtmp_i(34 downto 16);
+ mout_q <= mtmp_q(34 downto 16);
+
+ -- add offset (also adds 0.5 for rounding of multiplier-output)
+ atmp_i := resize(mout_i,20) + resize(config.ioff&"1",20);
+ atmp_q := resize(mout_q,20) + resize(config.qoff&"1",20);
+
+ -- clip output
+ out_i <= doClipValue(atmp_i(19 downto 1));
+ out_q <= doClipValue(atmp_q(19 downto 1));
+ 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;
diff --git a/fpga/hw-v2-mci/src/usbrx/datapath/usbrx_sdio.vhd b/fpga/hw-v2-mci/src/usbrx/datapath/usbrx_sdio.vhd
new file mode 100644
index 0000000..b8a775c
--- /dev/null
+++ b/fpga/hw-v2-mci/src/usbrx/datapath/usbrx_sdio.vhd
@@ -0,0 +1,133 @@
+---------------------------------------------------------------------------------------------------
+-- Filename : usbrx_sdio.vhd
+-- Project : OsmoSDR FPGA Firmware
+-- Purpose : ATSAM3U SDIO 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_sdio is
+ port(
+ -- common
+ clk : in std_logic;
+ reset : in std_logic;
+
+ -- config
+ config : in usbrx_ssc_config_t;
+
+ -- input
+ in_clk : in std_logic;
+ in_i : in signed(15 downto 0);
+ in_q : in signed(15 downto 0);
+
+ -- SDIO interface
+ sd_clk : in std_logic;
+ sd_cmd : inout std_logic;
+ sd_dat : inout std_logic_vector(3 downto 0)
+ );
+end usbrx_sdio;
+
+architecture rtl of usbrx_sdio is
+
+ -- 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;
+
+ -- SDIO input
+ signal sdio_clk : std_logic;
+ signal sdio_dat : std_logic_vector(31 downto 0);
+
+ -- debug
+ signal counter1 : unsigned(15 downto 0);
+ signal counter2 : unsigned(15 downto 0);
+
+begin
+
+ -- control logic
+ process(clk)
+ begin
+ if rising_edge(clk) then
+ -- set default values
+ sdio_clk <= '0';
+
+ -- handle incoming samples
+ if in_clk='1' then
+ -- latch sample
+ sdio_dat <= pack(in_i,in_q);
+ sdio_clk <= '1';
+
+ -- apply test-mode
+ if config.tmode='1' then
+ sdio_dat <= pack(counter1,counter2);
+ counter1 <= counter1 + 1;
+ counter2 <= counter2 - 1;
+ end if;
+ end if;
+
+ -- handle reset
+ if reset='1' then
+ sdio_clk <= '0';
+ sdio_dat <= (others=>'0');
+ counter1 <= (others=>'0');
+ counter2 <= (others=>'1');
+ end if;
+ end if;
+ end process;
+
+ -- SDIO controller core
+ sdio: entity sdio_top
+ port map (
+ -- common
+ clk => clk,
+ reset => reset,
+
+ -- input
+ in_clk => sdio_clk,
+ in_data => sdio_dat,
+
+ -- SDIO interface
+ sd_clk => sd_clk,
+ sd_cmd => sd_cmd,
+ sd_dat => sd_dat
+ );
+
+end rtl;
diff --git a/fpga/hw-v2-mci/src/usbrx/datapath/usbrx_ssc.vhd b/fpga/hw-v2-mci/src/usbrx/datapath/usbrx_ssc.vhd
new file mode 100644
index 0000000..6b9e03b
--- /dev/null
+++ b/fpga/hw-v2-mci/src/usbrx/datapath/usbrx_ssc.vhd
@@ -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;
+
+ -- input
+ 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;
diff --git a/fpga/hw-v2-mci/src/usbrx/filter/usbrx_halfband.vhd b/fpga/hw-v2-mci/src/usbrx/filter/usbrx_halfband.vhd
new file mode 100644
index 0000000..ffc6eda
--- /dev/null
+++ b/fpga/hw-v2-mci/src/usbrx/filter/usbrx_halfband.vhd
@@ -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;
diff --git a/fpga/hw-v2-mci/src/usbrx/toplevel/usbrx_clkgen.vhd b/fpga/hw-v2-mci/src/usbrx/toplevel/usbrx_clkgen.vhd
new file mode 100644
index 0000000..b1fc9a8
--- /dev/null
+++ b/fpga/hw-v2-mci/src/usbrx/toplevel/usbrx_clkgen.vhd
@@ -0,0 +1,154 @@
+---------------------------------------------------------------------------------------------------
+-- 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
+ );
+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
+ );
+
+ -- 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;
diff --git a/fpga/hw-v2-mci/src/usbrx/toplevel/usbrx_clkref.vhd b/fpga/hw-v2-mci/src/usbrx/toplevel/usbrx_clkref.vhd
new file mode 100644
index 0000000..0149a07
--- /dev/null
+++ b/fpga/hw-v2-mci/src/usbrx/toplevel/usbrx_clkref.vhd
@@ -0,0 +1,158 @@
+---------------------------------------------------------------------------------------------------
+-- Filename : usbrx_clkref.vhd
+-- Project : OsmoSDR FPGA Firmware
+-- Purpose : Reference Clock Measurement
+---------------------------------------------------------------------------------------------------
+
+-----------------------------------------------------------------------------------
+-- Copyright (C) 2012 maintech GmbH, Otto-Hahn-Str. 15, 97204 Hoechberg, Germany --
+-- written by Matthias Kleffel --
+-- --
+-- This program is free software; you can redistribute it and/or modify --
+-- it under the terms of the GNU General Public License as published by --
+-- the Free Software Foundation as version 3 of the License, or --
+-- --
+-- This program is distributed in the hope that it will be useful, --
+-- but WITHOUT ANY WARRANTY; without even the implied warranty of --
+-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the --
+-- GNU General Public License V3 for more details. --
+-- --
+-- You should have received a copy of the GNU General Public License --
+-- along with this program. If not, see <http://www.gnu.org/licenses/>. --
+-----------------------------------------------------------------------------------
+
+library ieee;
+ use ieee.std_logic_1164.all;
+ use ieee.numeric_std.all;
+library work;
+ use work.all;
+ use work.mt_toolbox.all;
+ use work.usbrx.all;
+
+entity usbrx_clkref is
+ port(
+ -- system clocks
+ clk_sys : in std_logic;
+ rst_sys : in std_logic;
+
+ -- reference signal
+ clk_ref : in std_logic;
+ rst_ref : in std_logic;
+
+ -- 1pps signal
+ gps_1pps : in std_logic;
+
+ -- status
+ status : out usbrx_ref_status_t
+ );
+end usbrx_clkref;
+
+architecture rtl of usbrx_clkref is
+
+ -- deglitcher
+ signal dgl_hist : std_logic_vector(3 downto 0);
+ signal dgl_out : std_logic;
+
+ -- edge detection
+ signal pps_last : std_logic;
+
+ -- active counters
+ signal cnt_lsb : unsigned(24 downto 0);
+
+ -- latched counters
+ signal lat_upd : std_logic;
+ signal lat_lsb : unsigned(24 downto 0);
+ signal lat_msb : unsigned(6 downto 0);
+
+ -- output register
+ signal out_upd : std_logic;
+ signal out_lsb : unsigned(24 downto 0);
+ signal out_msb : unsigned(6 downto 0);
+
+begin
+
+ -- reference counter
+ process(clk_ref)
+ variable cnt0,cnt1 : natural range 0 to 4;
+ variable re : boolean;
+ begin
+ if rising_edge(clk_ref) then
+ -- set default values
+ lat_upd <= '0';
+
+ -- deglitch pps signal
+ dgl_hist <= dgl_hist(dgl_hist'left-1 downto 0) & gps_1pps;
+ cnt0 := 0;
+ cnt1 := 0;
+ for i in dgl_hist'range loop
+ if dgl_hist(i)='0' then
+ cnt0 := cnt0 + 1;
+ end if;
+ if dgl_hist(i)='1' then
+ cnt1 := cnt1 + 1;
+ end if;
+ end loop;
+ if cnt0 >= 3 then
+ dgl_out <= '0';
+ elsif cnt1 >= 3 then
+ dgl_out <= '1';
+ end if;
+
+ -- detect rising edge on pps
+ pps_last <= dgl_out;
+ re := (dgl_out='1' and pps_last='0');
+
+ -- update counters
+ if re then
+ cnt_lsb <= to_unsigned(0, cnt_lsb'length);
+ lat_lsb <= cnt_lsb;
+ lat_msb <= lat_msb + 1;
+ lat_upd <= '1';
+ else
+ cnt_lsb <= cnt_lsb + 1;
+ end if;
+
+ -- handle reset
+ if rst_ref='1' then
+ dgl_hist <= (others=>'0');
+ dgl_out <= '0';
+ pps_last <= '0';
+ cnt_lsb <= (others=>'0');
+ lat_upd <= '0';
+ lat_lsb <= (others=>'0');
+ lat_msb <= (others=>'0');
+ end if;
+ end if;
+ end process;
+
+ -- bring update-pulse into correct clock domain
+ syn: entity mt_sync_feedback
+ port map (
+ i_clk => clk_ref,
+ i_data => lat_upd,
+ o_clk => clk_sys,
+ o_data => out_upd
+ );
+
+ -- output register
+ process(clk_sys)
+ begin
+ if rising_edge(clk_sys) then
+ -- update output when requested
+ if out_upd='1' then
+ out_lsb <= lat_lsb;
+ out_msb <= lat_msb;
+ end if;
+
+ -- handle reset
+ if rst_sys='1' then
+ out_lsb <= (others=>'0');
+ out_msb <= (others=>'0');
+ end if;
+ end if;
+ end process;
+
+ -- output status
+ status.lsb <= out_lsb;
+ status.msb <= out_msb;
+end rtl;
diff --git a/fpga/hw-v2-mci/src/usbrx/toplevel/usbrx_gpio.vhd b/fpga/hw-v2-mci/src/usbrx/toplevel/usbrx_gpio.vhd
new file mode 100644
index 0000000..5c62fe5
--- /dev/null
+++ b/fpga/hw-v2-mci/src/usbrx/toplevel/usbrx_gpio.vhd
@@ -0,0 +1,72 @@
+---------------------------------------------------------------------------------------------------
+-- Filename : usbrx_gpio.vhd
+-- Project : OsmoSDR FPGA Firmware
+-- Purpose : GPIO Block
+---------------------------------------------------------------------------------------------------
+
+-----------------------------------------------------------------------------------
+-- Copyright (C) 2012 maintech GmbH, Otto-Hahn-Str. 15, 97204 Hoechberg, Germany --
+-- written by Matthias Kleffel --
+-- --
+-- This program is free software; you can redistribute it and/or modify --
+-- it under the terms of the GNU General Public License as published by --
+-- the Free Software Foundation as version 3 of the License, or --
+-- --
+-- This program is distributed in the hope that it will be useful, --
+-- but WITHOUT ANY WARRANTY; without even the implied warranty of --
+-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the --
+-- GNU General Public License V3 for more details. --
+-- --
+-- You should have received a copy of the GNU General Public License --
+-- along with this program. If not, see <http://www.gnu.org/licenses/>. --
+-----------------------------------------------------------------------------------
+
+library ieee;
+ use ieee.std_logic_1164.all;
+ use ieee.numeric_std.all;
+library work;
+ use work.all;
+ use work.mt_toolbox.all;
+ use work.usbrx.all;
+
+entity usbrx_gpio is
+ port(
+ -- common
+ clk : in std_logic;
+ reset : in std_logic;
+
+ -- GPIOs
+ gpio : inout std_logic_vector(10 downto 0);
+
+ -- config / status
+ config : in usbrx_gpio_config_t;
+ status : out usbrx_gpio_status_t
+ );
+end usbrx_gpio;
+
+architecture rtl of usbrx_gpio is
+
+ -- register
+ signal ireg : std_logic_vector(10 downto 0) := (others=>'0');
+ signal oreg : std_logic_vector(10 downto 0) := (others=>'0');
+ signal oena : std_logic_vector(10 downto 0) := (others=>'0');
+
+begin
+
+ -- create output-driver
+ od: for i in gpio'range generate
+ begin
+ gpio(i) <= oreg(i) when oena(i)='1' else 'Z';
+ end generate;
+
+ -- IOBs
+ process(clk)
+ begin
+ if rising_edge(clk) then
+ ireg <= to_X01(gpio);
+ oreg <= config.odata;
+ oena <= config.oena;
+ end if;
+ end process;
+
+end rtl;
diff --git a/fpga/hw-v2-mci/src/usbrx/toplevel/usbrx_pwm.vhd b/fpga/hw-v2-mci/src/usbrx/toplevel/usbrx_pwm.vhd
new file mode 100644
index 0000000..c71e3a2
--- /dev/null
+++ b/fpga/hw-v2-mci/src/usbrx/toplevel/usbrx_pwm.vhd
@@ -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;
diff --git a/fpga/hw-v2-mci/src/usbrx/toplevel/usbrx_regbank.vhd b/fpga/hw-v2-mci/src/usbrx/toplevel/usbrx_regbank.vhd
new file mode 100644
index 0000000..dac3c94
--- /dev/null
+++ b/fpga/hw-v2-mci/src/usbrx/toplevel/usbrx_regbank.vhd
@@ -0,0 +1,240 @@
+---------------------------------------------------------------------------------------------------
+-- 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_gpio : out usbrx_gpio_config_t;
+ cfg_adc : out usbrx_adc_config_t;
+ cfg_ssc : out usbrx_ssc_config_t;
+ cfg_fil : out usbrx_fil_config_t;
+ cfg_off : out usbrx_off_config_t;
+
+ -- status
+ stat_ref : in usbrx_ref_status_t;
+ stat_gpio : in usbrx_gpio_status_t;
+
+ -- SPI interface
+ spi_ncs : in std_logic;
+ spi_sclk : in std_logic;
+ 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);
+ signal reg_gain : std_logic_vector(31 downto 0);
+ signal reg_swap : std_logic_vector(0 downto 0);
+ signal reg_ioe : std_logic_vector(10 downto 0);
+ signal reg_iod : std_logic_vector(10 downto 0);
+
+ -- avoid block-ram inference
+ attribute syn_romstyle : string;
+ 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";
+ reg_gain <= x"80008000";
+ reg_swap <= "0";
+ reg_ioe <= "00000000000";
+ reg_iod <= "00000000000";
+ elsif rising_edge(clk) then
+ -- output zeros by default
+ bus_rdata <= (others=>'0');
+
+ -- 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 =>
+ -- <unused>
+ null;
+
+ 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 =>
+ -- sample offset
+ bus_rdata <= reg_off;
+ if bus_wena='1' then
+ reg_off <= bus_wdata(31 downto 0);
+ end if;
+ when 8 =>
+ -- sample gain
+ bus_rdata <= reg_gain;
+ if bus_wena='1' then
+ reg_gain <= bus_wdata(31 downto 0);
+ end if;
+ when 9 =>
+ -- sample swap
+ bus_rdata(0 downto 0) <= reg_swap;
+ if bus_wena='1' then
+ reg_swap <= bus_wdata( 0 downto 0);
+ end if;
+
+ when 10 =>
+ -- GPIO - output enable
+ bus_rdata(10 downto 0) <= reg_ioe;
+ if bus_wena='1' then
+ reg_ioe <= bus_wdata(10 downto 0);
+ end if;
+ when 11 =>
+ -- GPIO - output data
+ bus_rdata(10 downto 0) <= reg_iod;
+ if bus_wena='1' then
+ reg_iod <= bus_wdata(10 downto 0);
+ end if;
+ when 12 =>
+ -- GPIO - input data
+ bus_rdata(10 downto 0) <= stat_gpio.idata;
+
+ when 13 =>
+ -- reference frequency
+ bus_rdata(24 downto 0) <= std_logic_vector(stat_ref.lsb);
+ bus_rdata(31 downto 25) <= std_logic_vector(stat_ref.msb);
+
+ when others =>
+ -- invalid address
+ 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));
+ cfg_off.igain <= unsigned(reg_gain(15 downto 0));
+ cfg_off.qgain <= unsigned(reg_gain(31 downto 16));
+ cfg_off.swap <= reg_swap(0);
+ cfg_gpio.oena <= reg_ioe;
+ cfg_gpio.odata <= reg_iod;
+
+end rtl;
diff --git a/fpga/hw-v2-mci/src/usbrx/toplevel/usbrx_spi.vhd b/fpga/hw-v2-mci/src/usbrx/toplevel/usbrx_spi.vhd
new file mode 100644
index 0000000..1c3b541
--- /dev/null
+++ b/fpga/hw-v2-mci/src/usbrx/toplevel/usbrx_spi.vhd
@@ -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;
diff --git a/fpga/hw-v2-mci/src/usbrx/toplevel/usbrx_toplevel.vhd b/fpga/hw-v2-mci/src/usbrx/toplevel/usbrx_toplevel.vhd
new file mode 100644
index 0000000..b5be3f4
--- /dev/null
+++ b/fpga/hw-v2-mci/src/usbrx/toplevel/usbrx_toplevel.vhd
@@ -0,0 +1,323 @@
+---------------------------------------------------------------------------------------------------
+-- 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
+ led : inout std_logic;
+ 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_gpio : usbrx_gpio_config_t;
+ signal cfg_adc : usbrx_adc_config_t;
+ signal cfg_ssc : usbrx_ssc_config_t;
+ signal cfg_fil : usbrx_fil_config_t;
+ signal cfg_off : usbrx_off_config_t;
+
+ -- status
+ signal stat_ref : usbrx_ref_status_t;
+ signal stat_gpio : usbrx_gpio_status_t;
+
+ -- ADC <-> offset
+ signal adc_off_clk : std_logic;
+ 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);
+
+ -- enusure that signal-names are kept (important for timing contraints)
+ attribute syn_keep of clk_in_pclk : signal is true;
+
+ -- TODO
+ signal gpio_dummy : std_logic_vector(5 downto 0) := (others=>'Z');
+
+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
+ );
+
+ -- 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,
+ cfg_gpio => cfg_gpio,
+
+ -- status
+ stat_ref => stat_ref,
+ stat_gpio => stat_gpio,
+
+ -- SPI interface
+ spi_ncs => ctl_cs,
+ spi_sclk => ctl_sck,
+ spi_mosi => ctl_mosi,
+ spi_miso => ctl_miso
+ );
+
+ -- reference clock measurement
+ refclk: entity usbrx_clkref
+ port map (
+ -- system clocks
+ clk_sys => clk_80,
+ rst_sys => rst_80,
+
+ -- reference signal
+ clk_ref => clk_30,
+ rst_ref => rst_30,
+
+ -- 1pps signal
+ gps_1pps => gps_1pps,
+
+ -- status
+ status => stat_ref
+ );
+
+ -- GPIOs
+ io: entity usbrx_gpio
+ port map (
+ -- common
+ clk => clk_80,
+ reset => rst_80,
+
+ -- GPIOs
+ gpio(3 downto 0) => gpio(3 downto 0),
+ gpio(9 downto 4) => gpio_dummy,
+ gpio(10) => led,
+
+ -- config / status
+ config => cfg_gpio,
+ status => stat_gpio
+ );
+
+ -- 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
+ );
+
+ -- SDIO output
+ sdio: entity usbrx_sdio
+ 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,
+
+ -- SDIO interface
+ sd_clk => gpio(4),
+ sd_cmd => gpio(5),
+ sd_dat => gpio(9 downto 6)
+ );
+
+ -- TODO
+-- synopsys translate_off
+ gpio(4) <= 'H';
+-- synopsys translate_on
+
+ -- TODO
+ rx_clk <= '1';
+ rx_syn <= '1';
+ rx_dat <= '1';
+
+ -- drive unused IOs
+ ctl_int <= '1';
+
+ -- virtual GNDs/VCCs
+ vgnd <= (others=>'0');
+ vcc12 <= (others=>'Z');
+ vcc33 <= (others=>'1');
+
+end rtl;
+
+
diff --git a/fpga/hw-v2-mci/src/usbrx/usbrx.vhd b/fpga/hw-v2-mci/src/usbrx/usbrx.vhd
new file mode 100644
index 0000000..3839c7a
--- /dev/null
+++ b/fpga/hw-v2-mci/src/usbrx/usbrx.vhd
@@ -0,0 +1,86 @@
+---------------------------------------------------------------------------------------------------
+-- 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 config
+ type usbrx_off_config_t is record
+ swap : std_logic;
+ ioff : signed(15 downto 0);
+ qoff : signed(15 downto 0);
+ igain : unsigned(15 downto 0);
+ qgain : unsigned(15 downto 0);
+ end record;
+
+ -- decimation filter config
+ type usbrx_fil_config_t is record
+ decim : unsigned(2 downto 0);
+ end record;
+
+ -- clock reference status
+ type usbrx_ref_status_t is record
+ lsb : unsigned(24 downto 0);
+ msb : unsigned(6 downto 0);
+ end record;
+
+ -- GPIO config
+ type usbrx_gpio_config_t is record
+ oena : std_logic_vector(10 downto 0);
+ odata : std_logic_vector(10 downto 0);
+ end record;
+
+ -- clock reference status
+ type usbrx_gpio_status_t is record
+ idata : std_logic_vector(10 downto 0);
+ end record;
+
+end usbrx;
+
+package body usbrx is
+ -- nothing so far
+end usbrx;
+
diff --git a/fpga/hw-v2-mci/stimulators.set b/fpga/hw-v2-mci/stimulators.set
new file mode 100644
index 0000000..78296b7
--- /dev/null
+++ b/fpga/hw-v2-mci/stimulators.set
@@ -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>
diff --git a/fpga/hw-v2-mci/synthesis.order b/fpga/hw-v2-mci/synthesis.order
new file mode 100644
index 0000000..3196ad6
--- /dev/null
+++ b/fpga/hw-v2-mci/synthesis.order
@@ -0,0 +1,5 @@
+i<>.\src\usbrx\toplevel\usbrx_toplevel.vhd
+i<>.\src\mt_toolbox\mt_synctools.vhd
+i<>.\src\sdio\sdio_top.vhd
+i<>.\src\testbench\tb_sdio.vhd
+i<>.\src\sdio\mt_resample_fifo.vhd
diff --git a/fpga/hw-v2-mci/usbrx_vhdl.adf b/fpga/hw-v2-mci/usbrx_vhdl.adf
new file mode 100644
index 0000000..607504f
--- /dev/null
+++ b/fpga/hw-v2-mci/usbrx_vhdl.adf
@@ -0,0 +1,172 @@
+[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:\DVB\sr_systems\sr-usbrx\usbrx_vhdl_sdio\src\sdio
+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
+
+[Files.Data]
+.\src\mt_toolbox\mt_toolbox.vhd=VHDL Source Code
+.\src\mt_toolbox\mt_clktools.vhd=VHDL Source Code
+.\src\mt_toolbox\mt_synctools.vhd=VHDL Source Code
+.\src\mt_filter\mt_filter.vhd=VHDL Source Code
+.\src\mt_filter\mt_fil_storage_slow.vhd=VHDL Source Code
+.\src\mt_filter\mt_fil_mac_slow.vhd=VHDL Source Code
+.\src\mt_filter\mt_fir_symmetric_slow.vhd=VHDL Source Code
+.\src\sdio\sdio_txfifo.vhd=VHDL Source Code
+.\src\sdio\sdio_txctrl.vhd=VHDL Source Code
+.\src\sdio\sdio_cmd.vhd=VHDL Source Code
+.\src\sdio\sdio_dat.vhd=VHDL Source Code
+.\src\sdio\sdio_top.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\datapath\usbrx_sdio.vhd=VHDL Source Code
+.\src\usbrx\toplevel\usbrx_clkgen.vhd=VHDL Source Code
+.\src\usbrx\toplevel\usbrx_clkref.vhd=VHDL Source Code
+.\src\usbrx\toplevel\usbrx_gpio.vhd=VHDL Source Code
+.\src\usbrx\toplevel\usbrx_spi.vhd=VHDL Source Code
+.\src\usbrx\toplevel\usbrx_regbank.vhd=VHDL Source Code
+.\src\usbrx\toplevel\usbrx_pwm.vhd=VHDL Source Code
+.\src\usbrx\toplevel\usbrx_toplevel.vhd=VHDL Source Code
+.\src\testbench\tb_sdio.vhd=VHDL Source Code
+.\src\testbench\tb_filter.vhd=VHDL Source Code
+.\src\testbench\tb_usbrx.vhd=VHDL Test Bench
+.\src\testbench\tb_sdio_stim.vhd=VHDL Source Code
+
+[Groups]
+mt_toolbox=1
+mt_filter=1
+sdio=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_toolbox/mt_synctools.vhd=-1
+mt_filter/mt_filter.vhd=-1
+mt_filter/mt_fil_storage_slow.vhd=-1
+mt_filter/mt_fil_mac_slow.vhd=-1
+mt_filter/mt_fir_symmetric_slow.vhd=-1
+sdio/sdio_txfifo.vhd=-1
+sdio/sdio_txctrl.vhd=-1
+sdio/sdio_cmd.vhd=-1
+sdio/sdio_dat.vhd=-1
+sdio/sdio_top.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\datapath/usbrx_sdio.vhd=-1
+usbrx\toplevel/usbrx_clkgen.vhd=-1
+usbrx\toplevel/usbrx_clkref.vhd=-1
+usbrx\toplevel/usbrx_gpio.vhd=-1
+usbrx\toplevel/usbrx_spi.vhd=-1
+usbrx\toplevel/usbrx_regbank.vhd=-1
+usbrx\toplevel/usbrx_pwm.vhd=-1
+usbrx\toplevel/usbrx_toplevel.vhd=-1
+testbench/tb_sdio.vhd=-1
+testbench/tb_sdio_stim.vhd=-1
+testbench/tb_filter.vhd=-1
+testbench/tb_usbrx.vhd=-1
+
diff --git a/fpga/hw-v2-mci/usbrx_vhdl.aws b/fpga/hw-v2-mci/usbrx_vhdl.aws
new file mode 100644
index 0000000..be6b731
--- /dev/null
+++ b/fpga/hw-v2-mci/usbrx_vhdl.aws
@@ -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