pax_global_header 0000666 0000000 0000000 00000000064 12651560150 0014513 g ustar 00root root 0000000 0000000 52 comment=02965e50741e81c59c7d4889186c0b0cef4cb564
x393-02965e50741e81c59c7d4889186c0b0cef4cb564/ 0000775 0000000 0000000 00000000000 12651560150 0017022 5 ustar 00root root 0000000 0000000 x393-02965e50741e81c59c7d4889186c0b0cef4cb564/.editor_defines 0000664 0000000 0000000 00000000366 12651560150 0022013 0 ustar 00root root 0000000 0000000 // This file may be used to define same pre-processor macros to be included into each parsed file
// TODO: Fix VDT - without IVERILOG defined, closure does not include modules needed for Icarus
`define IVERILOG 1
`include "system_defines.vh"
x393-02965e50741e81c59c7d4889186c0b0cef4cb564/.gitignore 0000664 0000000 0000000 00000000734 12651560150 0021016 0 ustar 00root root 0000000 0000000 unisims
vivado_*
syntax_*
simulation/*
ise_*
attic/*
hardware_tests/*
IVERILOG_INCLUDE.v
x393.prj
*DEBUG_VDT*
*.kate-swp
*.old
*.new
*.bad
*.pyc
*.pickle
py393/dbg*
includes/x393_cur_params_sim.vh
includes/x393_cur_params_target_*.vh
py393/exp_gpio.py
py393/mon_gpio.py
savefile01.sav
x353
compressor_jp/huff_fifo353.v
x393_testbench0-a1.sav
x393_testbench01-*.sav
x393_testbench01.gtkw
x393_testbench01_backup.sav
x393_testbench01_debug_membridge.sav
x393_testbench02-0.sav
x393-02965e50741e81c59c7d4889186c0b0cef4cb564/.project 0000664 0000000 0000000 00000011153 12651560150 0020472 0 ustar 00root root 0000000 0000000
x393
org.python.pydev.PyDevBuilder
com.elphel.vdt.veditor.simulateBuilder
com.elphel.vdt.veditor.simulateBuilder.00000000Default.CleanCommand
echo 'Clean'
com.elphel.vdt.veditor.simulateBuilder.00000000Default.buildOrder
0
com.elphel.vdt.veditor.simulateBuilder.00000000Default.command
echo 'No Build Configuration Specified'
com.elphel.vdt.veditor.simulateBuilder.00000000Default.enable
true
com.elphel.vdt.veditor.simulateBuilder.00000000Default.name
Default
com.elphel.vdt.veditor.simulateBuilder.00000000Default.parser
com.elphel.vdt.veditor.simulateBuilder.00000000Default.workFolder
com.elphel.vdt.veditor.HdlNature
org.python.pydev.pythonNature
ise_logs/ISExst.log
1
/home/andrey/git/x393/ise_logs/ISExst-20150505133407662.log
ise_state/x393-synth.tgz
1
/home/andrey/git/x393/ise_state/x393-synth-20150228145735970.tgz
vivado_logs/VivadoBitstream.log
1
/home/andrey/git/x393/vivado_logs/VivadoBitstream-20151117233913191.log
vivado_logs/VivadoOpt.log
1
/home/andrey/git/x393/vivado_logs/VivadoOpt-20151117233913191.log
vivado_logs/VivadoOptPhys.log
1
/home/andrey/git/x393/vivado_logs/VivadoOptPhys-20151117233913191.log
vivado_logs/VivadoOptPower.log
1
/home/andrey/git/x393/vivado_logs/VivadoOptPower-20151117233913191.log
vivado_logs/VivadoPlace.log
1
/home/andrey/git/x393/vivado_logs/VivadoPlace-20151117233913191.log
vivado_logs/VivadoRoute.log
1
/home/andrey/git/x393/vivado_logs/VivadoRoute-20151117233913191.log
vivado_logs/VivadoSynthesis.log
1
/home/andrey/git/x393/vivado_logs/VivadoSynthesis-20151117233307674.log
vivado_logs/VivadoTimimgSummaryReportImplemented.log
1
/home/andrey/git/x393/vivado_logs/VivadoTimimgSummaryReportImplemented-20151117233913191.log
vivado_logs/VivadoTimimgSummaryReportSynthesis.log
1
/home/andrey/git/x393/vivado_logs/VivadoTimimgSummaryReportSynthesis-20151105233458943.log
vivado_logs/VivadoTimingReportImplemented.log
1
/home/andrey/git/x393/vivado_logs/VivadoTimingReportImplemented-20151101221627109.log
vivado_logs/VivadoTimingReportSynthesis.log
1
/home/andrey/git/x393/vivado_logs/VivadoTimingReportSynthesis-20150905102847882.log
vivado_state/x393-opt-phys.dcp
1
/home/andrey/git/x393/vivado_state/x393-opt-phys-20150904164653967.dcp
vivado_state/x393-place.dcp
1
/home/andrey/git/x393/vivado_state/x393-place-20150904164653967.dcp
vivado_state/x393-route.dcp
1
/home/andrey/git/x393/vivado_state/x393-route-20150904164653967.dcp
vivado_state/x393-synth.dcp
1
/home/andrey/git/x393/vivado_state/x393-synth-20150905102847882.dcp
x393-02965e50741e81c59c7d4889186c0b0cef4cb564/.pydevproject 0000664 0000000 0000000 00000000456 12651560150 0021546 0 ustar 00root root 0000000 0000000
Default
python 2.7
x393-02965e50741e81c59c7d4889186c0b0cef4cb564/.settings/ 0000775 0000000 0000000 00000000000 12651560150 0020740 5 ustar 00root root 0000000 0000000 x393-02965e50741e81c59c7d4889186c0b0cef4cb564/.settings/com.elphel.vdt.FPGA_project.prefs 0000664 0000000 0000000 00000000740 12651560150 0027066 0 ustar 00root root 0000000 0000000 FPGA_project_0_SimulationTopFile=x393_testbench03.tf
FPGA_project_1_SimulationTopModule=x393_testbench03
FPGA_project_2_ImplementationTopFile=x393.v
FPGA_project_4_part=xc7z030fbg484-1
FPGA_project_5_part=xc7z030fbg484-1
com.elphel.store.context.FPGA_project=FPGA_project_2_ImplementationTopFile<-@\#\#@->FPGA_project_4_part<-@\#\#@->FPGA_project_0_SimulationTopFile<-@\#\#@->FPGA_project_1_SimulationTopModule<-@\#\#@->FPGA_project_5_part<-@\#\#@->
eclipse.preferences.version=1
x393-02965e50741e81c59c7d4889186c0b0cef4cb564/.settings/com.elphel.vdt.ISExst.prefs 0000664 0000000 0000000 00000000332 12651560150 0025777 0 ustar 00root root 0000000 0000000 ISExst_170_constraints=ddrc_test01.xcf
ISExst_96_OtherProblems=HDLCompiler\:413<-@\#\#@->
com.elphel.store.context.ISExst=ISExst_170_constraints<-@\#\#@->ISExst_96_OtherProblems<-@\#\#@->
eclipse.preferences.version=1
x393-02965e50741e81c59c7d4889186c0b0cef4cb564/.settings/com.elphel.vdt.VivadoBitstream.prefs 0000664 0000000 0000000 00000001252 12651560150 0027725 0 ustar 00root root 0000000 0000000 VivadoBitstream_103_PreBitstreamTCL=set_property BITSTREAM.STARTUP.MATCH_CYCLE NoWait [current_design]<-@\#\#@->
VivadoBitstream_105_force=true
VivadoBitstream_122_PreBitstreamTCL=set_property "BITSTREAM.STARTUP.MATCH_CYCLE" NoWait [current_design]<-@\#\#@->
VivadoBitstream_123_PreBitstreamTCL=set_property "BITSTREAM.STARTUP.MATCH_CYCLE" NoWait [current_design]<-@\#\#@->
VivadoBitstream_124_force=true
com.elphel.store.context.VivadoBitstream=VivadoBitstream_105_force<-@\#\#@->VivadoBitstream_103_PreBitstreamTCL<-@\#\#@->VivadoBitstream_124_force<-@\#\#@->VivadoBitstream_122_PreBitstreamTCL<-@\#\#@->VivadoBitstream_123_PreBitstreamTCL<-@\#\#@->
eclipse.preferences.version=1
x393-02965e50741e81c59c7d4889186c0b0cef4cb564/.settings/com.elphel.vdt.VivadoOpt.prefs 0000664 0000000 0000000 00000000326 12651560150 0026536 0 ustar 00root root 0000000 0000000 VivadoOpt_123_SkipSnapshotOpt=true
VivadoOpt_124_SkipSnapshotOpt=true
com.elphel.store.context.VivadoOpt=VivadoOpt_123_SkipSnapshotOpt<-@\#\#@->VivadoOpt_124_SkipSnapshotOpt<-@\#\#@->
eclipse.preferences.version=1
x393-02965e50741e81c59c7d4889186c0b0cef4cb564/.settings/com.elphel.vdt.VivadoOptPhys.prefs 0000664 0000000 0000000 00000000372 12651560150 0027403 0 ustar 00root root 0000000 0000000 VivadoOptPhys_123_SkipSnapshotOptPhys=true
VivadoOptPhys_124_SkipSnapshotOptPhys=true
com.elphel.store.context.VivadoOptPhys=VivadoOptPhys_123_SkipSnapshotOptPhys<-@\#\#@->VivadoOptPhys_124_SkipSnapshotOptPhys<-@\#\#@->
eclipse.preferences.version=1
x393-02965e50741e81c59c7d4889186c0b0cef4cb564/.settings/com.elphel.vdt.VivadoOptPower.prefs 0000664 0000000 0000000 00000000403 12651560150 0027547 0 ustar 00root root 0000000 0000000 VivadoOptPower_124_SkipSnapshotOptPower=true
VivadoOptPower_125_SkipSnapshotOptPower=true
com.elphel.store.context.VivadoOptPower=VivadoOptPower_124_SkipSnapshotOptPower<-@\#\#@->VivadoOptPower_125_SkipSnapshotOptPower<-@\#\#@->
eclipse.preferences.version=1
x393-02965e50741e81c59c7d4889186c0b0cef4cb564/.settings/com.elphel.vdt.VivadoPlace.prefs 0000664 0000000 0000000 00000000462 12651560150 0027021 0 ustar 00root root 0000000 0000000 VivadoPlace_111_verbose_place=true
VivadoPlace_123_SkipSnapshotPlace=true
VivadoPlace_124_SkipSnapshotPlace=true
com.elphel.store.context.VivadoPlace=VivadoPlace_111_verbose_place<-@\#\#@->VivadoPlace_123_SkipSnapshotPlace<-@\#\#@->VivadoPlace_124_SkipSnapshotPlace<-@\#\#@->
eclipse.preferences.version=1
x393-02965e50741e81c59c7d4889186c0b0cef4cb564/.settings/com.elphel.vdt.VivadoRoute.prefs 0000664 0000000 0000000 00000000506 12651560150 0027072 0 ustar 00root root 0000000 0000000 VivadoRoute_122_SkipSnapshotRoute=true
VivadoRoute_123_SkipSnapshotRoute=true
VivadoRoute_125_directive_route=MoreGlobalIterations
com.elphel.store.context.VivadoRoute=VivadoRoute_122_SkipSnapshotRoute<-@\#\#@->VivadoRoute_123_SkipSnapshotRoute<-@\#\#@->VivadoRoute_125_directive_route<-@\#\#@->
eclipse.preferences.version=1
x393-02965e50741e81c59c7d4889186c0b0cef4cb564/.settings/com.elphel.vdt.VivadoSynthesis.prefs 0000664 0000000 0000000 00000002567 12651560150 0027776 0 ustar 00root root 0000000 0000000 VivadoSynthesis_101_MaxMsg=10000
VivadoSynthesis_102_ConstraintsFiles=x393.xdc<-@\#\#@->x393_timing.xdc<-@\#\#@->
VivadoSynthesis_115_flatten_hierarchy=none
VivadoSynthesis_121_ConstraintsFiles=x393.xdc<-@\#\#@->x393_timing.xdc<-@\#\#@->
VivadoSynthesis_122_ConstraintsFiles=x393_hispi.xdc<-@\#\#@->x393_hispi_timing.xdc<-@\#\#@->
VivadoSynthesis_122_SkipSnapshotSynth=true
VivadoSynthesis_123_ResetProject=true
VivadoSynthesis_123_SkipSnapshotSynth=true
VivadoSynthesis_124_ConstraintsFiles=x393_hispi.xdc<-@\#\#@->x393_hispi_timing.xdc<-@\#\#@->
VivadoSynthesis_127_verbose=true
VivadoSynthesis_81_parser_mode=1
VivadoSynthesis_93_OtherProblems=Netlist 29-345<-@\#\#@->Board 49-26<-@\#\#@->Synth 8-638<-@\#\#@->Synth 8-256<-@\#\#@->
VivadoSynthesis_95_ShowInfo=true
com.elphel.store.context.VivadoSynthesis=VivadoSynthesis_102_ConstraintsFiles<-@\#\#@->VivadoSynthesis_95_ShowInfo<-@\#\#@->VivadoSynthesis_115_flatten_hierarchy<-@\#\#@->VivadoSynthesis_101_MaxMsg<-@\#\#@->VivadoSynthesis_127_verbose<-@\#\#@->VivadoSynthesis_93_OtherProblems<-@\#\#@->VivadoSynthesis_81_parser_mode<-@\#\#@->VivadoSynthesis_121_ConstraintsFiles<-@\#\#@->VivadoSynthesis_122_SkipSnapshotSynth<-@\#\#@->VivadoSynthesis_123_ResetProject<-@\#\#@->VivadoSynthesis_123_SkipSnapshotSynth<-@\#\#@->VivadoSynthesis_122_ConstraintsFiles<-@\#\#@->VivadoSynthesis_124_ConstraintsFiles<-@\#\#@->
eclipse.preferences.version=1
com.elphel.vdt.VivadoTimimgSummaryReportSynthesis.prefs 0000664 0000000 0000000 00000001021 12651560150 0033620 0 ustar 00root root 0000000 0000000 x393-02965e50741e81c59c7d4889186c0b0cef4cb564/.settings VivadoTimimgSummaryReportSynthesis_102_DisableVivadoTimingSummary=true
VivadoTimimgSummaryReportSynthesis_121_DisableVivadoTimingSummary=true
VivadoTimimgSummaryReportSynthesis_122_DisableVivadoTimingSummary=true
com.elphel.store.context.VivadoTimimgSummaryReportSynthesis=VivadoTimimgSummaryReportSynthesis_102_DisableVivadoTimingSummary<-@\#\#@->VivadoTimimgSummaryReportSynthesis_121_DisableVivadoTimingSummary<-@\#\#@->VivadoTimimgSummaryReportSynthesis_122_DisableVivadoTimingSummary<-@\#\#@->
eclipse.preferences.version=1
com.elphel.vdt.VivadoTimingReportImplemented.prefs 0000664 0000000 0000000 00000000575 12651560150 0032532 0 ustar 00root root 0000000 0000000 x393-02965e50741e81c59c7d4889186c0b0cef4cb564/.settings VivadoTimingReportImplemented_121_DisableVivadoTiming=true
VivadoTimingReportImplemented_122_DisableVivadoTiming=true
com.elphel.store.context.VivadoTimingReportImplemented=VivadoTimingReportImplemented_132_rawfile<-@\#\#@->VivadoTimingReportImplemented_121_DisableVivadoTiming<-@\#\#@->VivadoTimingReportImplemented_122_DisableVivadoTiming<-@\#\#@->
eclipse.preferences.version=1
com.elphel.vdt.VivadoTimingReportSynthesis.prefs 0000664 0000000 0000000 00000000666 12651560150 0032261 0 ustar 00root root 0000000 0000000 x393-02965e50741e81c59c7d4889186c0b0cef4cb564/.settings VivadoTimingReportSynthesis_102_DisableVivadoTiming=true
VivadoTimingReportSynthesis_121_DisableVivadoTiming=true
VivadoTimingReportSynthesis_122_DisableVivadoTiming=true
com.elphel.store.context.VivadoTimingReportSynthesis=VivadoTimingReportSynthesis_102_DisableVivadoTiming<-@\#\#@->VivadoTimingReportSynthesis_121_DisableVivadoTiming<-@\#\#@->VivadoTimingReportSynthesis_122_DisableVivadoTiming<-@\#\#@->
eclipse.preferences.version=1
x393-02965e50741e81c59c7d4889186c0b0cef4cb564/.settings/com.elphel.vdt.iverilog.prefs 0000664 0000000 0000000 00000005261 12651560150 0026446 0 ustar 00root root 0000000 0000000 com.elphel.store.context.iverilog=iverilog_81_TopModulesOther<-@\#\#@->iverilog_83_ExtraFiles<-@\#\#@->iverilog_88_ShowNoProblem<-@\#\#@->iverilog_77_Param_Exe<-@\#\#@->iverilog_78_VVP_Exe<-@\#\#@->iverilog_99_GrepFindErrWarn<-@\#\#@->iverilog_84_IncludeDir<-@\#\#@->iverilog_89_ShowNoProblem<-@\#\#@->iverilog_79_GtkWave_Exe<-@\#\#@->iverilog_98_GTKWaveSavFile<-@\#\#@->iverilog_100_TopModulesOther<-@\#\#@->iverilog_102_ExtraFiles<-@\#\#@->iverilog_103_IncludeDir<-@\#\#@->iverilog_101_TopModulesOther<-@\#\#@->iverilog_103_ExtraFiles<-@\#\#@->iverilog_104_IncludeDir<-@\#\#@->iverilog_113_SaveLogsSimulator<-@\#\#@->iverilog_109_ShowNoProblem<-@\#\#@->iverilog_110_ShowWarnings<-@\#\#@->iverilog_102_TopModulesOther<-@\#\#@->iverilog_104_ExtraFiles<-@\#\#@->iverilog_105_IncludeDir<-@\#\#@->iverilog_110_ShowNoProblem<-@\#\#@->iverilog_113_SaveLogsPreprocessor<-@\#\#@->iverilog_121_GrepFindErrWarn<-@\#\#@->iverilog_114_SaveLogsSimulator<-@\#\#@->iverilog_103_TopModulesOther<-@\#\#@->iverilog_105_ExtraFiles<-@\#\#@->iverilog_106_IncludeDir<-@\#\#@->iverilog_111_ShowNoProblem<-@\#\#@->iverilog_115_SaveLogsSimulator<-@\#\#@->
eclipse.preferences.version=1
iverilog_100_TopModulesOther=glbl<-@\#\#@->
iverilog_101_TopModulesOther=glbl<-@\#\#@->
iverilog_102_ExtraFiles=glbl.v<-@\#\#@->
iverilog_102_TopModulesOther=glbl<-@\#\#@->
iverilog_103_ExtraFiles=glbl.v<-@\#\#@->
iverilog_103_IncludeDir=${verilog_project_loc}/includes<-@\#\#@->${verilog_project_loc}/includes<-@\#\#@->
iverilog_103_TopModulesOther=glbl<-@\#\#@->
iverilog_104_ExtraFiles=glbl.v<-@\#\#@->
iverilog_104_IncludeDir=${verilog_project_loc}/ddr3<-@\#\#@->${verilog_project_loc}/includes<-@\#\#@->
iverilog_105_ExtraFiles=glbl.v<-@\#\#@->
iverilog_105_IncludeDir=${verilog_project_loc}/includes<-@\#\#@->${verilog_project_loc}/ddr3<-@\#\#@->
iverilog_106_IncludeDir=${verilog_project_loc}_sata/x393/includes<-@\#\#@->${verilog_project_loc}_sata/x393/ddr3<-@\#\#@->
iverilog_109_ShowNoProblem=true
iverilog_110_ShowNoProblem=true
iverilog_110_ShowWarnings=false
iverilog_111_ShowNoProblem=true
iverilog_113_SaveLogsPreprocessor=false
iverilog_113_SaveLogsSimulator=true
iverilog_114_SaveLogsSimulator=true
iverilog_115_SaveLogsSimulator=true
iverilog_121_GrepFindErrWarn=error|warning|sorry
iverilog_77_Param_Exe=/usr/local/bin/iverilog
iverilog_78_VVP_Exe=/usr/local/bin/vvp
iverilog_79_GtkWave_Exe=/usr/local/bin/gtkwave
iverilog_81_TopModulesOther=glbl<-@\#\#@->
iverilog_83_ExtraFiles=glbl.v<-@\#\#@->
iverilog_84_IncludeDir=${verilog_project_loc}/ddr3<-@\#\#@->${verilog_project_loc}/includes<-@\#\#@->
iverilog_88_ShowNoProblem=true
iverilog_89_ShowNoProblem=true
iverilog_98_GTKWaveSavFile=393_testbench01.sav
iverilog_99_GrepFindErrWarn=error|warning|sorry
x393-02965e50741e81c59c7d4889186c0b0cef4cb564/.settings/com.elphel.vdt.prefs 0000664 0000000 0000000 00000000227 12651560150 0024624 0 ustar 00root root 0000000 0000000 com.elphel.store.context.=com.elphel.vdt.PROJECT_DESING_MENU<-@\#\#@->
com.elphel.vdt.PROJECT_DESING_MENU=MainDesignMenu
eclipse.preferences.version=1
x393-02965e50741e81c59c7d4889186c0b0cef4cb564/.settings/org.eclipse.core.resources.prefs 0000664 0000000 0000000 00000000262 12651560150 0027153 0 ustar 00root root 0000000 0000000 eclipse.preferences.version=1
encoding//helpers/convert_data_to_params.py=utf-8
encoding//helpers/convert_pass_init_params.py=utf-8
encoding//helpers/convert_zigzag_rom.py=utf-8
x393-02965e50741e81c59c7d4889186c0b0cef4cb564/OSERDESE1.diff 0000664 0000000 0000000 00000231360 12651560150 0021153 0 ustar 00root root 0000000 0000000 --- /unisims/OSERDESE1.v 1969-12-31 17:00:00.000000000 -0700
+++ ../../vdt-projects/eddr3/unisims/OSERDESE1.v 2014-05-21 09:38:37.691045918 -0600
@@ -0,0 +1,3293 @@
+///////////////////////////////////////////////////////////////////////////////
+// Copyright (c) 1995/2005 Xilinx, Inc.
+// All Right Reserved.
+///////////////////////////////////////////////////////////////////////////////
+// ____ ____
+// / /\/ /
+// /___/ \ / Vendor : Xilinx
+// \ \ \/ Version : 10.1
+// \ \ Description : Xilinx Timing Simulation Library Component
+// / / Source Synchronous Output Serializer
+// /___/ /\ Filename : OSERDESE1.v
+// \ \ / \ Timestamp : Tue Sep 16 15:30:44 PDT 2008
+// \___\/\___\
+//
+// Revision:
+// 09/16/08 - Initial version.
+// 12/05/08 - IR 495397.
+// 01/13/09 - IR 503429.
+// 01/15/09 - IR 503783 CLKPERF is not inverted for OFB/ofb_out.
+// 02/06/09 - CR 507373 Removed IOCLKGLITCH and CLKB
+// 02/26/09 - CR 510489 fixed SHIFTIN2_in
+// 03/16/09 - CR 512140 and 512139 -- sdf load errors
+// 01/27/10 - CR 546419 Updated specify block
+// 12/13/11 - Added `celldefine and `endcelldefine (CR 524859).
+// 09/04/12 - 676501 CLK -> OFB specify path missing
+// End Revision
+
+`timescale 1 ps / 1 ps
+`celldefine
+
+module OSERDESE1 (OCBEXTEND, OFB, OQ, SHIFTOUT1, SHIFTOUT2, TFB, TQ,
+ CLK, CLKDIV, CLKPERF, CLKPERFDELAY, D1, D2, D3, D4, D5, D6, OCE, ODV, RST, SHIFTIN1, SHIFTIN2, T1, T2, T3, T4, TCE, WC);
+
+
+ parameter DATA_RATE_OQ = "DDR";
+ parameter DATA_RATE_TQ = "DDR";
+ parameter integer DATA_WIDTH = 4;
+ parameter integer DDR3_DATA = 1;
+ parameter [0:0] INIT_OQ = 1'b0;
+ parameter [0:0] INIT_TQ = 1'b0;
+ parameter INTERFACE_TYPE = "DEFAULT";
+ parameter integer ODELAY_USED = 0;
+ parameter SERDES_MODE = "MASTER";
+ parameter [0:0] SRVAL_OQ = 1'b0;
+ parameter [0:0] SRVAL_TQ = 1'b0;
+ parameter integer TRISTATE_WIDTH = 4;
+
+
+ `ifdef XIL_TIMING
+ parameter LOC = "UNPLACED";
+ `endif
+
+//-------------------------------------------------------------
+// Outputs:
+//-------------------------------------------------------------
+// OQ: Data output
+// TQ: Output of tristate mux
+// SHIFTOUT1: Carry out data 1 for slave
+// SHIFTOUT2: Carry out data 2 for slave
+// OFB: O Feedback output
+
+//
+//-------------------------------------------------------------
+// Inputs:
+//-------------------------------------------------------------
+//
+// Inputs:
+// CLK: High speed clock from DCM
+// CLKB: Inverted High speed clock from DCM
+// CLKDIV: Low speed divided clock from DCM
+// CLKPERF: Performance Path clock
+// CLKPERFDELAY: delayed Performance Path clock
+// D1, D2, D3, D4, D5, D6 : Data inputs
+// OCE: Clock enable for output data flops
+// ODV: ODELAY value > 140 degrees
+// RST: Reset control
+// T1, T2, T3, T4: tristate inputs
+// SHIFTIN1: Carry in data 1 for master from slave
+// SHIFTIN2: Carry in data 2 for master from slave
+// TCE: Tristate clock enable
+// WC: Write command given by memory controller
+
+ output OCBEXTEND;
+ output OFB;
+ output OQ;
+ output SHIFTOUT1;
+ output SHIFTOUT2;
+ output TFB;
+ output TQ;
+
+ input CLK;
+ input CLKDIV;
+ input CLKPERF;
+ input CLKPERFDELAY;
+ input D1;
+ input D2;
+ input D3;
+ input D4;
+ input D5;
+ input D6;
+ input OCE;
+ input ODV;
+ input RST;
+ input SHIFTIN1;
+ input SHIFTIN2;
+ input T1;
+ input T2;
+ input T3;
+ input T4;
+ input TCE;
+ input WC;
+
+
+//
+ wire SERDES, DDR_CLK_EDGE;
+ wire [5:0] SRTYPE;
+ wire WC_DELAY;
+ wire [4:0] SELFHEAL;
+
+
+ wire load;
+ wire qmux1, qmux, tmux1, tmux2;
+ wire data1, data2, triin1, triin2;
+ wire d2rnk2;
+ wire CLKD;
+ wire CLKDIVD;
+ wire iodelay_state;
+
+// attribute
+ reg data_rate_int;
+ reg [3:0] data_width_int;
+ reg [1:0] tristate_width_int;
+ reg data_rate_oq_int;
+ reg [1:0] data_rate_tq_int;
+ reg ddr3_data_int;
+ reg interface_type_int;
+ reg odelay_used_int;
+ reg serdes_mode_int;
+
+// Output signals
+ wire ioclkglitch_out, ocbextend_out, ofb_out, oq_out, tq_out, shiftout1_out, shiftout2_out;
+
+// Other signals
+ tri0 GSR = glbl.GSR;
+
+ reg notifier;
+
+ wire CLK_in;
+ wire CLKDIV_in;
+ wire CLKPERF_in;
+ wire CLKPERFDELAY_in;
+ wire D1_in;
+ wire D2_in;
+ wire D3_in;
+ wire D4_in;
+ wire D5_in;
+ wire D6_in;
+ wire OCE_in;
+ wire ODV_in;
+ wire RST_in;
+ wire SHIFTIN1_in;
+ wire SHIFTIN2_in;
+ wire T1_in;
+ wire T2_in;
+ wire T3_in;
+ wire T4_in;
+ wire TCE_in;
+ wire WC_in;
+
+`ifndef XIL_TIMING
+
+ assign CLK_in = CLK;
+ assign CLKDIV_in = CLKDIV;
+ assign D1_in = D1;
+ assign D2_in = D2;
+ assign D3_in = D3;
+ assign D4_in = D4;
+ assign D5_in = D5;
+ assign D6_in = D6;
+ assign OCE_in = OCE;
+ assign T1_in = T1;
+ assign T2_in = T2;
+ assign T3_in = T3;
+ assign T4_in = T4;
+ assign TCE_in = TCE;
+ assign WC_in = WC;
+
+`endif // `ifndef XIL_TIMING
+
+
+ assign CLKPERF_in = CLKPERF;
+// assign CLKPERFDELAY_in = CLKPERFDELAY;
+// IR 495397 & IR 499954
+// assign CLKPERFDELAY_in = (CLKPERFDELAY === 1'bx)? 1'b0 : CLKPERFDELAY;
+ generate
+ case (ODELAY_USED)
+ 0: assign CLKPERFDELAY_in = CLKPERF;
+ 1: assign CLKPERFDELAY_in = (CLKPERFDELAY === 1'bx)? 1'b0 : CLKPERFDELAY;
+ endcase
+ endgenerate
+
+ assign SHIFTIN1_in = SHIFTIN1;
+ assign SHIFTIN2_in = SHIFTIN2;
+ assign ODV_in = ODV;
+ assign RST_in = RST;
+
+ buf b_ocbextend (OCBEXTEND, ocbextend_out);
+ buf b_ofb (OFB, ofb_out);
+ buf b_oq (OQ, oq_out);
+ buf b_shiftout1 (SHIFTOUT1, shiftout1_out);
+ buf b_shiftout2 (SHIFTOUT2, shiftout2_out);
+ buf b_tfb (TFB, tfb_out);
+ buf b_tq (TQ, tq_out);
+
+
+ initial begin
+
+//-------------------------------------------------
+//----- DATA_RATE_OQ check
+//-------------------------------------------------
+ case (DATA_RATE_OQ)
+ "SDR" : data_rate_oq_int <= 1'b1;
+ "DDR" : data_rate_oq_int <= 1'b0;
+ default : begin
+ $display("Attribute Syntax Error : The attribute DATA_RATE_OQ on OSERDESE1 instance %m is set to %s. Legal values for this attribute are SDR or DDR", DATA_RATE_OQ);
+ $display("finish OSERDESE1 1");
+ $finish;
+ end
+ endcase // case(DATA_RATE_OQ)
+
+//-------------------------------------------------
+//----- DATA_RATE_TQ check
+//-------------------------------------------------
+ case (DATA_RATE_TQ)
+
+ "BUF" : data_rate_tq_int <= 2'b00;
+ "SDR" : data_rate_tq_int <= 2'b01;
+ "DDR" : data_rate_tq_int <= 2'b10;
+ default : begin
+ $display("Attribute Syntax Error : The attribute DATA_RATE_TQ on OSERDESE1 instance %m is set to %s. Legal values for this attribute are BUF, SDR or DDR", DATA_RATE_TQ);
+ $display("finish OSERDESE1 2");
+ $finish;
+ end
+
+ endcase // case(DATA_RATE_TQ)
+
+//-------------------------------------------------
+//----- DATA_WIDTH check
+//-------------------------------------------------
+ case (DATA_WIDTH)
+
+ 2, 3, 4, 5, 6, 7, 8, 10 : data_width_int = DATA_WIDTH;
+ default : begin
+ $display("Attribute Syntax Error : The attribute DATA_WIDTH on OSERDESE1 instance %m is set to %d. Legal values for this attribute are 2, 3, 4, 5, 6, 7, 8, or 10", DATA_WIDTH);
+ $display("finish OSERDESE1 3");
+ $finish;
+ end
+ endcase // case(DATA_WIDTH)
+
+//-------------------------------------------------
+//----- DDR3_DATA check
+//-------------------------------------------------
+ case (DDR3_DATA)
+ 0 : ddr3_data_int <= 1'b0;
+ 1 : ddr3_data_int <= 1'b1;
+ default : begin
+ $display("Attribute Syntax Error : The attribute DDR3_DATA on OSERDESE1 instance %m is set to %d. Legal values for this attribute are 0 or 1", DDR3_DATA);
+ $display("finish OSERDESE1 4");
+ $finish;
+ end
+ endcase // case(DDR3_DATA)
+
+//-------------------------------------------------
+//----- INTERFACE_TYPE check
+//-------------------------------------------------
+ case (INTERFACE_TYPE)
+ "DEFAULT" : interface_type_int <= 1'b0;
+ "MEMORY_DDR3" : interface_type_int <= 1'b1;
+ default : begin
+ $display("Attribute Syntax Error : The attribute INTERFACE_TYPE on OSERDESE1 instance %m is set to %s. Legal values for this attribute are DEFAULT, or MEMORY_DDR3", INTERFACE_TYPE);
+ $display("finish OSERDESE1 5");
+ $finish;
+ end
+ endcase // INTERFACE_TYPE
+
+
+//-------------------------------------------------
+//----- ODELAY_USED check
+//-------------------------------------------------
+ case (ODELAY_USED)
+
+// "FALSE" : odelay_used_int <= 1'b0;
+// "TRUE" : odelay_used_int <= 1'b1;
+ 0 : odelay_used_int <= 1'b0;
+ 1 : odelay_used_int <= 1'b1;
+ default : begin
+ $display("Attribute Syntax Error : The attribute ODELAY_USED on OSERDESE1 instance %m is set to %s. Legal values for this attribute are FALSE or TRUE", ODELAY_USED);
+ $display("finish OSERDESE1 6");
+ $finish;
+ end
+
+ endcase // case(ODELAY_USED)
+
+//-------------------------------------------------
+//----- SERDES_MODE check
+//-------------------------------------------------
+ case (SERDES_MODE)
+
+ "MASTER" : serdes_mode_int <= 1'b0;
+ "SLAVE" : serdes_mode_int <= 1'b1;
+ default : begin
+ $display("Attribute Syntax Error : The attribute SERDES_MODE on OSERDESE1 instance %m is set to %s. Legal values for this attribute are MASTER or SLAVE", SERDES_MODE);
+ $display("finish OSERDESE1 7");
+ $finish;
+ end
+
+ endcase // case(SERDES_MODE)
+
+//-------------------------------------------------
+//----- TRISTATE_WIDTH check
+//-------------------------------------------------
+ case (TRISTATE_WIDTH)
+
+ 1 : tristate_width_int <= 2'b00;
+ 2 : tristate_width_int <= 2'b01;
+ 4 : tristate_width_int <= 2'b10;
+ default : begin
+ $display("Attribute Syntax Error : The attribute TRISTATE_WIDTH on OSERDESE1 instance %m is set to %d. Legal values for this attribute are 1, 2 or 4", TRISTATE_WIDTH);
+ $display("finish OSERDESE1 8");
+ $finish;
+ end
+
+ endcase // case(TRISTATE_WIDTH)
+// $display("Info: The attribute TRISTATE_WIDTH on OSERDESE1 instance %m is set to %d", TRISTATE_WIDTH);
+
+//-------------------------------------------------
+ end // initial begin
+
+//-------------------------------------------------
+
+ assign SERDES = 1'b1;
+ assign SRTYPE = 6'b111111;
+ assign DDR_CLK_EDGE = 1'b1;
+ assign WC_DELAY = 1'b0;
+ assign SELFHEAL = 5'b00000;
+
+ assign #0 CLKD = CLK;
+ assign #0 CLKDIVD = CLKDIV;
+
+
+ assign #10 ofb_out = (ODELAY_USED == 1)? CLKPERF : oq_out;
+ assign #10 tfb_out = iodelay_state;
+
+
+/////////////////////////////////////////////////////////
+//
+// Delay assignments
+//
+/////////////////////////////////////////////////////////
+
+// Data output delays
+defparam dfront.FFD = 1; // clock to out delay for flip flops
+// driven by clk
+defparam datao.FFD = 1; // clock to out delay for flip flops
+// driven by clk
+defparam dfront.FFCD = 1; // clock to out delay for flip flops
+// driven by clkdiv
+defparam dfront.MXD = 1; // mux delay
+
+defparam dfront.MXR1 = 1; // mux before 2nd rank of flops
+
+// Programmable load generator
+defparam dfront.ldgen.ffdcnt = 1;
+defparam dfront.ldgen.mxdcnt = 1;
+defparam dfront.ldgen.FFRST = 145; // clock to out delay for flop in PLSG
+
+// Tristate output delays
+defparam tfront.ffd = 1; // clock to out delay for flip flops
+defparam tfront.mxd = 1; // mux delay
+
+defparam trio.ffd = 1; // clock to out delay for flip flops
+defparam trio.mxd = 1; // mux delay
+
+//------------------------------------------------------------------
+// Instantiate output data section
+//------------------------------------------------------------------
+
+rank12d_oserdese1_vlog dfront (.D1(D1_in), .D2(D2_in), .D3(D3_in), .D4(D4_in), .D5(D5_in), .D6(D6_in),
+ .d2rnk2(d2rnk2),
+ .SHIFTIN1(SHIFTIN1_in), .SHIFTIN2(SHIFTIN2_in),
+ .C(CLK_in), .CLKDIV(CLKDIV_in), .SR(RST_in), .OCE(OCE_in),
+ .data1(data1), .data2(data2), .SHIFTOUT1(shiftout1_out), .SHIFTOUT2(shiftout2_out),
+ .DATA_RATE_OQ(data_rate_oq_int), .DATA_WIDTH(data_width_int),
+ .SERDES_MODE(serdes_mode_int), .load(load),
+ .IOCLK_GLITCH(ioclkglitch_out),
+ .INIT_OQ(INIT_OQ), .SRVAL_OQ(SRVAL_OQ));
+
+
+trif_oserdese1_vlog tfront (.T1(T1_in), .T2(T2_in), .T3(T3_in), .T4(T4_in), .load(load),
+ .C(CLK_in), .CLKDIV(CLKDIV_in), .SR(RST_in), .TCE(TCE_in),
+ .DATA_RATE_TQ(data_rate_tq_int), .TRISTATE_WIDTH(tristate_width_int),
+ .INIT_TQ(INIT_TQ), .SRVAL_TQ(SRVAL_TQ),
+ .data1(triin1), .data2(triin2));
+
+
+txbuffer_oserdese1_vlog DDR3FIFO (.iodelay_state(iodelay_state), .qmux1(qmux1), .qmux2(qmux2), .tmux1(tmux1), .tmux2(tmux2),
+ .d1(data1), .d2(data2), .t1(triin1), .t2(triin2), .trif(tq_out),
+ .WC(WC_in), .ODV(ODV_in), .extra(ocbextend_out),
+ .clk(CLK_in), .clkdiv(CLKDIV_in), .bufo(CLKPERFDELAY_in), .bufop(CLKPERF_in), .rst(RST_in),
+ .ODELAY_USED(odelay_used_int), .DDR3_DATA(ddr3_data_int),
+ .DDR3_MODE(interface_type_int));
+
+dout_oserdese1_vlog datao (.data1(qmux1), .data2(qmux2),
+ .CLK(CLK_in), .BUFO(CLKPERFDELAY_in), .SR(RST_in), .OCE(OCE_in),
+ .OQ(oq_out), .d2rnk2(d2rnk2),
+ .DATA_RATE_OQ(data_rate_oq_int),
+ .INIT_OQ(INIT_OQ), .SRVAL_OQ(SRVAL_OQ),
+ .DDR3_MODE(interface_type_int));
+
+tout_oserdese1_vlog trio (.data1(tmux1), .data2(tmux2),
+ .CLK(CLK_in), .BUFO(CLKPERFDELAY_in), .SR(RST_in), .TCE(TCE_in),
+ .DATA_RATE_TQ(data_rate_tq_int), .TRISTATE_WIDTH(tristate_width_int),
+ .INIT_TQ(INIT_TQ), .SRVAL_TQ(SRVAL_TQ),
+ .TQ(tq_out), .DDR3_MODE(interface_type_int));
+
+
+`ifndef XIL_TIMING
+ specify
+ ( CLK => OFB) = (100, 100);
+ ( CLK => OQ) = (100, 100);
+ ( CLK => TQ) = (100, 100);
+ ( CLKPERF => OQ) = (100, 100);
+ ( CLKPERF => TQ) = (100, 100);
+ ( CLKPERFDELAY => OQ) = (100, 100);
+ ( CLKPERFDELAY => TQ) = (100, 100);
+ ( T1 => TQ) = (0, 0);
+
+ specparam PATHPULSE$ = 0;
+
+ endspecify
+`endif // `ifndef XIL_TIMING
+
+`ifdef XIL_TIMING
+//*** Timing Checks Start here
+
+ specify
+ ( CLK => OFB) = (100:100:100, 100:100:100);
+ ( CLK => OQ) = (100:100:100, 100:100:100);
+ ( CLK => TQ) = (100:100:100, 100:100:100);
+ ( CLKPERF => OQ) = (100:100:100, 100:100:100);
+ ( CLKPERF => TQ) = (100:100:100, 100:100:100);
+ ( CLKPERFDELAY => OQ) = (100:100:100, 100:100:100);
+ ( CLKPERFDELAY => TQ) = (100:100:100, 100:100:100);
+ ( T1 => TQ) = (0:0:0, 0:0:0);
+
+ $setuphold (posedge CLK, negedge OCE, 0:0:0, 0:0:0, notifier,,, CLK_in, OCE_in);
+ $setuphold (posedge CLK, negedge T1, 0:0:0, 0:0:0, notifier,,, CLK_in, T1_in);
+ $setuphold (posedge CLK, negedge TCE, 0:0:0, 0:0:0, notifier,,, CLK_in, TCE_in);
+ $setuphold (posedge CLK, posedge OCE, 0:0:0, 0:0:0, notifier,,, CLK_in, OCE_in);
+ $setuphold (posedge CLK, posedge T1, 0:0:0, 0:0:0, notifier,,, CLK_in, T1_in);
+ $setuphold (posedge CLK, posedge TCE, 0:0:0, 0:0:0, notifier,,, CLK_in, TCE_in);
+ $setuphold (posedge CLKDIV, negedge D1, 0:0:0, 0:0:0, notifier,,, CLKDIV_in, D1_in);
+ $setuphold (posedge CLKDIV, negedge D2, 0:0:0, 0:0:0, notifier,,, CLKDIV_in, D2_in);
+ $setuphold (posedge CLKDIV, negedge D3, 0:0:0, 0:0:0, notifier,,, CLKDIV_in, D3_in);
+ $setuphold (posedge CLKDIV, negedge D4, 0:0:0, 0:0:0, notifier,,, CLKDIV_in, D4_in);
+ $setuphold (posedge CLKDIV, negedge D5, 0:0:0, 0:0:0, notifier,,, CLKDIV_in, D5_in);
+ $setuphold (posedge CLKDIV, negedge D6, 0:0:0, 0:0:0, notifier,,, CLKDIV_in, D6_in);
+ $setuphold (posedge CLKDIV, negedge RST, 0:0:0, 0:0:0, notifier,,, CLKDIV_in, RST_in);
+ $setuphold (posedge CLKDIV, negedge T1, 0:0:0, 0:0:0, notifier,,, CLKDIV_in, T1_in);
+ $setuphold (posedge CLKDIV, negedge T2, 0:0:0, 0:0:0, notifier,,, CLKDIV_in, T2_in);
+ $setuphold (posedge CLKDIV, negedge T3, 0:0:0, 0:0:0, notifier,,, CLKDIV_in, T3_in);
+ $setuphold (posedge CLKDIV, negedge T4, 0:0:0, 0:0:0, notifier,,, CLKDIV_in, T4_in);
+ $setuphold (posedge CLKDIV, negedge WC, 0:0:0, 0:0:0, notifier,,, CLKDIV_in, WC_in);
+ $setuphold (posedge CLKDIV, posedge D1, 0:0:0, 0:0:0, notifier,,, CLKDIV_in, D1_in);
+ $setuphold (posedge CLKDIV, posedge D2, 0:0:0, 0:0:0, notifier,,, CLKDIV_in, D2_in);
+ $setuphold (posedge CLKDIV, posedge D3, 0:0:0, 0:0:0, notifier,,, CLKDIV_in, D3_in);
+ $setuphold (posedge CLKDIV, posedge D4, 0:0:0, 0:0:0, notifier,,, CLKDIV_in, D4_in);
+ $setuphold (posedge CLKDIV, posedge D5, 0:0:0, 0:0:0, notifier,,, CLKDIV_in, D5_in);
+ $setuphold (posedge CLKDIV, posedge D6, 0:0:0, 0:0:0, notifier,,, CLKDIV_in, D6_in);
+ $setuphold (posedge CLKDIV, posedge RST, 0:0:0, 0:0:0, notifier,,, CLKDIV_in, RST_in);
+ $setuphold (posedge CLKDIV, posedge T1, 0:0:0, 0:0:0, notifier,,, CLKDIV_in, T1_in);
+ $setuphold (posedge CLKDIV, posedge T2, 0:0:0, 0:0:0, notifier,,, CLKDIV_in, T2_in);
+ $setuphold (posedge CLKDIV, posedge T3, 0:0:0, 0:0:0, notifier,,, CLKDIV_in, T3_in);
+ $setuphold (posedge CLKDIV, posedge T4, 0:0:0, 0:0:0, notifier,,, CLKDIV_in, T4_in);
+ $setuphold (posedge CLKDIV, posedge WC, 0:0:0, 0:0:0, notifier,,, CLKDIV_in, WC_in);
+
+ specparam PATHPULSE$ = 0;
+
+ endspecify
+`endif // `ifdef XIL_TIMING
+
+
+endmodule // OSERDESE1
+
+`timescale 1ps/1ps
+/////////////////////////////////////////////////////////
+//
+// module selfheal_oserdese1_vlog
+//
+///////////////////////////////////////////////////////
+//
+// Self healing circuit for Mt Blanc
+// This model ONLY works for SERDES operation!!
+//
+//
+//
+////////////////////////////////////////////////////////
+//
+//
+//
+/////////////////////////////////////////////////////////
+//
+// Inputs:
+// dq3 - dq0: Data from load counter
+// CLKDIV: Divided clock from PLL
+// srint: RESET from load generator
+// rst: Set/Reset control
+//
+//
+//
+// Outputs:
+// SHO: Data output
+//
+//
+//
+// Programmable Points
+// SELFHEAL: String of 5 bits. 1 as enable and 4 as compare
+// Test attributes in model
+//
+//
+//
+//
+//
+////////////////////////////////////////////////////////////////////////////////
+//
+
+module selfheal_oserdese1_vlog (dq3, dq2, dq1, dq0,
+ CLKDIV, srint, rst,
+ SHO);
+
+input dq3, dq2, dq1, dq0;
+
+input CLKDIV, srint, rst;
+
+output SHO;
+
+
+reg shr;
+
+reg SHO;
+
+
+wire clkint;
+
+wire error;
+
+wire rst_in, rst_self_heal;
+
+
+// Programmable Points
+
+wire [4:0] SELFHEAL;
+assign SELFHEAL = 5'b00000;
+
+
+
+//////////////////////////////////////////////////
+// Delay values
+//
+parameter FFD = 10; // clock to out delay for flip flops
+// driven by clk
+parameter FFCD = 10; // clock to out delay for flip flops
+// driven by clkdiv
+parameter MXD = 10; // 60 ps mux delay
+
+parameter MXR1 = 10;
+
+
+
+/////////////////////////////////////////
+
+
+assign clkint = CLKDIV & SELFHEAL[4];
+
+assign error = (((~SELFHEAL[4] ^ SELFHEAL[3]) ^ dq3) | ((~SELFHEAL[4] ^ SELFHEAL[2]) ^ dq2) | ((~SELFHEAL[4] ^ SELFHEAL[1]) ^ dq1) | ((~SELFHEAL[4] ^ SELFHEAL[0]) ^ dq0));
+
+assign rst_in = (~SELFHEAL[4] | ~srint);
+
+assign rst_self_heal = (rst | ~shr);
+
+/////////////////////////////////////////
+// Reset Flop
+////////////////////////////////////////
+
+always @ (posedge clkint or posedge rst)
+begin
+ begin
+ if (rst)
+ begin
+ shr <= # FFD 1'b0;
+ end
+ else begin
+ shr <= #FFD rst_in;
+ end
+ end
+end
+
+// Self heal flop
+always @ (posedge clkint or posedge rst_self_heal)
+begin
+ begin
+
+ if (rst_self_heal)
+ begin
+ SHO <= 1'b0;
+ end
+ else
+ begin
+ SHO <= # FFD error;
+ end
+ end
+end
+
+
+
+
+endmodule
+`timescale 1ps/1ps
+////////////////////////////////////////////////////////
+//
+// module plg_oserdese1_vlog
+//
+////////////////////////////////////////////////////////
+//
+// Programmable Load Generator (PLG)
+// Divide by 2-8 counter with load enable output
+//
+//
+/////////////////////////////////////////////////////////
+//
+// Inputs:
+// c23: Selects between divide by 2 or 3
+// c45: Selects between divide by 4 or 5
+// c67: Selects between divide by 6 or 7
+// sel: Selects which divide function is chosen
+// 00:2 or 3, 01:4 or 5, 10:6 or 7, 11:8
+// clk: High speed clock from DCM
+// clkdiv: Low speed clock from DCM
+// rst: Reset
+//
+//
+//
+// Outputs:
+//
+// load: Loads serdes register at terminal count
+//
+//
+// Test attributes:
+// INIT_LOADCNT: 4-bits to init counter
+// SRTYPE: 1-bit to control synchronous or asynchronous operation
+// SELFHEAL: 5-bits to control self healing feature
+//
+//
+//
+////////////////////////////////////////////////////////////////////////////////
+//
+
+module plg_oserdese1_vlog (c23, c45, c67, sel,
+ clk, clkdiv, rst,
+ load, IOCLK_GLITCH);
+
+input c23, c45, c67;
+
+input [1:0] sel;
+
+input clk, clkdiv, rst;
+
+output load;
+
+output IOCLK_GLITCH;
+
+wire SRTYPE;
+wire [3:0] INIT_LOADCNT;
+wire [4:0] SELFHEAL;
+assign SRTYPE = 1'b1;
+assign INIT_LOADCNT = 4'b0000;
+assign SELFHEAL = 5'b00000;
+
+reg q0, q1, q2, q3;
+
+reg qhr, qlr;
+
+reg load, mux;
+
+wire cntrrst;
+
+
+assign cntrrst = IOCLK_GLITCH | rst;
+
+
+
+// Parameters for gate delays
+parameter ffdcnt = 1;
+parameter mxdcnt = 1;
+parameter FFRST = 145; // clock to out delay for flop in PLSG
+
+
+
+//////////////////////////////////////////////////
+
+tri0 GSR = glbl.GSR;
+
+always @(GSR)
+begin
+ if (GSR)
+ begin
+ force q3 = INIT_LOADCNT[3];
+ force q2 = INIT_LOADCNT[2];
+ force q1 = INIT_LOADCNT[1];
+ force q0 = INIT_LOADCNT[0];
+ end
+ else
+ begin
+ release q3;
+ release q2;
+ release q1;
+ release q0;
+ end
+end
+
+
+
+
+
+
+
+// flops for counter
+// asynchronous reset
+always @ (posedge qhr or posedge clk)
+begin
+ if (qhr & !SRTYPE)
+ begin
+ q0 <= # ffdcnt 1'b0;
+ q1 <= # ffdcnt 1'b0;
+ q2 <= # ffdcnt 1'b0;
+ q3 <= # ffdcnt 1'b0;
+ end
+ else if (!SRTYPE)
+ begin
+ q3 <= # ffdcnt q2;
+ q2 <= # ffdcnt (!(!q0 & !q2) & q1);
+ q1 <= # ffdcnt q0;
+ q0 <= # ffdcnt mux;
+ end
+end
+// synchronous reset
+always @ (posedge clk)
+begin
+ if (qhr & SRTYPE)
+ begin
+ q0 <= # ffdcnt 1'b0;
+ q1 <= # ffdcnt 1'b0;
+ q2 <= # ffdcnt 1'b0;
+ q3 <= # ffdcnt 1'b0;
+ end
+ else if (SRTYPE)
+ begin
+ q3 <= # ffdcnt q2;
+ q2 <= # ffdcnt (!(!q0 & !q2) & q1);
+ q1 <= # ffdcnt q0;
+ q0 <= # ffdcnt mux;
+ end
+end
+
+
+// mux settings for counter
+always @ (sel or c23 or c45 or c67 or q0 or q1 or q2 or q3)
+ begin
+ case (sel)
+ 2'b00: mux <= # mxdcnt (!q0 & !(c23 & q1));
+ 2'b01: mux <= # mxdcnt (!q1 & !(c45 & q2));
+ 2'b10: mux <= # mxdcnt (!q2 & !(c67 & q3));
+ 2'b11: mux <= # mxdcnt !q3;
+ default: mux <= # mxdcnt 1'b0;
+ endcase
+ end
+
+
+// mux decoding for load signal
+always @ (sel or c23 or c45 or c67 or q0 or q1 or q2 or q3)
+ begin
+ case (sel)
+ 2'b00: load <= # mxdcnt q0;
+ 2'b01: load <= # mxdcnt q0 & q1;
+ 2'b10: load <= # mxdcnt q0 & q2;
+ 2'b11: load <= # mxdcnt q0 & q3;
+ default: load <= # mxdcnt 1'b0;
+ endcase
+ end
+
+// flops to reset counter
+
+// Low speed flop
+// asynchronous reset
+always @ (posedge cntrrst or posedge clkdiv)
+ begin
+ if (cntrrst & !SRTYPE)
+ begin
+ qlr <= # FFRST 1'b1;
+ end
+ else if (!SRTYPE)
+ begin
+ qlr <= # FFRST 1'b0;
+ end
+ end
+// synchronous reset
+always @ (posedge clkdiv)
+ begin
+ if (cntrrst & SRTYPE)
+ begin
+ qlr <= # FFRST 1'b1;
+ end
+ else if (SRTYPE)
+ begin
+ qlr <= # FFRST 1'b0;
+ end
+ end
+
+
+
+// High speed flop
+// asynchronous reset
+always @ (posedge cntrrst or posedge clk)
+ begin
+ if (cntrrst & !SRTYPE)
+ begin
+ qhr <= # ffdcnt 1'b1;
+ end
+ else if (!SRTYPE)
+ begin
+ qhr <= # ffdcnt qlr;
+ end
+ end
+// synchronous reset
+always @ (posedge clk)
+ begin
+ if (cntrrst & SRTYPE)
+ begin
+ qhr <= # ffdcnt 1'b1;
+ end
+ else if (SRTYPE)
+ begin
+ qhr <= # ffdcnt qlr;
+ end
+ end
+
+selfheal_oserdese1_vlog fixcntr (.dq3(q3), .dq2(q2), .dq1(q1), .dq0(q0),
+ .CLKDIV(clkdiv), .srint(qlr), .rst(rst),
+ .SHO(IOCLK_GLITCH));
+endmodule
+`timescale 1ps/1ps
+////////////////////////////////////////////////////////
+//
+// module rank12d_oserdese1_vlog
+//
+//
+// This model ONLY works for SERDES operation!!
+// Does not include tristate circuit
+//
+//
+////////////////////////////////////////////////////////
+//
+// Inputs:
+// D1: Data input 1
+// D2: Data input 2
+// D3: Data input 3
+// D4: Data input 4
+// D5: Data input 5
+// D6: Data input 6
+// C: High speed clock from DCM
+// OCE: Clock enable for output data flops
+// SR: Set/Reset control. For the last 3 flops in OQ
+// (d1rnk2, d2rnk2 and d2nrnk2) this function is
+// controlled bythe attributes SRVAL_OQ. In SERDES mode,
+// SR is a RESET ONLY for all other flops! The flops will
+// still be RESET even if SR is programmed to a SET!
+// CLKDIV: Low speed divided clock from DCM
+// SHIFTIN1: Carry in data 1 for master from slave
+// SHIFTIN2: Carry in data 2 for master from slave
+//
+//
+//
+// Outputs:
+// data1: Data output mux for top flop
+// data2: Data output mux for bottom flop
+// SHIFTOUT1: Carry out data 1 for slave
+// SHIFTOUT2: Carry out data 2 for slave
+// load: Used for the tristate when combined into a single model
+//
+//
+//
+// Programmable Points
+// DATA_RATE_OQ: Rate control for data output, 1-bit
+// sdr (1), ddr (0)
+// DATA_WIDTH: Input data width,
+// 4-bits, values can be from 2 to 10
+// SERDES_MODE: Denotes master (0) or slave (1)
+// SIM_X_INPUT: This attribute is NOT SUPPORTED in this model!!!
+//
+//
+//
+// Programmable points for Test model
+// SRTYPE: This is a 4-bit field Sets asynchronous (0) or synchronous (1) set/reset
+// 1st bit (msb) sets rank1 flops, 2nd bit sets 4 flops in rank 2,
+// 3rd bit sets "3 legacy flops, and 4th (lsb) bit sets the counter
+// INIT_ORANK1: Init value for 6 registers in 1st rank (6-bits)
+// INIT_ORANK2_PARTIAL: Init value for bottom 4 registers in the 2nd rank (4-bits)
+// INIT_LOADCNT: Init value for the load counter (4-bits)
+// The other 2 registers in the load counter have init bits, but are
+// not supported in this model
+// SERDES: Indicates that SERDES mode is chosen
+// SLEFHEAL: 5-bit to set self heal circuit
+//
+//
+////////////////////////////////////////////////////////////////////////////////
+//
+
+module rank12d_oserdese1_vlog (D1, D2, D3, D4, D5, D6, d2rnk2,
+ SHIFTIN1, SHIFTIN2,
+ C, CLKDIV, SR, OCE,
+ data1, data2, SHIFTOUT1, SHIFTOUT2,
+ DATA_RATE_OQ, DATA_WIDTH,
+ SERDES_MODE, load,
+ IOCLK_GLITCH,
+ INIT_OQ, SRVAL_OQ);
+
+input D1, D2, D3, D4, D5, D6;
+
+input d2rnk2;
+
+input SHIFTIN1, SHIFTIN2;
+
+input C, CLKDIV, SR, OCE;
+
+input INIT_OQ, SRVAL_OQ;
+
+output data1, data2;
+
+output SHIFTOUT1, SHIFTOUT2;
+
+output load;
+
+output IOCLK_GLITCH;
+
+// Programmable Points
+
+input DATA_RATE_OQ;
+
+input [3:0] DATA_WIDTH;
+
+input SERDES_MODE;
+
+wire DDR_CLK_EDGE, SERDES;
+wire [3:0] SRTYPE;
+wire [4:0] SELFHEAL;
+
+wire [3:0] INIT_ORANK2_PARTIAL;
+wire [5:0] INIT_ORANK1;
+
+assign DDR_CLK_EDGE = 1'b1;
+assign SERDES = 1'b1;
+assign SRTYPE = 4'b1111;
+assign SELFHEAL = 5'b00000;
+
+assign INIT_ORANK2_PARTIAL = 4'b0000;
+assign INIT_ORANK1 = 6'b000000;
+
+reg d1r, d2r, d3r, d4r, d5r, d6r;
+
+reg d3rnk2, d4rnk2, d5rnk2, d6rnk2;
+
+reg data1, data2, data3, data4, data5, data6;
+
+reg ddr_data, odata_edge, sdata_edge;
+
+reg c23, c45, c67;
+
+reg [1:0] sel;
+
+wire C2p, C3;
+
+wire loadint;
+
+wire [3:0] seloq;
+
+wire oqsr, oqrev;
+
+wire [2:0] sel1_4;
+
+wire [3:0] sel5_6;
+
+wire [4:0] plgcnt;
+
+assign C2p = (C & DDR_CLK_EDGE) | (!C & !DDR_CLK_EDGE);
+
+assign C3 = !C2p;
+
+assign plgcnt = {DATA_RATE_OQ,DATA_WIDTH};
+
+assign sel1_4 = {SERDES,loadint,DATA_RATE_OQ};
+
+assign sel5_6 = {SERDES,SERDES_MODE,loadint,DATA_RATE_OQ};
+
+assign load = loadint;
+
+assign seloq = {OCE,DATA_RATE_OQ,oqsr,oqrev};
+
+assign oqsr = !SRTYPE[1] & SR & !SRVAL_OQ;
+
+assign oqrev = !SRTYPE[1] & SR & SRVAL_OQ;
+
+
+
+//////////////////////////////////////////////////
+// Delay values
+//
+parameter FFD = 1; // clock to out delay for flip flops
+// driven by clk
+parameter FFCD = 1; // clock to out delay for flip flops
+// driven by clkdiv
+parameter MXD = 1; // 60 ps mux delay
+
+parameter MXR1 = 1;
+
+////////////////////////////////////////////
+// Initialization of flops with GSR for test model
+///////////////////////////////////////////
+
+tri0 GSR = glbl.GSR;
+
+always @(GSR)
+begin
+ if (GSR)
+ begin
+ force d6rnk2 = INIT_ORANK2_PARTIAL[3];
+ force d5rnk2 = INIT_ORANK2_PARTIAL[2];
+ force d4rnk2 = INIT_ORANK2_PARTIAL[1];
+ force d3rnk2 = INIT_ORANK2_PARTIAL[0];
+
+ force d6r = INIT_ORANK1[5];
+ force d5r = INIT_ORANK1[4];
+ force d4r = INIT_ORANK1[3];
+ force d3r = INIT_ORANK1[2];
+ force d2r = INIT_ORANK1[1];
+ force d1r = INIT_ORANK1[0];
+ end
+ else
+ begin
+ release d6rnk2;
+ release d5rnk2;
+ release d4rnk2;
+ release d3rnk2;
+ release d6r;
+ release d5r;
+ release d4r;
+ release d3r;
+ release d2r;
+ release d1r;
+ end
+end
+
+/////////////////////////////////////////
+
+
+
+// Assign shiftout1 and shiftout2
+
+assign SHIFTOUT1 = d3rnk2 & SERDES_MODE;
+
+assign SHIFTOUT2 = d4rnk2 & SERDES_MODE;
+
+
+
+
+
+
+// last 4 flops which only have reset and init
+// asynchronous operation
+always @ (posedge C or posedge SR)
+begin
+ begin
+ if (SR & !SRTYPE[2])
+ begin
+ d3rnk2 <= # FFD 1'b0;
+ d4rnk2 <= # FFD 1'b0;
+ d5rnk2 <= # FFD 1'b0;
+ d6rnk2 <= # FFD 1'b0;
+ end
+ else if (!SRTYPE[2])
+ begin
+ d3rnk2 <= # FFD data3;
+ d4rnk2 <= # FFD data4;
+ d5rnk2 <= # FFD data5;
+ d6rnk2 <= # FFD data6;
+
+ end
+ end
+end
+// synchronous operation
+always @ (posedge C)
+begin
+ begin
+ if (SR & SRTYPE[2])
+ begin
+ d3rnk2 <= # FFD 1'b0;
+ d4rnk2 <= # FFD 1'b0;
+ d5rnk2 <= # FFD 1'b0;
+ d6rnk2 <= # FFD 1'b0;
+ end
+ else if (SRTYPE[2])
+ begin
+ d3rnk2 <= # FFD data3;
+ d4rnk2 <= # FFD data4;
+ d5rnk2 <= # FFD data5;
+ d6rnk2 <= # FFD data6;
+
+ end
+ end
+end
+
+
+
+
+
+
+
+///////////////////////////////////////////////////
+// First rank of flops for input data
+//////////////////////////////////////////////////
+
+// asynchronous operation
+always @ (posedge CLKDIV or posedge SR)
+begin
+ begin
+ if (SR & !SRTYPE[3])
+ begin
+ d1r <= # FFCD 1'b0;
+ d2r <= # FFCD 1'b0;
+ d3r <= # FFCD 1'b0;
+ d4r <= # FFCD 1'b0;
+ d5r <= # FFCD 1'b0;
+ d6r <= # FFCD 1'b0;
+ end
+ else if (!SRTYPE[3])
+ begin
+ d1r <= # FFCD D1;
+ d2r <= # FFCD D2;
+ d3r <= # FFCD D3;
+ d4r <= # FFCD D4;
+ d5r <= # FFCD D5;
+ d6r <= # FFCD D6;
+
+ end
+ end
+end
+// synchronous operation
+always @ (posedge CLKDIV)
+begin
+ begin
+ if (SR & SRTYPE[3])
+ begin
+ d1r <= # FFCD 1'b0;
+ d2r <= # FFCD 1'b0;
+ d3r <= # FFCD 1'b0;
+ d4r <= # FFCD 1'b0;
+ d5r <= # FFCD 1'b0;
+ d6r <= # FFCD 1'b0;
+ end
+ else if (SRTYPE[3])
+ begin
+ d1r <= # FFCD D1;
+ d2r <= # FFCD D2;
+ d3r <= # FFCD D3;
+ d4r <= # FFCD D4;
+ d5r <= # FFCD D5;
+ d6r <= # FFCD D6;
+
+ end
+ end
+end
+
+// Muxs for 2nd rank of flops
+always @ (sel1_4 or d1r or d2rnk2 or d3rnk2)
+ begin
+
+ casex (sel1_4)
+ 3'b100: data1 <= # MXR1 d3rnk2;
+ 3'b110: data1 <= # MXR1 d1r;
+ 3'b101: data1 <= # MXR1 d2rnk2;
+ 3'b111: data1 <= # MXR1 d1r;
+ default: data1 <= # MXR1 d3rnk2;
+ endcase
+ end
+
+always @ (sel1_4 or d2r or d3rnk2 or d4rnk2)
+ begin
+ casex (sel1_4)
+ 3'b100: data2 <= # MXR1 d4rnk2;
+ 3'b110: data2 <= # MXR1 d2r;
+ 3'b101: data2 <= # MXR1 d3rnk2;
+ 3'b111: data2 <= # MXR1 d2r;
+ default: data2 <= # MXR1 d4rnk2;
+ endcase
+ end
+
+//Note: To stop data rate of 00 from being illegal, register data is fed to mux
+always @ (sel1_4 or d3r or d4rnk2 or d5rnk2)
+ begin
+ casex (sel1_4)
+ 3'b100: data3 <= # MXR1 d5rnk2;
+ 3'b110: data3 <= # MXR1 d3r;
+ 3'b101: data3 <= # MXR1 d4rnk2;
+ 3'b111: data3 <= # MXR1 d3r;
+ default: data3 <= # MXR1 d5rnk2;
+ endcase
+ end
+
+always @ (sel1_4 or d4r or d5rnk2 or d6rnk2)
+ begin
+ casex (sel1_4)
+ 3'b100: data4 <= # MXR1 d6rnk2;
+ 3'b110: data4 <= # MXR1 d4r;
+ 3'b101: data4 <= # MXR1 d5rnk2;
+ 3'b111: data4 <= # MXR1 d4r;
+ default: data4 <= # MXR1 d6rnk2;
+ endcase
+ end
+
+always @ (sel5_6 or d5r or d6rnk2 or SHIFTIN1)
+ begin
+ casex (sel5_6)
+ 4'b1000: data5 <= # MXR1 SHIFTIN1;
+ 4'b1010: data5 <= # MXR1 d5r;
+ 4'b1001: data5 <= # MXR1 d6rnk2;
+ 4'b1011: data5 <= # MXR1 d5r;
+ 4'b1100: data5 <= # MXR1 1'b0;
+ 4'b1110: data5 <= # MXR1 d5r;
+ 4'b1101: data5 <= # MXR1 d6rnk2;
+ 4'b1111: data5 <= # MXR1 d5r;
+ default: data5 <= # MXR1 SHIFTIN1;
+ endcase
+ end
+
+always @ (sel5_6 or D6 or d6r or SHIFTIN1 or SHIFTIN2)
+ begin
+ casex (sel5_6)
+ 4'b1000: data6 <= # MXR1 SHIFTIN2;
+ 4'b1010: data6 <= # MXR1 d6r;
+ 4'b1001: data6 <= # MXR1 SHIFTIN1;
+ 4'b1011: data6 <= # MXR1 d6r;
+ 4'b1100: data6 <= # MXR1 1'b0;
+ 4'b1110: data6 <= # MXR1 d6r;
+ 4'b1101: data6 <= # MXR1 1'b0;
+ 4'b1111: data6 <= # MXR1 d6r;
+ default: data6 <= # MXR1 SHIFTIN2;
+ endcase
+ end
+
+
+
+
+// instantiate programmable load generator
+plg_oserdese1_vlog ldgen (.c23(c23), .c45(c45), .c67(c67), .sel(sel),
+ .clk(C), .clkdiv(CLKDIV), .rst(SR),
+ .load(loadint), .IOCLK_GLITCH(IOCLK_GLITCH));
+
+// Set value of counter in programmable load generator
+always @ (plgcnt or c23 or c45 or c67 or sel)
+begin
+ casex (plgcnt)
+ 5'b00100: begin c23=1'b0; c45=1'b0; c67=1'b0; sel=2'b00; end
+ 5'b00110: begin c23=1'b1; c45=1'b0; c67=1'b0; sel=2'b00; end
+ 5'b01000: begin c23=1'b0; c45=1'b0; c67=1'b0; sel=2'b01; end
+ 5'b01010: begin c23=1'b0; c45=1'b1; c67=1'b0; sel=2'b01; end
+ 5'b10010: begin c23=1'b0; c45=1'b0; c67=1'b0; sel=2'b00; end
+ 5'b10011: begin c23=1'b1; c45=1'b0; c67=1'b0; sel=2'b00; end
+ 5'b10100: begin c23=1'b0; c45=1'b0; c67=1'b0; sel=2'b01; end
+ 5'b10101: begin c23=1'b0; c45=1'b1; c67=1'b0; sel=2'b01; end
+ 5'b10110: begin c23=1'b0; c45=1'b0; c67=1'b0; sel=2'b10; end
+ 5'b10111: begin c23=1'b0; c45=1'b0; c67=1'b1; sel=2'b10; end
+ 5'b11000: begin c23=1'b0; c45=1'b0; c67=1'b0; sel=2'b11; end
+ default: $display("DATA_WIDTH %b and DATA_RATE_OQ %b at %t is an illegal value", DATA_WIDTH, DATA_RATE_OQ, $time);
+ endcase
+end
+
+endmodule
+`timescale 1ps/1ps
+//////////////////////////////////////////////////////////
+//
+// module trif_oserdese1_vlog
+//
+/////////////////////////////////////////////////////////
+//
+// Inputs:
+//
+// T1, T2, T3, T4: tristate inputs
+// load: Programmable load generator output
+// TCE: Tristate clock enable
+// SR: Set/Reset control. For the last 3 flops in TQ
+// (qt1, qt2 and qt2n) this function is
+// controlled bythe attributes SRVAL_TQ. In SERDES mode,
+// SR is a RESET ONLY for all other flops! The flops will
+// still be RESET even if SR is programmed to a SET!
+// C, C2: High speed clocks
+// C2 drives 2nd latch and C3 (inverse of C2) drives
+// 3rd latch in output section
+// CLKDIV: Low speed clock
+//
+//
+//
+//
+// Outputs:
+//
+// TQ: Output of tristate mux
+//
+//
+// Programmable Options:
+//
+// DATA_RATE_TQ: 2-bit field for types of operaiton
+// 0 (buf from T1), 1 (registered output from T1), 2 (ddr)
+// TRISTATE_WIDTH: 2-bit field for input width
+// 0 (width 1), 1 (width 2), 2 (width 4)
+// INIT_TQ: Init TQ output (0,1)
+// SRVAL_TQ: This bit to controls value of SR input.
+// Only the last 3 flops (qt1, qt2 and qt2n) are
+// affected by this bit.For SERDES mode, this bit
+// should be set to '0' making SR a reset. This is the
+// desired state since all other flops only
+// respond to this pin as a reset. Their function
+// cannot be changed. SR is 'O' for SET and '1' for RESET.
+//
+//
+// Programmable Test Options:
+// SRTYPE: Control S and R as asynchronous (0) or synchronous (1)
+// 2-bit value. 1st bit (msb) controls the 4 input flops
+// and the 2nd bit (lsb) controls the "3 legacy flops"
+// DDR_CLK_EDGE: Same or opposite edge operation
+//
+//
+//
+////////////////////////////////////////////////////////////////////////////////
+//
+
+module trif_oserdese1_vlog (T1, T2, T3, T4, load,
+ C, CLKDIV, SR, TCE,
+ DATA_RATE_TQ, TRISTATE_WIDTH,
+ INIT_TQ, SRVAL_TQ,
+ data1, data2);
+
+input T1, T2, T3, T4, load;
+
+input C, CLKDIV, SR, TCE;
+
+input [1:0] TRISTATE_WIDTH;
+
+input [1:0] DATA_RATE_TQ;
+
+input INIT_TQ, SRVAL_TQ;
+
+output data1, data2;
+
+wire DDR_CLK_EDGE;
+wire [3:0] INIT_TRANK1;
+wire [1:0] SRTYPE;
+assign SRTYPE = 2'b11;
+assign DDR_CLK_EDGE = 1'b1;
+assign INIT_TRANK1 = 4'b0000;
+
+reg t1r, t2r, t3r, t4r;
+
+reg qt1, qt2, qt2n;
+
+reg data1, data2;
+
+reg sdata_edge, odata_edge, ddr_data;
+
+wire C2p, C3;
+
+wire load;
+
+wire [6:0] tqsel;
+
+wire [4:0] sel;
+
+assign sel = {load,DATA_RATE_TQ,TRISTATE_WIDTH};
+
+
+
+
+
+//////////////////////////////////////////////////
+
+
+// Parameters for gate delays
+parameter ffd = 1;
+parameter mxd = 1;
+
+
+/////////////////////////////
+// Initialization of Flops
+////////////////////////////
+
+tri0 GSR = glbl.GSR;
+
+always @(GSR)
+begin
+ if (GSR)
+ begin
+ force t1r = INIT_TRANK1[0];
+ force t2r = INIT_TRANK1[1];
+ force t3r = INIT_TRANK1[2];
+ force t4r = INIT_TRANK1[3];
+
+ end
+ else
+ begin
+ release t1r;
+ release t2r;
+ release t3r;
+ release t4r;
+ end
+end
+
+
+
+
+// First rank of flops
+// asynchronous reset operation
+always @ (posedge CLKDIV or posedge SR)
+begin
+ begin
+ if (SR & !SRTYPE[1])
+ begin
+ t1r <= # ffd 1'b0;
+ t2r <= # ffd 1'b0;
+ t3r <= # ffd 1'b0;
+ t4r <= # ffd 1'b0;
+ end
+ else if (!SRTYPE[1])
+ begin
+ t1r <= # ffd T1;
+ t2r <= # ffd T2;
+ t3r <= # ffd T3;
+ t4r <= # ffd T4;
+ end
+ end
+end
+
+// synchronous reset operation
+always @ (posedge CLKDIV)
+begin
+ begin
+ if (SR & SRTYPE[1])
+ begin
+ t1r <= # ffd 1'b0;
+ t2r <= # ffd 1'b0;
+ t3r <= # ffd 1'b0;
+ t4r <= # ffd 1'b0;
+ end
+ else if (SRTYPE[1])
+ begin
+ t1r <= # ffd T1;
+ t2r <= # ffd T2;
+ t3r <= # ffd T3;
+ t4r <= # ffd T4;
+ end
+ end
+end
+
+
+
+
+
+// Data Muxs for tristate otuput signals
+always @ (sel or T1 or t1r or t3r)
+ begin
+
+ casex (sel)
+ 5'b00000: data1 <= # mxd T1;
+ 5'b10000: data1 <= # mxd T1;
+ 5'bX0000: data1 <= # mxd T1;
+ 5'b00100: data1 <= # mxd T1;
+ 5'b10100: data1 <= # mxd T1;
+ 5'bX0100: data1 <= # mxd T1;
+ 5'b01001: data1 <= # mxd T1;
+ 5'b11001: data1 <= # mxd T1;
+ 5'b01010: data1 <= # mxd t3r;
+ 5'b11010: data1 <= # mxd t1r;
+// CR 551953 -- enabled TRISTATE_WIDTH to be 1 in DDR mode. No func change, but removed warnings
+ 5'b01000: ;
+ 5'b11000: ;
+ 5'bX1000: ;
+
+ default:
+ begin
+ $display("DATA_RATE_TQ %b and/or TRISTATE_WIDTH %b at time %t are not supported by OSERDES", DATA_RATE_TQ,TRISTATE_WIDTH,$time);
+ $display("1.sel= %b",sel);
+ end
+ endcase
+ end
+// For data 2, width of 1 is inserted as acceptable for buf and sdr
+// The capability exists in the device if the feature is added
+always @ (sel or T2 or t2r or t4r)
+ begin
+ casex (sel)
+ 5'b00000: data2 <= # mxd T2;
+ 5'b00100: data2 <= # mxd T2;
+ 5'b10000: data2 <= # mxd T2;
+ 5'b10100: data2 <= # mxd T2;
+ 5'bX0000: data2 <= # mxd T2;
+ 5'bX0100: data2 <= # mxd T2;
+ 5'b00X00: data2 <= # mxd T2;
+ 5'b10X00: data2 <= # mxd T2;
+ 5'bX0X00: data2 <= # mxd T2;
+ 5'b01001: data2 <= # mxd T2;
+ 5'b11001: data2 <= # mxd T2;
+ 5'bX1001: data2 <= # mxd T2;
+ 5'b01010: data2 <= # mxd t4r;
+ 5'b11010: data2 <= # mxd t2r;
+// CR 551953 -- enabled TRISTATE_WIDTH to be 1 in DDR mode. No func change, but removed warnings
+ 5'b01000: ;
+ 5'b11000: ;
+ 5'bX1000: ;
+
+ default:
+ begin
+ $display("DATA_RATE_TQ %b and/or TRISTATE_WIDTH %b at time %t are not supported by OSERDES", DATA_RATE_TQ,TRISTATE_WIDTH,$time);
+ $display("2.sel= %b",sel);
+ end
+ endcase
+ end
+
+
+endmodule
+`timescale 1ps/1ps
+//////////////////////////////////////////////////////////
+//
+// module txbuffer_oserdese1_vlog
+//
+/////////////////////////////////////////////////////////
+//
+// FIFO and Control circuit for OSERDES
+
+module txbuffer_oserdese1_vlog (iodelay_state, qmux1, qmux2, tmux1, tmux2,
+ d1, d2, t1, t2, trif,
+ WC, ODV, extra,
+ clk, clkdiv, bufo, bufop, rst,
+ ODELAY_USED, DDR3_DATA,
+ DDR3_MODE);
+
+input d1, d2, t1, t2;
+
+input trif;
+
+input WC, ODV;
+
+input rst;
+
+input clk, clkdiv, bufo, bufop;
+
+input ODELAY_USED, DDR3_DATA;
+
+input DDR3_MODE;
+
+output iodelay_state, extra;
+
+output qmux1, qmux2, tmux1, tmux2;
+
+wire WC_DELAY;
+assign WC_DELAY = 1'b0;
+
+wire rd_gap1;
+
+wire rst_bufo_p, rst_bufg_p;
+
+
+wire rst_bufo_rc, rst_bufg_wc, rst_cntr, rst_bufop_rc;
+
+wire [1:0] qwc, qrd;
+
+wire bufo_out;
+
+
+fifo_tdpipe_oserdese1_vlog data1 (.muxout(inv_qmux1), .din(~d1), .qwc(qwc), .qrd(qrd),
+ .rd_gap1(rd_gap1),
+ .bufg_clk(clk), .bufo_clk(bufo), .rst_bufo_p(rst_bufo_p), .rst_bufg_p(rst_bufg_p),
+ .DDR3_DATA(DDR3_DATA), .extra(extra), .ODV(ODV), .DDR3_MODE(DDR3_MODE)
+
+ );
+
+fifo_tdpipe_oserdese1_vlog data2 (.muxout(inv_qmux2), .din(~d2), .qwc(qwc), .qrd(qrd),
+ .rd_gap1(rd_gap1),
+ .bufg_clk(clk), .bufo_clk(bufo), .rst_bufo_p(rst_bufo_p), .rst_bufg_p(rst_bufg_p),
+ .DDR3_DATA(DDR3_DATA), .extra(extra), .ODV(ODV), .DDR3_MODE(DDR3_MODE)
+
+ );
+
+fifo_tdpipe_oserdese1_vlog tris1 (.muxout(inv_tmux1), .din(~t1), .qwc(qwc), .qrd(qrd),
+ .rd_gap1(rd_gap1),
+ .bufg_clk(clk), .bufo_clk(bufo), .rst_bufo_p(rst_bufo_p), .rst_bufg_p(rst_bufg_p),
+ .DDR3_DATA(DDR3_DATA), .extra(extra), .ODV(ODV), .DDR3_MODE(DDR3_MODE)
+
+ );
+
+fifo_tdpipe_oserdese1_vlog tris2 (.muxout(inv_tmux2), .din(~t2), .qwc(qwc), .qrd(qrd),
+ .rd_gap1(rd_gap1),
+ .bufg_clk(clk), .bufo_clk(bufo), .rst_bufo_p(rst_bufo_p), .rst_bufg_p(rst_bufg_p),
+ .DDR3_DATA(DDR3_DATA), .extra(extra), .ODV(ODV), .DDR3_MODE(DDR3_MODE)
+
+ );
+
+wire qmux1 = ~inv_qmux1;
+wire qmux2 = ~inv_qmux2;
+wire tmux1 = ~inv_tmux1;
+wire tmux2 = ~inv_tmux2;
+
+fifo_reset_oserdese1_vlog rstckt (.rst_bufo_p(rst_bufo_p), .rst_bufo_rc(rst_bufo_rc),
+ .rst_bufg_p(rst_bufg_p), .rst_bufg_wc(rst_bufg_wc),
+ .rst_cntr(rst_cntr),
+ .bufg_clk(clk), .bufo_clk(bufo), .clkdiv(clkdiv), .rst(rst),
+ .divide_2(WC_DELAY), .bufop_clk(bufop), .rst_bufop_rc(rst_bufop_rc)
+
+ );
+
+
+
+
+fifo_addr_oserdese1_vlog addcntr (.qwc(qwc), .qrd(qrd), .rd_gap1(rd_gap1), .rst_bufg_wc(rst_bufg_wc), .rst_bufo_rc(rst_bufo_rc), .bufg_clk(clk), .bufo_clk(bufo),
+ .data(DDR3_DATA), .extra(extra), .rst_bufop_rc(rst_bufop_rc), .bufop_clk(bufop)
+
+ );
+
+
+
+iodlyctrl_npre_oserdese1_vlog idlyctrl (.iodelay_state(iodelay_state), .bufo_out(bufo_out), .rst_cntr(rst_cntr),
+ .wc(WC), .trif(trif),
+ .rst(rst_bufg_p), .bufg_clk(clk), .bufo_clk(bufo), .bufg_clkdiv(clkdiv),
+ .ddr3_dimm(ODELAY_USED), .wl6(WC_DELAY)
+ );
+
+endmodule
+`timescale 1ps/1ps
+////////////////////////////////////////////////////////
+//
+// module fifo_tdpipe_oserdese1_vlog
+//
+////////////////////////////////////////////////////////
+
+// FIFO for write path
+
+module fifo_tdpipe_oserdese1_vlog (muxout, din, qwc, qrd,
+ rd_gap1,
+ bufg_clk, bufo_clk, rst_bufo_p, rst_bufg_p,
+ DDR3_DATA, extra, ODV, DDR3_MODE
+
+ );
+
+
+input din;
+
+input [1:0] qwc, qrd;
+
+input rd_gap1;
+
+input rst_bufo_p, rst_bufg_p;
+
+input bufg_clk, bufo_clk;
+
+input DDR3_DATA, ODV;
+
+input extra;
+
+input DDR3_MODE;
+
+output muxout;
+
+
+reg muxout;
+
+reg qout1, qout2;
+
+reg qout_int, qout_int2;
+
+reg [4:1] fifo;
+
+reg cin1;
+
+reg omux;
+
+wire [2:0] sel;
+
+reg pipe1, pipe2;
+
+wire selqoi, selqoi2;
+
+wire [2:0] selmuxout;
+
+
+
+
+
+
+// 4 flops that make up the basic FIFO. They are all clocked
+// off of fast BUFG. The first flop is the top flop in the chain.
+// The CE input is used to mux the inputs. If the flop is selected,
+// CE is high and it takes data from the output of the mux. If the
+// flop is not selected, it retains its data.
+
+always @ (posedge bufg_clk or posedge rst_bufg_p)
+ begin
+ if (rst_bufg_p)
+ begin
+ fifo <= #10 4'b0000;
+ end
+ else if (!qwc[1] & !qwc[0])
+ begin
+ fifo <= #10 {fifo[4:2],din};
+ end
+ else if (!qwc[1] & qwc[0])
+ begin
+ fifo <= #10 {fifo[4:3],din,fifo[1]};
+ end
+ else if (qwc[1] & qwc[0])
+ begin
+ fifo <= #10 {fifo[4],din,fifo[2:1]};
+ end
+ else if (qwc[1] & !qwc[0])
+ begin
+ fifo <= #10 {din,fifo[3:1]};
+ end
+ end
+
+
+
+// Capture stage top
+// This is the top flop of the "3 flops" for ODDR. This flop, along with the read
+// counter will be clocked off of bufo. A 4:1 mux wil decode the outputs of the
+// read counter and load the write data. A subsequent 2:1 mux will decode between
+// the fifo and the legacy operation
+
+
+// OMUX
+
+always @ (qrd or fifo)
+ begin
+ case (qrd)
+ 2'b00: omux <= #10 fifo[1];
+ 2'b01: omux <= #10 fifo[2];
+ 2'b10: omux <= #10 fifo[4];
+ 2'b11: omux <= #10 fifo[3];
+ default: omux <= #10 fifo[1];
+ endcase
+ end
+
+
+always @ (posedge bufo_clk or posedge rst_bufo_p)
+ begin
+ if (rst_bufo_p)
+ begin
+ qout_int <= #10 1'b0;
+ qout_int2 <= #10 1'b0;
+ end
+ else
+ begin
+ qout_int <= #10 omux;
+ qout_int2 <= #10 qout_int;
+ end
+ end
+
+assign #10 selqoi = ODV | rd_gap1;
+
+
+always @ (selqoi or qout_int or omux)
+ begin
+ case(selqoi)
+ 1'b0: qout1 <= #10 omux;
+ 1'b1: qout1 <= #10 qout_int;
+ default: qout1 <= #10 omux;
+ endcase
+ end
+
+assign #10 selqoi2 = ODV & rd_gap1;
+
+always @ (selqoi2 or qout_int2 or qout_int)
+ begin
+ case(selqoi2)
+ 1'b0: qout2 <= #10 qout_int;
+ 1'b1: qout2 <= #10 qout_int2;
+ default qout2 <= #10 qout_int;
+ endcase
+ end
+
+
+assign #14 selmuxout = {DDR3_MODE,DDR3_DATA,extra};
+
+
+always @ (selmuxout or din or omux or qout1 or qout2)
+ begin
+ case (selmuxout)
+ 3'b000: muxout = #1 din;
+ 3'b001: muxout = #1 din;
+ 3'b010: muxout = #1 din;
+ 3'b011: muxout = #1 din;
+ 3'b100: muxout = #1 omux;
+ 3'b101: muxout = #1 omux;
+ 3'b110: muxout = #1 qout1;
+ 3'b111: muxout = #1 qout2;
+ default: muxout = #10 din;
+ endcase
+ end
+
+
+
+endmodule
+`timescale 1ps/1ps
+////////////////////////////////////////////////////////
+//
+// module fifo_reset_oserdese1_vlog
+//
+////////////////////////////////////////////////////////
+//
+// TX FIFO reset
+//
+// This design performs 2 functions. One function is to reset all the
+// flops in the TX FIFO. The other function is to respond to the signal
+// rst_cntr. This signal comes from iodlyctrl and will be used to initiate an
+// orderly transition to switch the DQ/DQS I/O from and read to a write.
+// This process is required only for DDR3 DIMM support because the IODELAY
+// is used for both the inputs and the outputs. The signal from the
+// squelch circuit is a present fabric output. An additional input
+// indicating that a write command was issued will be
+// required for all I/O to support this signal.
+//
+// This design uses an asynchronous reset to reset all flops. After the
+// reset is disabled, a 0 is propagated through the pipe stages to terminate
+// the reset. The first 2 flops run off of the clkdiv domain. Their output
+// feeds a latch to cross between the clkdiv and bufg_clk domain. The pipe
+// stage for the bufg_clk domain is 3 deep, where the last flop is the
+// reset signal for the bufg_clk domain. The 2nd flop of the bufg_clk pipe
+// is fed to 2 flops that are in the bufo_clk domain. The 2 flops are
+// to resolve metastability between the 2 clock domains.
+//
+// The circuit to enable an orderly transition from read to write uses the
+// PREAMBLE_SYNCHED output of a portion of the squelch circuit. This pulse
+// will initiate the reset sequence and also generate an enable which will
+// switch the IODELAY from an IDELAY to an ODELAY. Timing is as specified in
+// the "State of the Union" presentation.
+//
+//
+
+
+module fifo_reset_oserdese1_vlog (rst_bufo_p, rst_bufo_rc,
+ rst_bufg_p, rst_bufg_wc,
+ rst_cntr,
+ bufg_clk, bufo_clk, clkdiv, rst,
+ divide_2, bufop_clk, rst_bufop_rc
+
+ );
+
+
+input rst_cntr;
+
+input rst;
+
+input bufg_clk, bufo_clk, clkdiv;
+
+input bufop_clk;
+
+
+// Memory cell input to support divide by 1 operation
+input divide_2;
+
+
+output rst_bufo_p, rst_bufo_rc;
+output rst_bufg_p, rst_bufg_wc;
+
+output rst_bufop_rc;
+
+
+reg [1:0] clkdiv_pipe;
+
+reg bufg_pipe;
+
+reg rst_cntr_reg;
+
+reg [2:0] bufo_rst_p, bufo_rst_rc;
+
+reg [1:0] bufop_rst_rc;
+
+reg [1:0] bufg_rst_p, bufg_rst_wc;
+
+wire bufg_clkdiv_latch, ltint1, ltint2, ltint3;
+
+wire latch_in;
+
+
+
+
+
+
+
+// 2 stage pipe for clkdiv domain to allow user to properly
+// time everything
+
+
+always @ (posedge bufg_clk or posedge rst)
+ begin
+ if (rst)
+ begin
+ rst_cntr_reg <= #10 1'b0;
+ end
+ else
+ begin
+ rst_cntr_reg <= #10 rst_cntr;
+ end
+ end
+
+
+always @ (posedge clkdiv or posedge rst)
+ begin
+ if (rst)
+ begin
+ clkdiv_pipe <= #10 2'b11;
+ end
+ else
+ begin
+ clkdiv_pipe <= #10 {clkdiv_pipe[0],1'b0};
+ end
+ end
+
+// Latch to compensate for clkdiv and bufg_clk clock skew
+// Built of actual gates
+
+assign #1 latch_in = clkdiv_pipe[1];
+
+assign #1 bufg_clkdiv_latch = !(ltint1 && ltint3);
+assign #1 ltint1 = !(latch_in && bufg_clk);
+assign #1 ltint2 = !(ltint1 && bufg_clk);
+assign #1 ltint3 = !(bufg_clkdiv_latch && ltint2);
+
+
+
+
+
+// BUFG flop to register latch signal
+always @ (posedge bufg_clk or posedge rst)
+ begin
+ if (rst)
+ begin
+ bufg_pipe <= #10 1'b1;
+ end
+ else
+ begin
+ bufg_pipe <= #10 bufg_clkdiv_latch;
+ end
+ end
+
+
+
+
+// BUFG clock domain resests
+
+always @ (posedge bufg_clk or posedge rst)
+ begin
+ if (rst)
+ begin
+ bufg_rst_p <= #10 2'b11;
+ end
+ else
+ begin
+ bufg_rst_p <= #10 {bufg_rst_p[0],bufg_pipe};
+ end
+ end
+
+
+always @ (posedge bufg_clk or posedge rst_cntr or posedge rst)
+ begin
+ if (rst || rst_cntr)
+ begin
+ bufg_rst_wc <= #10 2'b11;
+ end
+ else
+ begin
+ bufg_rst_wc <= #10 {bufg_rst_wc[0],bufg_pipe};
+ end
+ end
+
+
+
+// BUFO clock domain Resets
+always @ (posedge bufo_clk or posedge rst)
+ begin
+ if (rst)
+ begin
+ bufo_rst_p <= #10 3'b111;
+ end
+ else
+ begin
+ bufo_rst_p <= #10 {bufo_rst_p[1:0],bufg_pipe};
+ end
+ end
+
+always @ (posedge bufo_clk or posedge rst or posedge rst_cntr)
+ begin
+ if (rst || rst_cntr)
+ begin
+ bufo_rst_rc <= #10 3'b111;
+ end
+ else
+ begin
+ bufo_rst_rc <= #10 {bufo_rst_rc[1:0],bufg_pipe};
+ end
+ end
+
+
+
+always @ (posedge bufop_clk or posedge rst or posedge rst_cntr)
+ begin
+ if (rst || rst_cntr)
+ begin
+ bufop_rst_rc <= #10 2'b11;
+ end
+ else
+ begin
+ bufop_rst_rc <= #10 {bufop_rst_rc[0],bufg_pipe};
+ end
+ end
+
+
+// final reset assignments
+assign rst_bufo_rc = bufo_rst_rc[1];
+
+assign rst_bufo_p = bufo_rst_p[1];
+
+assign rst_bufop_rc = bufop_rst_rc[1];
+
+assign rst_bufg_wc = bufg_rst_wc[1];
+
+assign rst_bufg_p = bufg_rst_p[1];
+
+
+endmodule
+`timescale 1ps/1ps
+////////////////////////////////////////////////////////
+//
+// module fifo_addr_oserdese1_vlog
+//
+////////////////////////////////////////////////////////
+// Read and Write address generators for TX FIFO
+//
+// This circuit contains 2 greycode read and write address generators
+// that will be used with the TX FIFO. Both counters generate a
+// count sequence of 00 -> 01 -> 11 -> 10 -> 00.
+
+
+
+module fifo_addr_oserdese1_vlog (qwc, qrd, rd_gap1, rst_bufg_wc, rst_bufo_rc, bufg_clk, bufo_clk,
+ data, extra, rst_bufop_rc, bufop_clk
+
+ );
+
+
+input bufg_clk, bufo_clk;
+
+input rst_bufo_rc, rst_bufg_wc;
+
+input rst_bufop_rc;
+
+input data; // mc to tell if I/O is DDR3 DQ or DQS
+
+input bufop_clk;
+
+output [1:0]qwc, qrd; // Scalar port ``qwc'' has a vectored net declaration [1:0]
+
+output rd_gap1, extra;
+
+
+
+
+reg [1:0] qwc; // unisims/OSERDESE1.v:2073 error: Scalar port ``qwc'' has a vectored net declaration [1:0]
+
+reg [1:0] qrd; // unisims/OSERDESE1.v:2075: error: Scalar port ``qrd'' has a vectored net declaration [1:0]
+
+
+reg stop_rd, rd_gap1, extra;
+
+reg rd_cor, rd_cor_cnt, rd_cor_cnt1;
+
+
+wire qwc0_latch, qwc1_latch;
+
+wire li01, li02, li03;
+
+wire li11, li12, li13;
+
+
+wire qwc0_latchn, qwc1_latchn;
+
+wire li01n, li02n, li03n;
+
+wire li11n, li12n, li13n;
+
+
+reg stop_rdn, rd_cor_cntn, rd_cor_cnt1n, stop_rc;
+
+
+
+
+reg [1:0] qwcd;
+
+reg [1:0] qrdd;
+
+
+reg stop_rdd, rd_gap1d, extrad;
+
+reg rd_cord, rd_cor_cntd, rd_cor_cnt1d;
+
+
+wire qwcd0_latch, qwcd1_latch;
+
+wire li01d, li02d, li03d;
+
+wire li11d, li12d, li13d;
+
+
+
+// Write counter
+// The write counter uses 2 flops to create the grey code pattern of
+// 00 -> 01 -> 11 -> 10 -> 00. The write counter is initialized
+// to 11 and the read counter will be initialized to 00. This gives
+// a basic 2 clock separation to compensate for the phase differences.
+// The write counter is clocked off of the bufg clock
+
+always @ (posedge bufg_clk or posedge rst_bufg_wc)
+ begin
+ if (rst_bufg_wc)
+ begin
+ qwc <= # 10 2'b11;
+ end
+ else if (qwc[1] ^ qwc[0])
+ begin
+ qwc[1] <= # 10 ~qwc[1];
+ qwc[0] <= # 10 qwc[0];
+ end
+ else
+ begin
+ qwc[1] <= # 10 qwc[1];
+ qwc[0] <= # 10 ~qwc[0];
+ end
+ end
+
+
+
+
+
+
+// Read counter
+// The read counter uses 2 flops to create the grey code pattern of
+// 00 -> 01 -> 11 -> 10 -> 00. The read counter is initialized
+// to 00 and the write counter will be initialized to 11. This gives
+// a basic 2 clock separation to compensate for the phase differences.
+// The read counter is clocked off of the bufo clock
+
+always @ (posedge bufo_clk or posedge rst_bufo_rc)
+
+ begin
+ if (rst_bufo_rc)
+ begin
+ qrd <= # 10 2'b00;
+ end
+ else if (stop_rd && !data)
+ begin
+ qrd <= #10 qrd;
+ end
+ else if (qrd[1] ^ qrd[0])
+ begin
+ qrd[1] <= # 10 ~qrd[1];
+ qrd[0] <= # 10 qrd[0];
+ end
+ else
+ begin
+ qrd[1] <= # 10 qrd[1];
+ qrd[0] <= # 10 ~qrd[0];
+ end
+ end
+
+always @ (posedge bufo_clk or posedge rst_bufo_rc)
+
+ begin
+ if (rst_bufo_rc)
+ begin
+ rd_gap1 <= # 10 1'b0;
+ end
+// else if ((qwc1_latch && qwc0_latch) && (qrd[0] ^ qrd[1]))
+ else if ((qwc1_latch && qwc0_latch) && (qrd[0]))
+ begin
+ rd_gap1 <= # 10 1'b1;
+ end
+ else
+ begin
+ rd_gap1 <= # 10 rd_gap1;
+ end
+ end
+
+
+
+
+
+// Looking for 11
+
+assign #1 qwc0_latch = !(li01 & li03);
+assign #1 li01 = !(qwc[0] & bufo_clk);
+assign #1 li02 = !(li01 & bufo_clk);
+assign #1 li03 = !(qwc0_latch & li02);
+
+
+assign #1 qwc1_latch = !(li11 & li13);
+assign #1 li11 = !(qwc[1] & bufo_clk);
+assign #1 li12 = !(li11 & bufo_clk);
+assign #1 li13 = !(qwc1_latch & li12);
+
+
+// The following counter is to match the control counter to see if the
+// read counter did a hold after reset. This knowledge will enable the
+// computation of the 'extra' output. This in turn can add the
+// proper number of pipe stages to the output. The circuit must use
+// the output of BUFO and not be modified by ODELAY. This is because
+// the control pins PP clock was not modified by BUFO. If the
+// control pins PP clock was modified by BUFO, the reset must be done
+// with this in mind.
+
+// Read counter
+// The read counter uses 2 flops to create the grey code pattern of
+// 00 -> 01 -> 11 -> 10 -> 00. The read counter is initialized
+// to 00 and the write counter will be initialized to 11. This gives
+// a basic 2 clock separation to compensate for the phase differences.
+// The read counter is clocked off of the bufo clock
+
+always @ (posedge bufop_clk or posedge rst_bufop_rc)
+
+ begin
+ if (rst_bufop_rc)
+ begin
+ qrdd <= # 10 2'b00;
+ end
+ else if (qrdd[1] ^ qrdd[0])
+ begin
+ qrdd[1] <= # 10 ~qrdd[1];
+ qrdd[0] <= # 10 qrdd[0];
+ end
+ else
+ begin
+ qrdd[1] <= # 10 qrdd[1];
+ qrdd[0] <= # 10 ~qrdd[0];
+ end
+ end
+
+
+
+// Looking for 11
+
+assign #1 qwcd0_latch = !(li01d & li03d);
+assign #1 li01d = !(qwc[0] & bufop_clk);
+assign #1 li02d = !(li01d & bufop_clk);
+assign #1 li03d = !(qwcd0_latch & li02d);
+
+
+assign #1 qwcd1_latch = !(li11d & li13d);
+assign #1 li11d = !(qwc[1] & bufop_clk);
+assign #1 li12d = !(li11d & bufop_clk);
+assign #1 li13d = !(qwcd1_latch & li12d);
+
+
+
+// Circuit to fix read address counters in non data pins
+always @ (posedge bufop_clk or posedge rst_bufo_rc)
+
+ begin
+ if (rst_bufop_rc)
+ begin
+ stop_rd <= # 10 1'b0;
+ rd_cor_cnt <= #10 1'b0;
+ rd_cor_cnt1 <= #10 1'b0;
+ end
+ else if (((qwcd1_latch && qwcd0_latch) && (qrdd[0] ^ qrdd[1]) && !rd_cor_cnt1))
+ begin
+ stop_rd <= #10 1'b1;
+ rd_cor_cnt <= #10 1'b1;
+ rd_cor_cnt1 <= #10 rd_cor_cnt;
+ end
+ else
+ begin
+ stop_rd <= #10 1'b0;
+ rd_cor_cnt <= #10 1'b1;
+ rd_cor_cnt1 <= #10 rd_cor_cnt;
+ end
+ end
+
+// Circuit to inform data if control counters habe been fixed
+
+always @ (posedge bufop_clk or posedge rst_bufop_rc)
+ begin
+ if (rst_bufop_rc)
+ begin
+ extra <= #10 1'b0;
+ end
+ else if (stop_rd)
+ begin
+ extra <= #10 1'b1;
+ end
+ end
+
+endmodule
+`timescale 1ps/1ps
+////////////////////////////////////////////////////////
+//
+// module iodlyctrl_npre_oserdese1_vlog
+//
+////////////////////////////////////////////////////////
+//
+// Circuit to automatically switch IODELAY from IDELAY to ODELAY using knowledge
+// of write command. This circuit forces the user to wait 3 extra CLK/CLK# cycles
+// when performing a read to write turnaround. The JEDEC DDR3 spec states that
+// the turnaround can be done in 2 clock cycles. This circuit requires 5 clock
+// cycles.
+// This circuit is only used for a DDR3 appplication that uses DIMMs
+
+
+
+module iodlyctrl_npre_oserdese1_vlog (iodelay_state, bufo_out, rst_cntr,
+ wc, trif,
+ rst, bufg_clk, bufo_clk, bufg_clkdiv,
+ ddr3_dimm, wl6
+ );
+
+
+input wc;
+
+input trif;
+
+input rst;
+
+input bufo_clk, bufg_clk, bufg_clkdiv;
+
+input ddr3_dimm, wl6;
+
+output iodelay_state, rst_cntr;
+
+output bufo_out;
+
+
+reg qw0cd, qw1cd;
+
+reg turn, turn_p1;
+
+reg rst_cntr;
+
+reg w_to_w;
+
+reg [2:0] wtw_cntr;
+
+reg cmd0, cmd0_n6, cmd0_6, cmd1;
+
+
+
+
+wire wr_cmd0;
+
+wire lt0int1, lt0int2, lt0int3;
+
+wire lt1int1, lt1int2, lt1int3;
+
+wire latch_in;
+
+reg qwcd;
+
+
+
+
+
+assign bufo_out = bufo_clk;
+
+
+// create turn signal for IODELAY
+assign iodelay_state = (trif && ~w_to_w) & ((~turn && ~turn_p1) || ~ddr3_dimm);
+
+
+
+// Registers to detect write command
+
+// Registers using bufg clkdiv
+always @ (posedge bufg_clkdiv)
+begin
+ if (rst)
+ begin
+ qwcd <= #10 0;
+ end
+ else
+ begin
+ qwcd <= #10 wc;
+ end
+end
+
+
+
+// Latch to allow skew between CLK and CLKDIV from BUFGs
+assign #1 wr_cmd0 = !(lt0int1 && lt0int3);
+assign #1 lt0int1 = !(qwcd && bufg_clk);
+assign #1 lt0int2 = !(lt0int1 && bufg_clk);
+assign #1 lt0int3 = !(wr_cmd0 && lt0int2);
+
+always @ (posedge bufg_clk)
+ begin
+ if (rst)
+ begin
+ cmd0_n6 <= #10 1'b0;
+ cmd0_6 <= #10 1'b0;
+ end
+ else
+ begin
+ cmd0_n6 <= #10 wr_cmd0;
+ cmd0_6 <= #10 cmd0_n6;
+ end
+ end
+
+
+
+// mux to add extra pipe stage for WL = 6
+always @ (cmd0_n6 or wl6 or cmd0_6)
+ begin
+ case (wl6)
+ 1'b0: cmd0 <= #10 cmd0_n6;
+ 1'b1: cmd0 <= #10 cmd0_6;
+ default: cmd0 <= #10 cmd0_n6;
+ endcase
+ end
+
+
+// Turn IODELAY and reset FIFO read/write counters
+//always @ (posedge bufg_clk)
+// begin
+// if (rst)
+//
+// begin
+// turn <= #10 1'b0;
+// rst_cntr <= #10 1'b0;
+// end
+// else if (w_to_w)
+// begin
+// turn <= #10 1'b1;
+// rst_cntr <= #10 1'b0;
+// end
+// else if (cmd0 && !turn)
+// begin
+// turn <= #10 1'b1;
+// rst_cntr <= #10 1'b1;
+// end
+// else if (~trif)
+// begin
+// turn <= #10 1'b0;
+// rst_cntr <= #10 1'b0;
+// end
+// else if (turn)
+// begin
+// turn <= #10 1'b1;
+// rst_cntr <= #10 1'b0;
+// end
+// else
+// begin
+// turn <= #10 1'b0;
+// rst_cntr <= #10 1'b0;
+// end
+// end
+
+
+
+always @ (posedge bufg_clk)
+begin
+ begin
+ if (rst)
+ begin
+ turn <= #10 1'b0;
+ end
+ else
+ begin
+ turn <= #10 (w_to_w || (cmd0 && ~turn) ||
+ (~wtw_cntr[2] && turn));
+ end
+
+ end
+
+ begin
+ if (rst)
+ begin
+ rst_cntr <= #10 1'b0;
+ end
+ else
+ begin
+ rst_cntr <= #10 (~w_to_w && (cmd0 && ~turn));
+ end
+ end
+end
+
+
+
+
+always @ (posedge bufg_clk)
+ begin
+ if (rst)
+ begin
+ turn_p1 <= #10 1'b0;
+ end
+ else
+ begin
+ turn_p1 <= #10 turn;
+ end
+ end
+
+
+
+
+// Detect multiple write commands and don"t turn IODELAY
+//always @ (posedge bufg_clk)
+// begin
+// if (rst)
+// begin
+// w_to_w <= #10 1'b0;
+// wtw_cntr <= #10 3'b000;
+// end
+// else if (cmd0 && turn_p1)
+// begin
+// w_to_w <= #10 1'b1;
+// wtw_cntr <= #10 3'b000;
+// end
+// else if (wtw_cntr == 3'b101)
+// begin
+// w_to_w <= #10 1'b0;
+// wtw_cntr <= #10 3'b000;
+// end
+// else if (w_to_w)
+// begin
+// w_to_w <= #10 1'b1;
+// wtw_cntr <= #10 wtw_cntr + 1;
+// end
+// end
+
+
+always @ (posedge bufg_clk)
+begin
+ begin
+ if (rst)
+ begin
+ w_to_w <= #10 1'b0;
+ end
+ else
+ begin
+ w_to_w <= #10 ((cmd0 && turn_p1) ||
+ (w_to_w && (~wtw_cntr[2] || ~wtw_cntr[1])));
+ end
+ end
+end
+
+
+always @ (posedge bufg_clk)
+
+ begin
+ if (!(w_to_w || turn) || (cmd0 && turn_p1))
+ begin
+ wtw_cntr <= #10 3'b000;
+ end
+ else if (w_to_w || turn_p1)
+ begin
+ wtw_cntr <= #10 wtw_cntr + 1;
+ end
+ end
+
+endmodule
+`timescale 1ps/1ps
+////////////////////////////////////////////////////////
+//
+// MODULE dout_oserdese1_vlog
+//
+// This model ONLY works for SERDES operation!!
+// Does not include tristate circuit
+//
+/////////////////////////////////////////////////////////
+//
+// Inputs:
+// data1: Data from FIFO
+// data2: Data input FIFO
+// CLK: High speed clock from DCM
+// BUFO: Clock from performance path
+// OCE: Clock enable for output data flops
+// SR: Set/Reset control. For the last 3 flops in OQ
+// (d1rnk2, d2rnk2 and d2nrnk2) this function is
+// controlled bythe attributes SRVAL_OQ. In SERDES mode,
+// SR is a RESET ONLY for all other flops! The flops will
+// still be RESET even if SR is programmed to a SET!
+//
+//
+//
+// Outputs:
+// OQ: Data output
+//
+//
+//
+// Programmable Points
+// DATA_RATE_OQ: Rate control for data output, 1-bit
+// sdr (1), ddr (0)
+// INIT_OQ: Init OQ output "flop"
+// SRVAL_OQ: This bit to controls value of SR input.
+// Only the last 3 flops (d1rnk2, d2rnk2 and d2nrnk2)
+// are affected by this bit.For SERDES mode, this bit
+// should be set to '0' making SR a reset. This is the
+// desired state since all other flops only respond to
+// this pin as a reset. Their function cannot be
+// changed. SR is '1' for SET and '0' for RESET.
+//
+//
+//
+// Programmable points for Test model
+// SRTYPE: This is a 4-bit field Sets asynchronous (0) or synchronous (1) set/reset
+// 1st bit (msb) sets rank1 flops, 2nd bit sets 4 flops in rank 2,
+// 3rd bit sets "3 legacy flops, and 4th (lsb) bit sets the counter
+// DDR_CLK_EDGE: Controls use of 2 or 3 flops for single case. Default to 1 for
+// SERDES operation
+//
+//
+///////////////////////////////////////////////////////////////////////////////
+//
+
+module dout_oserdese1_vlog (data1, data2,
+ CLK, BUFO, SR, OCE,
+ OQ, d2rnk2,
+ DATA_RATE_OQ,
+ INIT_OQ, SRVAL_OQ,
+ DDR3_MODE);
+
+input data1, data2;
+
+input CLK, SR, OCE;
+
+input BUFO;
+
+input INIT_OQ, SRVAL_OQ;
+
+input DDR3_MODE;
+
+output OQ;
+
+output d2rnk2;
+
+
+// Programmable Points
+
+input DATA_RATE_OQ;
+
+wire DDR_CLK_EDGE;
+wire [3:0] SRTYPE;
+assign DDR_CLK_EDGE = 1'b1;
+assign SRTYPE = 4'b1111;
+reg d1rnk2, d2rnk2, d2nrnk2;
+
+reg OQ;
+
+reg ddr_data, odata_edge, sdata_edge;
+
+reg c23, c45, c67;
+
+wire C;
+
+wire C2p, C3;
+
+wire [3:0] seloq;
+
+wire oqsr, oqrev;
+
+assign C = (BUFO & DDR3_MODE) | (CLK & !DDR3_MODE);
+
+assign C2p = (C & DDR_CLK_EDGE) | (!C & !DDR_CLK_EDGE);
+
+assign C3 = !C2p;
+
+assign seloq = {OCE,DATA_RATE_OQ,oqsr,oqrev};
+
+assign oqsr = !SRTYPE[1] & SR & !SRVAL_OQ;
+
+assign oqrev = !SRTYPE[1] & SR & SRVAL_OQ;
+
+
+
+//////////////////////////////////////////////////
+// Delay values
+//
+parameter FFD = 1; // clock to out delay for flip flops
+// driven by clk
+parameter FFCD = 1; // clock to out delay for flip flops
+// driven by clkdiv
+parameter MXD = 1; // 60 ps mux delay
+
+parameter MXR1 = 1;
+
+////////////////////////////////////////////
+// Initialization of flops with GSR for test model
+///////////////////////////////////////////
+
+tri0 GSR = glbl.GSR;
+
+always @(GSR)
+begin
+ if (GSR)
+ begin
+ assign OQ = INIT_OQ;
+ assign d1rnk2 = INIT_OQ;
+ assign d2rnk2 = INIT_OQ;
+ assign d2nrnk2 = INIT_OQ;
+ end
+ else
+ begin
+ deassign OQ;
+ deassign d1rnk2;
+ deassign d2rnk2;
+ deassign d2nrnk2;
+ end
+end
+
+/////////////////////////////////////////
+
+
+
+
+
+
+/////////////////////////////////////////
+// 3 flops to create DDR operations of 4 latches
+////////////////////////////////////////
+
+// Representation of top latch
+// asynchronous operation
+always @ (posedge C or posedge SR)
+begin
+ begin
+ if (SR & !SRVAL_OQ & !SRTYPE[1])
+ begin
+ d1rnk2 <= # FFD 1'b0;
+ end
+ else if (SR & SRVAL_OQ & !SRTYPE[1])
+ begin
+ d1rnk2 <= # FFD 1'b1;
+ end
+ else if (!OCE & !SRTYPE[1])
+ begin
+ d1rnk2 <= # FFD OQ;
+ end
+ else if (!SRTYPE[1])
+ begin
+ d1rnk2 <= # FFD data1;
+ end
+ end
+end
+
+// synchronous operation
+always @ (posedge C)
+begin
+ begin
+
+ if (SR & !SRVAL_OQ & SRTYPE[1])
+ begin
+ d1rnk2 <= # FFD 1'b0;
+ end
+ else if (SR & SRVAL_OQ & SRTYPE[1])
+ begin
+ d1rnk2 <= # FFD 1'b1;
+ end
+ else if (!OCE & SRTYPE[1])
+ begin
+ d1rnk2 <= # FFD OQ;
+ end
+ else if (SRTYPE[1])
+ begin
+ d1rnk2 <= # FFD data1;
+ end
+ end
+end
+
+
+
+
+// Representation of 2nd latch
+// asynchronous operation
+always @ (posedge C2p or posedge SR)
+begin
+ begin
+ if (SR & !SRVAL_OQ & !SRTYPE[1])
+ begin
+ d2rnk2 <= # FFD 1'b0;
+ end
+ else if (SR & SRVAL_OQ & !SRTYPE[1])
+ begin
+ d2rnk2 <= # FFD 1'b1;
+ end
+ else if (!OCE & !SRTYPE[1])
+ begin
+ d2rnk2 <= # FFD OQ;
+ end
+ else if (!SRTYPE[1])
+ begin
+ d2rnk2 <= # FFD data2;
+ end
+ end
+end
+
+// synchronous operation
+always @ (posedge C2p)
+begin
+ begin
+
+ if (SR & !SRVAL_OQ & SRTYPE[1])
+ begin
+ d2rnk2 <= # FFD 1'b0;
+ end
+ else if (SR & SRVAL_OQ & SRTYPE[1])
+ begin
+ d2rnk2 <= # FFD 1'b1;
+ end
+ else if (!OCE & SRTYPE[1])
+ begin
+ d2rnk2 <= # FFD OQ;
+ end
+ else if (SRTYPE[1])
+ begin
+ d2rnk2 <= # FFD data2;
+ end
+ end
+end
+
+
+
+
+// Representation of 3rd flop ( latch and output latch)
+// asynchronous operation
+always @ (posedge C3 or posedge SR)
+begin
+ begin
+ if (SR & !SRVAL_OQ & !SRTYPE[1])
+ begin
+ d2nrnk2 <= # FFD 1'b0;
+ end
+ else if (SR & SRVAL_OQ & !SRTYPE[1])
+ begin
+ d2nrnk2 <= # FFD 1'b1;
+ end
+ else if (!OCE & !SRTYPE[1])
+ begin
+ d2nrnk2 <= # FFD OQ;
+ end
+ else if (!SRTYPE[1])
+ begin
+ d2nrnk2 <= # FFD d2rnk2;
+ end
+ end
+end
+
+// synchronous operation
+always @ (posedge C3)
+begin
+
+ begin
+ if (SR & !SRVAL_OQ & SRTYPE[1])
+ begin
+ d2nrnk2 <= # FFD 1'b0;
+ end
+ else if (SR & SRVAL_OQ & SRTYPE[1])
+ begin
+ d2nrnk2 <= # FFD 1'b1;
+ end
+ else if (!OCE & SRTYPE[1])
+ begin
+ d2nrnk2 <= # FFD OQ;
+ end
+ else if (SRTYPE[1])
+ begin
+ d2nrnk2 <= # FFD d2rnk2;
+ end
+ end
+end
+
+
+// Logic to generate same edge data from d1rnk2 and d2nrnk2;
+always @ (C or C3 or d1rnk2 or d2nrnk2)
+ begin
+ sdata_edge <= # MXD (d1rnk2 & C) | (d2nrnk2 & C3);
+ end
+
+// Mux to create opposite edge DDR data from d1rnk2 and d2rnk2
+always @ (C or d1rnk2 or d2rnk2)
+ begin
+ case (C)
+ 1'b0: odata_edge <= # MXD d2rnk2;
+ 1'b1: odata_edge <= # MXD d1rnk2;
+ default: odata_edge <= # MXD d1rnk2;
+ endcase
+ end
+
+// Logic to same edge and opposite data into just ddr data
+always @ (ddr_data or sdata_edge or odata_edge or DDR_CLK_EDGE)
+ begin
+ ddr_data <= # MXD (odata_edge & !DDR_CLK_EDGE) | (sdata_edge & DDR_CLK_EDGE);
+ end
+
+
+// Output mux to generate OQ
+always @ (seloq or d1rnk2 or ddr_data or OQ)
+ begin
+ casex (seloq)
+ 4'bXX01: OQ <= # MXD 1'b1;
+ 4'bXX10: OQ <= # MXD 1'b0;
+ 4'bXX11: OQ <= # MXD 1'b0;
+ 4'bX000: OQ <= # MXD ddr_data;
+ 4'bX100: OQ <= # MXD d1rnk2;
+ default: OQ <= # MXD ddr_data;
+ endcase
+ end
+
+
+endmodule
+`timescale 1ps/1ps
+//////////////////////////////////////////////////////////
+//
+// module tout_oserdese1_vlog
+//
+// Tristate Output cell for Mt Blanc
+//
+//
+////////////////////////////////////////////////////////
+//
+//
+//
+/////////////////////////////////////////////////////////
+//
+// Inputs:
+//
+// data1, data2: tristate inputs
+// TCE: Tristate clock enable
+// SR: Set/Reset control. For the last 3 flops in TQ
+// (qt1, qt2 and qt2n) this function is
+// controlled bythe attributes SRVAL_TQ. In SERDES mode,
+// SR is a RESET ONLY for all other flops! The flops will
+// still be RESET even if SR is programmed to a SET!
+// CLK: High speed clocks
+// C2 drives 2nd latch and C3 (inverse of C2) drives
+// 3rd latch in output section
+// BUFO: Performance path clock
+//
+//
+//
+//
+// Outputs:
+//
+// TQ: Output of tristate mux
+//
+//
+// Programmable Options:
+//
+// DATA_RATE_TQ: 2-bit field for types of operaiton
+// 0 (buf from T1), 1 (registered output from T1), 2 (ddr)
+// TRISTATE_WIDTH: 2-bit field for input width
+// 0 (width 1), 1 (width 2), 2 (width 4)
+// INIT_TQ: Init TQ output (0,1)
+// SRVAL_TQ: This bit to controls value of SR input.
+// Only the last 3 flops (qt1, qt2 and qt2n) are
+// affected by this bit.For SERDES mode, this bit
+// should be set to '0' making SR a reset. This is the
+// desired state since all other flops only
+// respond to this pin as a reset. Their function
+// cannot be changed. SR is 'O' for SET and '1' for RESET.
+//
+//
+// Programmable Test Options:
+// SRTYPE: Control S and R as asynchronous (0) or synchronous (1)
+// 2-bit value. 1st bit (msb) controls the 4 input flops
+// and the 2nd bit (lsb) controls the "3 legacy flops"
+// DDR_CLK_EDGE: Same or opposite edge operation
+//
+//
+//
+////////////////////////////////////////////////////////////////////////////////
+//
+
+module tout_oserdese1_vlog (data1, data2,
+ CLK, BUFO, SR, TCE,
+ DATA_RATE_TQ, TRISTATE_WIDTH,
+ INIT_TQ, SRVAL_TQ,
+ TQ, DDR3_MODE);
+
+input data1, data2;
+
+input CLK, BUFO, SR, TCE;
+
+input [1:0] DATA_RATE_TQ, TRISTATE_WIDTH;
+
+input INIT_TQ, SRVAL_TQ;
+
+input DDR3_MODE;
+
+output TQ;
+
+wire DDR_CLK_EDGE;
+wire [1:0] SRTYPE;
+assign SRTYPE = 2'b11;
+assign DDR_CLK_EDGE = 1'b1;
+
+reg TQ;
+
+reg t1r, t2r, t3r, t4r;
+
+reg qt1, qt2, qt2n;
+
+reg sdata_edge, odata_edge, ddr_data;
+
+wire C;
+
+wire C2p, C3;
+
+wire load;
+
+wire [5:0] tqsel;
+
+wire tqsr, tqrev;
+
+wire [4:0] sel;
+
+assign C = (BUFO & DDR3_MODE) | (CLK & !DDR3_MODE);
+
+assign C2p = (C & DDR_CLK_EDGE) | (!C & !DDR_CLK_EDGE);
+
+assign C3 = !C2p;
+
+assign tqsr = (!SRTYPE[0] & SR & !SRVAL_TQ) | (!SRTYPE[0] & SRVAL_TQ);
+
+assign tqrev = (!SRTYPE[0] & SR & SRVAL_TQ) | (!SRTYPE[0] & !SRVAL_TQ);
+
+assign tqsel = {TCE,DATA_RATE_TQ,TRISTATE_WIDTH,tqsr};
+
+
+
+
+
+//////////////////////////////////////////////////
+
+
+// Parameters for gate delays
+parameter ffd = 1;
+parameter mxd = 1;
+
+
+/////////////////////////////
+// Initialization of Flops
+////////////////////////////
+
+tri0 GSR = glbl.GSR;
+
+always @(GSR)
+begin
+ if (GSR)
+ begin
+ assign TQ = INIT_TQ;
+ assign qt1 = INIT_TQ;
+ assign qt2 = INIT_TQ;
+ assign qt2n = INIT_TQ;
+ end
+ else
+ begin
+ deassign TQ;
+ deassign qt1;
+ deassign qt2;
+ deassign qt2n;
+ end
+end
+
+
+
+/////////////////////////////////////////
+// 3 flops to create DDR operations of 4 latches
+////////////////////////////////////////
+
+// Representation of top latch
+// asynchronous operation
+always @ (posedge C or posedge SR)
+begin
+ begin
+ if (SR & !SRVAL_TQ & !SRTYPE[0])
+ begin
+ qt1 <= # ffd 1'b0;
+ end
+ else if (SR & SRVAL_TQ & !SRTYPE[0])
+ begin
+ qt1 <= # ffd 1'b1;
+ end
+ else if (!TCE & !SRTYPE[0])
+ begin
+ qt1 <= # ffd TQ;
+ end
+ else if (!SRTYPE[0])
+ begin
+ qt1 <= # ffd data1;
+ end
+ end
+end
+
+// synchronous operation
+always @ (posedge C)
+begin
+ begin
+
+ if (SR & !SRVAL_TQ & SRTYPE[0])
+ begin
+ qt1 <= # ffd 1'b0;
+ end
+ else if (SR & SRVAL_TQ & SRTYPE[0])
+ begin
+ qt1 <= # ffd 1'b1;
+ end
+ else if (!TCE & SRTYPE[0])
+ begin
+ qt1 <= # ffd TQ;
+ end
+ else if (SRTYPE[0])
+ begin
+ qt1 <= # ffd data1;
+ end
+ end
+end
+
+
+
+
+// Representation of 2nd latch
+// asynchronous operation
+always @ (posedge C2p or posedge SR)
+begin
+ begin
+ if (SR & !SRVAL_TQ & !SRTYPE[0])
+ begin
+ qt2 <= # ffd 1'b0;
+ end
+ else if (SR & SRVAL_TQ & !SRTYPE[0])
+ begin
+ qt2 <= # ffd 1'b1;
+ end
+ else if (!TCE & !SRTYPE[0])
+ begin
+ qt2 <= # ffd TQ;
+ end
+ else if (!SRTYPE[0])
+ begin
+ qt2 <= # ffd data2;
+ end
+ end
+end
+
+// synchronous operation
+always @ (posedge C2p)
+begin
+ begin
+ if (SR & !SRVAL_TQ & SRTYPE[0])
+ begin
+ qt2 <= # ffd 1'b0;
+ end
+ else if (SR & SRVAL_TQ & SRTYPE[0])
+ begin
+ qt2 <= # ffd 1'b1;
+ end
+ else if (!TCE & SRTYPE[0])
+ begin
+ qt2 <= # ffd TQ;
+ end
+ else if (SRTYPE[0])
+ begin
+ qt2 <= # ffd data2;
+ end
+ end
+end
+
+
+
+
+// Representation of 3rd flop ( latch and output latch)
+// asynchronous operation
+always @ (posedge C3 or posedge SR)
+begin
+ begin
+ if (SR & !SRVAL_TQ & !SRTYPE[0])
+ begin
+ qt2n <= # ffd 1'b0;
+ end
+ else if (SR & SRVAL_TQ & !SRTYPE[0])
+ begin
+ qt2n <= # ffd 1'b1;
+ end
+ else if (!TCE & !SRTYPE[0])
+ begin
+ qt2n <= # ffd TQ;
+ end
+ else if (!SRTYPE[0])
+ begin
+ qt2n <= # ffd qt2;
+ end
+ end
+end
+
+// synchronous operation
+always @ (posedge C3)
+begin
+
+ begin
+ if (SR & !SRVAL_TQ & SRTYPE[0])
+ begin
+ qt2n <= # ffd 1'b0;
+ end
+ else if (SR & SRVAL_TQ & SRTYPE[0])
+ begin
+ qt2n <= # ffd 1'b1;
+ end
+ else if (!TCE & SRTYPE[0])
+ begin
+ qt2n <= # ffd TQ;
+ end
+ else if (SRTYPE[0])
+ begin
+ qt2n <= # ffd qt2;
+ end
+ end
+end
+
+
+// Logic to generate same edge data from qt1, qt3;
+always @ (C or C3 or qt1 or qt2n)
+ begin
+ sdata_edge <= # mxd (qt1 & C) | (qt2n & C3);
+ end
+
+// Mux to create opposite edge DDR function
+always @ (C or qt1 or qt2)
+ begin
+ case (C)
+ 1'b0: odata_edge <= # mxd qt2;
+ 1'b1: odata_edge <= # mxd qt1;
+ default: odata_edge <= 1'b0;
+ endcase
+ end
+
+// Logic to same edge and opposite data into just ddr data
+always @ (ddr_data or sdata_edge or odata_edge or DDR_CLK_EDGE)
+ begin
+ ddr_data <= # mxd (odata_edge & !DDR_CLK_EDGE) | (sdata_edge & DDR_CLK_EDGE);
+ end
+
+// Output mux to generate TQ
+// Note that the TQ mux can also support T2 combinatorial or
+// registered outputs.
+always @ (tqsel or data1 or ddr_data or qt1 or TQ)
+ begin
+ casex (tqsel)
+ 6'bX01XX1: TQ <= # mxd 1'b0;
+ 6'bX10XX1: TQ <= # mxd 1'b0;
+ 6'bX01XX1: TQ <= # mxd 1'b0;
+ 6'bX10XX1: TQ <= # mxd 1'b0;
+ 6'bX0000X: TQ <= # mxd data1;
+ // 6'b001000: TQ <= # mxd TQ;
+ // 6'b010010: TQ <= # mxd TQ;
+ // 6'b010100: TQ <= # mxd TQ;
+ 6'bX01000: TQ <= # mxd qt1;
+ 6'bX10010: TQ <= # mxd ddr_data;
+ 6'bX10100: TQ <= # mxd ddr_data;
+ default: TQ <= # mxd ddr_data;
+ endcase
+ end
+
+
+endmodule
+
+`endcelldefine
x393-02965e50741e81c59c7d4889186c0b0cef4cb564/README.md 0000664 0000000 0000000 00000000773 12651560150 0020310 0 ustar 00root root 0000000 0000000 x393
=====
FPGA code for Elphel 393 camera, created with [VDT plugin](https://github.com/Elphel/vdt-plugin)
Branch ```master``` includes the code that is simulated and tested with the NC393 hardware as described in the blog post about the [multichannel memory controller](http://blog.elphel.com/2015/05/nc393-development-progress-multichannel-memory-controller-for-the-multi-sensor-camera/).
Branch ```adding_sensors``` is the current development branch that is not yet simulated, synthesized or tested. x393-02965e50741e81c59c7d4889186c0b0cef4cb564/address_map.txt 0000664 0000000 0000000 00000044640 12651560150 0022055 0 ustar 00root root 0000000 0000000 parameter MCONTR_WR_MASK = 'h3c00, // AXI write address mask for the 1Kx32 buffers command sequence memory
parameter MCONTR_RD_MASK = 'h3c00, // AXI read address mask to generate busy
parameter MCONTR_CMD_WR_ADDR = 'h0000, // AXI write to command sequence memory
parameter MCONTR_BUF0_RD_ADDR = 'h0400, // AXI read address from buffer 0 (PS sequence, memory read)
parameter MCONTR_BUF0_WR_ADDR = 'h0400, // AXI write address to buffer 0 (PS sequence, memory write)
parameter MCONTR_BUF1_RD_ADDR = 'h0800, // AXI read address from buffer 1 (PL sequence, scanline, memory read)
parameter MCONTR_BUF1_WR_ADDR = 'h0800, // AXI write address to buffer 1 (PL sequence, scanline, memory write)
parameter MCONTR_BUF2_RD_ADDR = 'h0c00, // AXI read address from buffer 2 (PL sequence, tiles, memory read)
parameter MCONTR_BUF2_WR_ADDR = 'h0c00, // AXI write address to buffer 2 (PL sequence, tiles, memory write)
parameter MCONTR_BUF3_RD_ADDR = 'h1000, // AXI read address from buffer 3 (PL sequence, scanline, memory read)
parameter MCONTR_BUF3_WR_ADDR = 'h1000, // AXI write address to buffer 3 (PL sequence, scanline, memory write)
parameter MCONTR_BUF4_RD_ADDR = 'h1400, // AXI read address from buffer 4 (PL sequence, tiles, memory read)
parameter MCONTR_BUF4_WR_ADDR = 'h1400, // AXI write address to buffer 4 (PL sequence, tiles, memory write)
parameter CONTROL_ADDR = 'h2000, // AXI write address of control write registers
parameter CONTROL_ADDR_MASK = 'h3800, // AXI write address of control registers
// so 'h2000..'h23ff (CONTROL_ADDR) - no busy when writing, 'h2400..'h27ff (CONTROL_ADDR | BUSY_WR_ADDR) generates busy if fifo half full
parameter BUSY_WR_ADDR = 'h1400, // AXI write address to generate busy
parameter BUSY_WR_ADDR_MASK = 'h3c00, // AXI write address mask to generate busy during memory controller register write
parameter STATUS_ADDR = 'h2800, // AXI write address of status read registers
parameter STATUS_ADDR_MASK = 'h3c00, // AXI write address of status registers
parameter AXI_WR_ADDR_BITS = 14,
parameter AXI_RD_ADDR_BITS = 14,
parameter STATUS_DEPTH= 8, // 256 cells, maybe just 16..64 are enough?
--------------
.MCONTR_WR_MASK (MCONTR_WR_MASK),
.MCONTR_RD_MASK (MCONTR_RD_MASK),
.MCONTR_CMD_WR_ADDR (MCONTR_CMD_WR_ADDR),
.MCONTR_BUF0_RD_ADDR (MCONTR_BUF0_RD_ADDR),
.MCONTR_BUF0_WR_ADDR (MCONTR_BUF0_WR_ADDR),
.MCONTR_BUF1_RD_ADDR (MCONTR_BUF1_RD_ADDR),
.MCONTR_BUF1_WR_ADDR (MCONTR_BUF1_WR_ADDR),
.MCONTR_BUF2_RD_ADDR (MCONTR_BUF2_RD_ADDR),
.MCONTR_BUF2_WR_ADDR (MCONTR_BUF2_WR_ADDR),
.MCONTR_BUF3_RD_ADDR (MCONTR_BUF3_RD_ADDR),
.MCONTR_BUF3_WR_ADDR (MCONTR_BUF3_WR_ADDR),
.MCONTR_BUF4_RD_ADDR (MCONTR_BUF4_RD_ADDR),
.MCONTR_BUF4_WR_ADDR (MCONTR_BUF4_WR_ADDR),
.CONTROL_ADDR (CONTROL_ADDR),
.CONTROL_ADDR_MASK (CONTROL_ADDR_MASK),
.BUSY_WR_ADDR (BUSY_WR_ADDR),
.BUSY_WR_ADDR_MASK (BUSY_WR_ADDR_MASK),
.STATUS_ADDR (STATUS_ADDR),
.STATUS_ADDR_MASK (STATUS_ADDR_MASK),
.AXI_WR_ADDR_BITS (AXI_WR_ADDR_BITS),
.AXI_RD_ADDR_BITS (AXI_RD_ADDR_BITS),
.STATUS_DEPTH (STATUS_DEPTH),
ddrc_control
parameter BUSY_WR_ADDR = 'h1800, // AXI write address to generate busy
parameter BUSY_WR_ADDR_MASK = 'h1c00, // AXI write address mask to generate busy
//0x1080..10ff - 8- bit data - to set various delay values
parameter DLY_LD = 'h080, // address to generate delay load
parameter DLY_LD_MASK = 'h380, // address mask to generate delay load
0x1000..103f - 0- bit data (set/reset)
parameter MCONTR_PHY_0BIT_ADDR = 'h020, // address to set sequnecer channel and run (4 LSB-s - channel)
parameter MCONTR_PHY_0BIT_ADDR_MASK = 'h3f0, // address mask to generate sequencer channel/run
0x1020 - DLY_SET // 0 bits -set pre-programmed delays
0x1024..1025 - CMDA_EN // 0 bits - disable/enable command/address outputs
0x1026..1027 - SDRST_ACT // 0 bits - disable/enable active-low reset signal to DDR3 memory
0x1028..1029 - CKE_EN // 0 bits - disable/enable CKE signal to memory
0x102a..102b - DCI_RST // 0 bits - disable/enable CKE signal to memory
0x102c..102d - DLY_RST // 0 bits - disable/enable CKE signal to memory
parameter MCONTR_PHY_0BIT_DLY_SET = 'h0, // set pre-programmed delays
parameter MCONTR_PHY_0BIT_CMDA_EN = 'h4, // disable/enable command/address outputs
parameter MCONTR_PHY_0BIT_SDRST_ACT = 'h6, // disable/enable active-low reset signal to DDR3 memory
parameter MCONTR_PHY_0BIT_CKE_EN = 'h8, // disable/enable CKE signal to memory
parameter MCONTR_PHY_0BIT_DCI_RST = 'ha, // disable/enable CKE signal to memory
parameter MCONTR_PHY_0BIT_DLY_RST = 'hc, // disable/enable CKE signal to memory
0x1030..1037 - 0-bit memory cotroller (set/reset)
parameter MCONTR_TOP_0BIT_ADDR = 'h030, // address to turn on/off memory controller features
parameter MCONTR_TOP_0BIT_ADDR_MASK = 'h3f8, // address mask to generate sequencer channel/run
0x1030..1031 - MCONTR_EN // 0 bits, disable/enable memory controller
0x1032..1033 - REFRESH_EN // 0 bits, disable/enable memory refresh
0x1034..1037 - reserved
parameter MCONTR_TOP_0BIT_MCONTR_EN = 'h0, // set pre-programmed delays
parameter MCONTR_TOP_0BIT_REFRESH_EN = 'h2, // disable/enable command/address outputs
0x1040..107f - 16-bit data
0x1050..1057: MCONTR_PHY16
parameter MCONTR_PHY_16BIT_ADDR = 'h050, // address to set sequnecer channel and run (4 LSB-s - channel)
parameter MCONTR_PHY_16BIT_ADDR_MASK = 'h3f8, // address mask to generate sequencer channel/run
0x1050 - PATTERNS // 16 bits
0x1051 - PATTERNS_TRI // 16-bit address to set DQM and DQS tristate on/off patterns {dqs_off,dqs_on, dq_off,dq_on} - 4 bits each
0x1052 - WBUF_DELAY // 4 bits - extra delay (in mclk cycles) to add to write buffer enable (DDR3 read data)
0x1053 - EXTRA_REL // 1 bit - set extra parameters (currently just inv_clk_div)
0x1054 - STATUS_CNTRL // 8 bits - write to status control
parameter MCONTR_PHY_16BIT_PATTERNS = 'h0, // set DQM and DQS patterns (16'h0055)
parameter MCONTR_PHY_16BIT_PATTERNS_TRI = 'h1, // 16-bit address to set DQM and DQS tristate on/off patterns {dqs_off,dqs_on, dq_off,dq_on} - 4 bits each
parameter MCONTR_PHY_16BIT_WBUF_DELAY = 'h2, // 4 bits - extra delay (in mclk cycles) to add to write buffer enable (DDR3 read data)
parameter MCONTR_PHY_16BIT_EXTRA_REL = 'h3, // 1 bit - set extra parameters (currently just inv_clk_div)
parameter MCONTR_PHY_STATUS_CNTRL = 'h4, // 8 bits - write to status control
0x1060..106f: arbiter priority data
parameter MCONTR_ARBIT_ADDR = 'h060, // Address to set channel priorities
parameter MCONTR_ARBIT_ADDR_MASK = 'h3f0, // Address mask to set channel priorities
0x1070..1077 - 16-bit top memory controller:
parameter MCONTR_TOP_16BIT_ADDR = 'h070, // address to set mcontr top control registers
parameter MCONTR_TOP_16BIT_ADDR_MASK = 'h3f8, // address mask to set mcontr top control registers
0x1070 - MCONTR_CHN_EN // 16 bits per-channel enable (want/need requests)
0x1071 - REFRESH_PERIOD // 8-bit refresh period
0x1072 - REFRESH_ADDRESS // 10 bits
0x1073 - STATUS_CNTRL // 8 bits - write to status control (and debug?)
parameter MCONTR_TOP_16BIT_CHN_EN = 'h0, // 16 bits per-channel enable (want/need requests)
parameter MCONTR_TOP_16BIT_REFRESH_PERIOD = 'h1, // 8-bit refresh period
parameter MCONTR_TOP_16BIT_REFRESH_ADDRESS= 'h2, // 10 bits refresh address in the sequencer (PL) memory
parameter MCONTR_TOP_16BIT_STATUS_CNTRL= 'h3, // 8 bits - write to status control (and debug?)
0x1080..10ff
0x1080..10ff - DLY_LD // 8 bits :
0x1080..109f - set delay for SDD0-SDD7
0x10a0..10bf - set delay for SDD8-SDD15
0x10c0..10df - set delay for SD_CMDA
0x10e0 - set delay for MMCM
localparam LD_DLY_LANE0_ODELAY = DLY_LD+'h00; // 0x1080
localparam LD_DLY_LANE0_IDELAY = DLY_LD+'h10; // 0x1090
localparam LD_DLY_LANE1_ODELAY = DLY_LD+'h20; // 0x10a0
localparam LD_DLY_LANE1_IDELAY = DLY_LD+'h30; // 0x10b0
localparam LD_DLY_CMDA = DLY_LD+'h40; // 0x10c0
localparam LD_DLY_PHASE = DLY_LD+'h60; // 0x10e0
localparam DLY_SET = MCONTR_PHY_0BIT_ADDR + MCONTR_PHY_0BIT_DLY_SET; //0x1020
----
parameter MCNTRL_TEST01_ADDR= 'h0f0,
parameter MCNTRL_TEST01_MASK= 'h3f0
0x1100..11ff - 32-bit per-channel memory control
0x1100..110f - control of memory channels 0,1 - PS-controlled sequences
parameter MCNTRL_PS_ADDR= 'h100,
parameter MCNTRL_PS_MASK= 'h3e0, // both channels 0 and 1
0x1100 - MCNTRL_PS_EN_RST
0x1101 - MCNTRL_PS_CMD
0x1102 - MCNTRL_PS_STATUS_CNTRL
parameter MCNTRL_PS_EN_RST= 'h0,
parameter MCNTRL_PS_CMD= 'h1,
parameter MCNTRL_PS_STATUS_CNTRL= 'h2,
============= Add the following (addresses will vary for individual channels)
parameter MCNTRL_SCANLINE_CHN2_ADDR= 'h120,
parameter MCNTRL_SCANLINE_CHN3_ADDR= 'h130,
parameter MCNTRL_SCANLINE_MASK= 'h3f0, // both channels 0 and 1
parameter MCNTRL_SCANLINE_MODE= 'h0, // set mode register: {extra_pages[1:0],write_mode,enable,!reset}
parameter MCNTRL_SCANLINE_STATUS_CNTRL= 'h1, // control status reporting
parameter MCNTRL_SCANLINE_STARTADDR= 'h2, // 22-bit frame start address (3 CA LSBs==0. BA==0)
parameter MCNTRL_SCANLINE_FRAME_FULL_WIDTH='h3, // Padded line length (8-row increment), in 8-bursts (16 bytes)
parameter MCNTRL_SCANLINE_WINDOW_WH= 'h4, // low word - 13-bit window width (0->'n4000), high word - 16-bit frame height (0->'h10000)
parameter MCNTRL_SCANLINE_WINDOW_X0Y0= 'h5, // low word - 13-bit window left, high word - 16-bit window top
parameter MCNTRL_SCANLINE_WINDOW_STARTXY= 'h6, // low word - 13-bit start X (relative to window), high word - 16-bit start y
// Start XY can be used when read command to start from the middle
// TODO: Add number of blocks to R/W? (blocks can be different) - total length?
// Read back current address (fro debugging)?
============= Tiled read access (CHN4)
parameter MCNTRL_TILED_CHN4_ADDR= 'h140,
parameter MCNTRL_TILED_MASK= 'h3f0, // both channels 0 and 1
parameter MCNTRL_TILED_MODE= 'h0, // set mode register: {extra_pages[1:0],write_mode,enable,!reset}
parameter MCNTRL_TILED_STATUS_CNTRL= 'h1, // control status reporting
parameter MCNTRL_TILED_STARTADDR= 'h2, // 22-bit frame start address (3 CA LSBs==0. BA==0)
parameter MCNTRL_TILED_FRAME_FULL_WIDTH='h3, // Padded line length (8-row increment), in 8-bursts (16 bytes)
parameter MCNTRL_TILED_WINDOW_WH= 'h4, // low word - 13-bit window width (0->'n4000), high word - 16-bit frame height (0->'h10000)
parameter MCNTRL_TILED_WINDOW_X0Y0= 'h5, // low word - 13-bit window left, high word - 16-bit window top
parameter MCNTRL_TILED_WINDOW_STARTXY= 'h6, // low word - 13-bit start X (relative to window), high word - 16-bit start y
// Start XY can be used when read command to start from the middle
// TODO: Add number of blocks to R/W? (blocks can be different) - total length?
// Read back current address (fro debugging)?
parameter MCNTRL_TILED_TILE_WH= 'h7, // low word - 6-bit tile width in 8-bursts, high - tile height (0 - > 64)
== test module (8-bit):
parameter MCNTRL_TEST01_ADDR= 'h0f0,
parameter MCNTRL_TEST01_MASK= 'h3f0,
parameter FRAME_HEIGHT_BITS= 16, // Maximal frame height
parameter MCNTRL_TEST01_CHN2_MODE= 'h4, // set mode register for channel 2
parameter MCNTRL_TEST01_CHN2_STATUS_CNTRL= 'h5, // control status reporting for channel 2
parameter MCNTRL_TEST01_CHN3_MODE= 'h6, // set mode register for channel 3
parameter MCNTRL_TEST01_CHN3_STATUS_CNTRL= 'h7, // control status reporting for channel 3
parameter MCNTRL_TEST01_CHN4_MODE= 'h8, // set mode register for channel 4
parameter MCNTRL_TEST01_CHN4_STATUS_CNTRL= 'h9, // control status reporting for channel 4
parameter MCNTRL_TEST01_STATUS_REG_CHN2_ADDR= 'h3c, // status/readback register for channel 2
parameter MCNTRL_TEST01_STATUS_REG_CHN3_ADDR= 'h3d, // status/readback register for channel 3
parameter MCNTRL_TEST01_STATUS_REG_CHN4_ADDR= 'h3e // status/readback register for channel 4
// Status read address
parameter STATUS_ADDR = 'h1400, // AXI write address of status read registers
parameter STATUS_ADDR_MASK = 'h1400, // AXI write address of status registers
parameter STATUS_DEPTH= 8, // 256 cells, maybe just 16..64 are enough?
parameter MCONTR_PHY_STATUS_REG_ADDR= 'h0,//8 or less bits: status register address to use for memory controller phy
parameter MCONTR_TOP_STATUS_REG_ADDR= 'h1,//8 or less bits: status register address to use for memory controller
parameter MCNTRL_PS_STATUS_REG_ADDR= 'h2
parameter MCNTRL_SCANLINE_STATUS_REG_CHN1_ADDR='h4,
parameter MCNTRL_TILED_STATUS_REG_CHN2_ADDR= 'h5,
parameter MCNTRL_SCANLINE_STATUS_REG_CHN3_ADDR='h6,
parameter MCNTRL_TILED_STATUS_REG_CHN4_ADDR= 'h7,
parameter MCNTRL_TEST01_STATUS_REG_CHN2_ADDR= 'h3c, // status/readback register for channel 2
parameter MCNTRL_TEST01_STATUS_REG_CHN3_ADDR= 'h3d, // status/readback register for channel 3
parameter MCNTRL_TEST01_STATUS_REG_CHN4_ADDR= 'h3e // status/readback register for channel 4
================================ OLD =======================================================
Control addresses (in original ddrc_test01)
0x1000..100f - RUN_CHN // address to set sequnecer channel and run (4 LSB-s - channel) - bits?
0x1020 - PATTERNS // 16 bits
0x1021 - PATTERNS_TRI // 16-bit address to set DQM and DQS tristate on/off patterns {dqs_off,dqs_on, dq_off,dq_on} - 4 bits each
0x1022 - WBUF_DELAY // 4? bits - extra delay (in mclk cycles) to add to write buffer enable (DDR3 read data)
0x1023 - PAGES // will be removed! 8 bits - address to set buffer pages {port1_page[1:0], port1_int_page[1:0], port0_page[1:0], port0_int_page[1:0]}
0x1024..1025 - CMDA_EN // 0 bits - enable/disable command/address outputs
0x1026..1027 - SDRST_ACT // 0 bits - enable/disable active-low reset signal to DDR3 memory
0x1028..1029 - CKE_EN // 0 bits - enable/disable CKE signal to memory
0x102a..102b - DCI_RST // 0 bits - enable/disable CKE signal to memory
0x102c..102d - DLY_RST // 0 bits - enable/disable CKE signal to memory
0x102e - EXTRA_REL // ? bits - set extra parameters (currently just inv_clk_div)
0x102f - X
0x1030..1031 - REFRESH_EN // 0 bits - enable/disable DDR refresh
0x1032 - REFRESH_PER // 16? bits - refresh period in 32 x tCK
0x1033 - REFRESH_ADDR // 16? bits - sequencer start address for DDR refresh
0x1070 - DLY_SET // 0 bits (set bit delays)
0x1080..10ff - DLY_LD // 8 bits :
0x1080..109f - set delay for SDD0-SDD7
0x10a0..10bf - set delay for SDD8-SDD15
0x10c0..10df - set delay for SD_CMDA
0x10e0 - set delay for MMCM
parameter WBUF_DELAY_REL_MASK = 'h3ff, // address mask to set extra delay
parameter PAGES_REL = 'h023, // address to set buffer pages {port1_page[1:0],port1_int_page[1:0],port0_page[1:0],port0_int_page[1:0]}
parameter PAGES_REL_MASK = 'h3ff, // address mask to set DQM and DQS patterns
parameter CMDA_EN_REL = 'h024, // address to enable('h825)/disable('h824) command/address outputs
parameter CMDA_EN_REL_MASK = 'h3fe, // address mask for command/address outputs
parameter SDRST_ACT_REL = 'h026, // address to activate('h827)/deactivate('h826) active-low reset signal to DDR3 memory
parameter SDRST_ACT_REL_MASK = 'h3fe, // address mask for reset DDR3
parameter CKE_EN_REL = 'h028, // address to enable('h829)/disable('h828) CKE signal to memory
parameter CKE_EN_REL_MASK = 'h3fe, // address mask for command/address outputs
parameter DCI_RST_REL = 'h02a, // address to activate('h82b)/deactivate('h82a) Zynq DCI calibrate circuitry
parameter DCI_RST_REL_MASK = 'h3fe, // address mask for DCI calibrate circuitry
parameter DLY_RST_REL = 'h02c, // address to activate('h82d)/deactivate('h82c) delay calibration circuitry
parameter DLY_RST_REL_MASK = 'h3fe, // address mask for delay calibration circuitry
parameter EXTRA_REL = 'h02e, // address to set extra parameters (currently just inv_clk_div)
parameter EXTRA_REL_MASK = 'h3ff, // address mask for extra parameters
parameter REFRESH_EN_REL = 'h030, // address to enable('h31) and disable ('h30) DDR refresh
parameter REFRESH_EN_REL_MASK = 'h3fe, // address mask to enable/disable DDR refresh
parameter REFRESH_PER_REL = 'h032, // address to set refresh period in 32 x tCK
parameter REFRESH_PER_REL_MASK = 'h3ff, // address mask set refresh period
parameter REFRESH_ADDR_REL = 'h033, // address to set sequencer start address for DDR refresh
parameter REFRESH_ADDR_REL_MASK = 'h3ff // address mask set refresh sequencer address
x393-02965e50741e81c59c7d4889186c0b0cef4cb564/axi/ 0000775 0000000 0000000 00000000000 12651560150 0017603 5 ustar 00root root 0000000 0000000 x393-02965e50741e81c59c7d4889186c0b0cef4cb564/axi/axibram_read.v 0000664 0000000 0000000 00000031635 12651560150 0022420 0 ustar 00root root 0000000 0000000 /*******************************************************************************
* Module: axibram_read
* Date:2014-03-18
* Author: Andrey Filippov
* Description: Read block RAM memory over AXI PS Master GP0
*
* Copyright (c) 2014 Elphel, Inc.
* axibram_read.v is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* axibram_read.v is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*
* Additional permission under GNU GPL version 3 section 7:
* If you modify this Program, or any covered work, by linking or combining it
* with independent modules provided by the FPGA vendor only (this permission
* does not extend to any 3-rd party modules, "soft cores" or macros) under
* different license terms solely for the purpose of generating binary "bitstream"
* files and/or simulating the code, the copyright holders of this Program give
* you the right to distribute the covered work without those independent modules
* as long as the source code for them is available from the FPGA vendor free of
* charge, and there is no dependence on any encrypted modules for simulating of
* the combined code. This permission applies to you if the distributed code
* contains all the components and scripts required to completely simulate it
* with at least one of the Free Software programs.
*******************************************************************************/
// Check that this fix did not break anything:
`include "system_defines.vh"
`define USE_SHORT_REN_REGEN
module axibram_read #(
parameter ADDRESS_BITS = 10 // number of memory address bits
)(
input aclk, // clock - should be buffered
// input rst, // reset, active high
input arst, // @posedge aclk sync reset, active high
// AXI Read Address
input [31:0] araddr, // ARADDR[31:0], input
input arvalid, // ARVALID, input
output arready, // ARREADY, output
input [11:0] arid, // ARID[11:0], input
input [ 3:0] arlen, // ARLEN[3:0], input
input [ 1:0] arsize, // ARSIZE[1:0], input
input [ 1:0] arburst, // ARBURST[1:0], input
// AXI Read Data
output [31:0] rdata, // RDATA[31:0], output
output reg rvalid, // RVALID, output
input rready, // RREADY, input
output reg [11:0] rid, // RID[11:0], output
output reg rlast, // RLAST, output
output [ 1:0] rresp,
// External memory synchronization
output [ADDRESS_BITS-1:0] pre_araddr, // same as awaddr_out, early address to decode and return dev_ready
output start_burst, // start of read burst, valid pre_araddr, save externally to control ext. dev_ready multiplexer
input dev_ready, // extrernal combinatorial ready signal, multiplexed from different sources according to pre_araddr@start_burst
// External memory interface
output bram_rclk, // .rclk(aclk), // clock for read port
output [ADDRESS_BITS-1:0] bram_raddr, // .raddr(read_in_progress?read_address[9:0]:10'h3ff), // read address
output bram_ren, // .ren(bram_reg_re_w) , // read port enable
output bram_regen, // .regen(bram_reg_re_w), // output register enable
input [31:0] bram_rdata // .data_out(rdata[31:0]), // data out
// RRESP[1:0], output
);
// **** AXI Read channel ****
wire ar_nempty;
wire ar_half_full;
assign arready=~ar_half_full;
wire [ 1:0] arburst_out;
// SuppressWarnings VEditor all
wire [ 1:0] arsize_out; // not used
wire [ 3:0] arlen_out;
wire [ADDRESS_BITS-1:0] araddr_out;
wire [11:0] arid_out;
// wire rst=~aresetn;
reg read_in_progress=0;
reg read_in_progress_d=0; // delayed by one active cycle (not skipped)
reg read_in_progress_or=0; // read_in_progress || read_in_progress_d
reg [ADDRESS_BITS-1:0] read_address; // transfer address (not including lower bits
reg [ 3:0] read_left; // number of read transfers
// will ignore arsize - assuming always 32 bits (a*size[2:0]==2)
reg [ 1:0] rburst; // registered burst type
reg [ 3:0] rlen; // registered burst type
wire [ADDRESS_BITS-1:0] next_rd_address_w; // next transfer address;
assign next_rd_address_w= //SuppressThisWarning ISExst Result of 32-bit expression is truncated to fit in 13-bit target.
rburst[1]?
(rburst[0]? {ADDRESS_BITS{1'b0}}:((read_address[ADDRESS_BITS-1:0]+1) & {{(ADDRESS_BITS-4){1'b1}}, ~rlen[3:0]})):
(rburst[0]? (read_address[ADDRESS_BITS-1:0]+1):(read_address[ADDRESS_BITS-1:0]));
wire start_read_burst_w;
// wire bram_re_w;
wire bram_reg_re_w;
wire read_in_progress_w;
wire read_in_progress_d_w;
wire last_in_burst_w;
wire last_in_burst_d_w;
reg pre_last_in_burst_r;
assign rresp=2'b0;
// reduce combinatorial delay from rready (use it in final mux)
// assign bram_reg_re_w= read_in_progress && (!rvalid || rready);
// assign start_read_burst_w=ar_nempty && (!read_in_progress || (bram_reg_re_w && (read_left==4'b0))); // reduce delay from arready
assign last_in_burst_w= bram_reg_re_w && (read_left==4'b0);
assign last_in_burst_d_w=bram_reg_re_w && pre_last_in_burst_r;
// make sure ar_nempty is updated
// assign start_read_burst_w=ar_nempty && (!read_in_progress || last_in_burst_w); // reduce delay from arready
assign read_in_progress_w= start_read_burst_w || (read_in_progress && !last_in_burst_w); // reduce delay from arready
assign read_in_progress_d_w=(read_in_progress && bram_reg_re_w) ||
(read_in_progress && !last_in_burst_d_w); // reduce delay from arready
// assign read_in_progress_d_w=read_in_progress_d;
wire pre_rvalid_w;
assign pre_rvalid_w=bram_reg_re_w || (rvalid && !rready);
wire pre_left_zero_w;
// TODO: Speed up by moving registers
// SuppressWarnings VEditor all - not yet used
reg bram_reg_re_0;
// SuppressWarnings VEditor all - not yet used
reg last_in_burst_1;
// SuppressWarnings VEditor all - not yet used
reg last_in_burst_0;
// SuppressWarnings VEditor all - not yet used
reg start_read_burst_0;
// SuppressWarnings VEditor all - not yet used
reg start_read_burst_1;
reg [11:0] pre_rid0;
reg [11:0] pre_rid;
// External memory interface - synchronization with ready
assign pre_araddr= araddr_out[ADDRESS_BITS-1:0];
assign start_burst= start_read_burst_w;
//input dev_ready, // extrernal combinatorial ready signal, multiplexed from different sources according to pre_araddr@start_burst
// External memory interface
assign bram_rclk = aclk; // clock for read port
assign bram_raddr = read_in_progress?read_address[ADDRESS_BITS-1:0]:{ADDRESS_BITS{1'b1}}; // read address
`ifdef USE_SHORT_REN_REGEN
reg bram_regen_r;
// assign bram_ren = bram_reg_re_w && !pre_last_in_burst_r ; // read port enable
/// assign bram_ren = read_in_progress;
assign bram_ren = read_in_progress && dev_ready;
assign bram_regen = bram_regen_r; // output register enable
`else
assign bram_ren = bram_reg_re_w; // read port enable
assign bram_regen = bram_reg_re_w; // output register enable
`endif
assign rdata[31:0] = bram_rdata; // data out
always @ (posedge aclk) begin
`ifdef USE_SHORT_REN_REGEN
if (arst) bram_regen_r <= 0;
else bram_regen_r <= bram_ren;
`endif
if (arst) pre_last_in_burst_r <= 0;
// else if (start_read_burst_w) pre_last_in_burst_r <= (read_left==4'b0);
else if (bram_reg_re_w) pre_last_in_burst_r <= (read_left==4'b0);
if (arst) rburst[1:0] <= 0;
else if (start_read_burst_w) rburst[1:0] <= arburst_out[1:0];
if (arst) rlen[3:0] <= 0;
else if (start_read_burst_w) rlen[3:0] <= arlen_out[3:0];
if (arst) read_in_progress <= 0;
else read_in_progress <= read_in_progress_w;
if (arst) read_in_progress_d <= 0;
// else read_in_progress_d <= read_in_progress_d_w;
else if (bram_reg_re_w) read_in_progress_d <= read_in_progress_d_w;
if (arst) read_in_progress_or <= 0;
// else read_in_progress_or <= read_in_progress_d_w || read_in_progress_w;
// else if (bram_reg_re_w) read_in_progress_or <= read_in_progress_d_w || read_in_progress_w;
// FIXME:
else if (bram_reg_re_w || !read_in_progress_or) read_in_progress_or <= read_in_progress_d_w || read_in_progress_w;
// reg read_in_progress_d=0; // delayed by one active cycle (not skipped)
// reg read_in_progress_or=0; // read_in_progress || read_in_progress_d
if (arst) read_left <= 0;
else if (start_read_burst_w) read_left <= arlen_out[3:0]; // precedence over inc
else if (bram_reg_re_w) read_left <= read_left-1; //SuppressThisWarning ISExst Result of 32-bit expression is truncated to fit in 4-bit target.
if (arst) read_address <= {ADDRESS_BITS{1'b0}};
else if (start_read_burst_w) read_address <= araddr_out[ADDRESS_BITS-1:0]; // precedence over inc
else if (bram_reg_re_w) read_address <= next_rd_address_w;
if (arst) rvalid <= 1'b0;
else if (bram_reg_re_w && read_in_progress_d) rvalid <= 1'b1;
else if (rready) rvalid <= 1'b0;
if (arst) rlast <= 1'b0;
else if (last_in_burst_d_w) rlast <= 1'b1;
else if (rready) rlast <= 1'b0;
end
always @ (posedge aclk) begin //SuppressThisWarning ISExst Assignment to bram_reg_re_0 ignored, since the identifier is never used
// bram_reg_re_0 <= read_in_progress_w && !pre_rvalid_w;
bram_reg_re_0 <= (ar_nempty && !read_in_progress) || (read_in_progress && !read_in_progress);
last_in_burst_1 <= read_in_progress_w && pre_left_zero_w;
last_in_burst_0 <= read_in_progress_w && !pre_rvalid_w && pre_left_zero_w;
start_read_burst_1 <= !read_in_progress_w || pre_left_zero_w;
start_read_burst_0 <= !read_in_progress_w || (!pre_rvalid_w && pre_left_zero_w);
if (start_read_burst_w) pre_rid0[11:0] <= arid_out[11:0];
if (bram_reg_re_w) pre_rid[11:0] <= pre_rid0[11:0];
if (bram_reg_re_w) rid[11:0] <= pre_rid[11:0];
end
// reducing rready combinatorial delay
assign pre_left_zero_w=start_read_burst_w?(arlen_out[3:0]==4'b0):(bram_reg_re_w && (read_left==4'b0001));
// assign bram_reg_re_w= read_in_progress && (!rvalid || rready);
assign bram_reg_re_w= dev_ready && read_in_progress_or && (!rvalid || rready); // slower/simplier
// assign bram_reg_re_w= rready? read_in_progress : bram_reg_re_0; // faster - more verification
assign last_in_burst_w=bram_reg_re_w && (read_left==4'b0); // slower/simplier
// assign last_in_burst_w=rready? (read_in_progress && (read_left==4'b0)): (bram_reg_re_0 && (read_left==4'b0));
// assign last_in_burst_w=rready? last_in_burst_1: last_in_burst_0; // faster (unfinished) - more verification
assign start_read_burst_w=ar_nempty && (!read_in_progress || (bram_reg_re_w && (read_left==4'b0))); // reduce delay from rready
// assign start_read_burst_w=ar_nempty && (!read_in_progress || ((rready? read_in_progress : bram_reg_re_0) && (read_left==4'b0)));
// assign start_read_burst_w=
// rready?
// (ar_nempty && (!read_in_progress || ((read_in_progress) && (read_left==4'b0)))):
// (ar_nempty && (!read_in_progress || ((bram_reg_re_0 ) && (read_left==4'b0))));
/*
assign start_read_burst_w=
ar_nempty*(rready?
(!read_in_progress || (read_left==4'b0)):
((!read_in_progress || ((bram_reg_re_0 ) && (read_left==4'b0)))));
*/
// assign start_read_burst_w= ar_nempty && (rready?start_read_burst_1:start_read_burst_0);
fifo_same_clock #( .DATA_WIDTH(ADDRESS_BITS+20),.DATA_DEPTH(4))
raddr_i (
.rst(1'b0),
.clk(aclk),
.sync_rst(arst),
.we(arvalid && arready),
.re(start_read_burst_w),
.data_in({arid[11:0], arburst[1:0],arsize[1:0],arlen[3:0],araddr[ADDRESS_BITS+1:2]}),
.data_out({arid_out[11:0], arburst_out[1:0],arsize_out[1:0],arlen_out[3:0],araddr_out[ADDRESS_BITS-1:0]}), //SuppressThisWarning ISExst Assignment to arsize ignored, since the identifier is never used
.nempty(ar_nempty),
.half_full(ar_half_full)
);
endmodule
x393-02965e50741e81c59c7d4889186c0b0cef4cb564/axi/axibram_write.v 0000664 0000000 0000000 00000027312 12651560150 0022634 0 ustar 00root root 0000000 0000000 /*******************************************************************************
* Module: axibram_write
* Date:2014-03-18
* Author: Andrey Filippov
* Description: Read block RAM memory (or memories?) over AXI PS Master GP0
* Memory is supposed to be fast enough
*
* Copyright (c) 2014 Elphel, Inc.
* axibram_write.v is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* axibram_write.v is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*
* Additional permission under GNU GPL version 3 section 7:
* If you modify this Program, or any covered work, by linking or combining it
* with independent modules provided by the FPGA vendor only (this permission
* does not extend to any 3-rd party modules, "soft cores" or macros) under
* different license terms solely for the purpose of generating binary "bitstream"
* files and/or simulating the code, the copyright holders of this Program give
* you the right to distribute the covered work without those independent modules
* as long as the source code for them is available from the FPGA vendor free of
* charge, and there is no dependence on any encrypted modules for simulating of
* the combined code. This permission applies to you if the distributed code
* contains all the components and scripts required to completely simulate it
* with at least one of the Free Software programs.
*******************************************************************************/
//`define DEBUG_FIFO 1
`include "system_defines.vh"
`ifdef DEBUG_FIFO
`undef DEBUG_FIFO
`endif
module axibram_write #(
parameter ADDRESS_BITS = 10 // number of memory address bits
)(
input aclk, // clock - should be buffered
input arst, // @aclk sync reset, active high
// AXI Write Address
input [31:0] awaddr, // AWADDR[31:0], input
input awvalid, // AWVALID, input
output awready, // AWREADY, output
input [11:0] awid, // AWID[11:0], input
input [ 3:0] awlen, // AWLEN[3:0], input
input [ 1:0] awsize, // AWSIZE[1:0], input
input [ 1:0] awburst, // AWBURST[1:0], input
// AXI PS Master GP0: Write Data
input [31:0] wdata, // WDATA[31:0], input
input wvalid, // WVALID, input
output wready, // WREADY, output
input [11:0] wid, // WID[11:0], input
input wlast, // WLAST, input
input [ 3:0] wstb, // WSTRB[3:0], input
// AXI PS Master GP0: Write response
output bvalid, // BVALID, output
input bready, // BREADY, input
output [11:0] bid, // BID[11:0], output
output [ 1:0] bresp, // BRESP[1:0], output
// BRAM (and other write modules) interface
output [ADDRESS_BITS-1:0] pre_awaddr, // same as awaddr_out, early address to decode and return dev_ready
output start_burst, // start of write burst, valid pre_awaddr, save externally to control ext. dev_ready multiplexer
input dev_ready, // extrernal combinatorial ready signal, multiplexed from different sources according to pre_awaddr@start_burst
output bram_wclk,
output [ADDRESS_BITS-1:0] bram_waddr,
output pre_bram_wen,// 1 ahead of bram_wen, not masked by dev_ready
output bram_wen, // external memory write enable, (internally combined with registered dev_ready
output [3:0] bram_wstb,
output [31:0] bram_wdata
`ifdef DEBUG_FIFO
,
output waddr_under,
output wdata_under,
output wresp_under,
output waddr_over,
output wdata_over,
output wresp_over,
output [3:0] waddr_wcount,
output [3:0] waddr_rcount,
output [3:0] waddr_num_in_fifo,
output [3:0] wdata_wcount,
output [3:0] wdata_rcount,
output [3:0] wdata_num_in_fifo,
output [3:0] wresp_wcount,
output [3:0] wresp_rcount,
output [3:0] wresp_num_in_fifo,
output [3:0] wleft,
output [3:0] wlength,
output reg [3:0] wlen_in_dbg
`endif
);
// wire rst=~aresetn;
// **** Write channel: ****
wire aw_nempty;
wire aw_half_full;
assign awready=~aw_half_full;
wire [ 1:0] awburst_out;
// SuppressWarnings VEditor all
wire [ 1:0] awsize_out; // not used
wire [ 3:0] awlen_out;
wire [ADDRESS_BITS-1:0] awaddr_out;
// SuppressWarnings VEditor all
wire [11:0] awid_out; // not used
wire w_nempty;
wire w_half_full;
assign wready=~w_half_full;
wire [31:0] wdata_out;
// SuppressWarnings VEditor all
wire wlast_out; // not used
wire [ 3:0] wstb_out; // WSTRB[3:0], input
wire [11:0] wid_out;
reg write_in_progress=0;
reg [ADDRESS_BITS-1:0] write_address; // transfer address (not including lower bits
reg [ 3:0] write_left; // number of write transfers
// will ignore arsize - assuming always 32 bits (a*size[2:0]==2)
reg [ 1:0] wburst; // registered burst type
reg [ 3:0] wlen; // registered awlen type (for wrapped over transfers)
wire [ADDRESS_BITS-1:0] next_wr_address_w; // next transfer address;
wire bram_we_w; //,bram_we_nonmasked; // write BRAM memory non-masked - should be combined with
wire start_write_burst_w;
wire write_in_progress_w;
wire aw_nempty_ready; // aw_nempty and device ready
wire w_nempty_ready; // w_nempty and device ready
assign aw_nempty_ready=aw_nempty && dev_ready_r; // should it be dev_ready?
assign w_nempty_ready=w_nempty && dev_ready_r; // should it be dev_ready?
reg dev_ready_r; // device, selected at start burst
assign next_wr_address_w= //SuppressThisWarning ISExst Result of 32-bit expression is truncated to fit in 13-bit target.
wburst[1]?
(wburst[0]? {ADDRESS_BITS{1'b0}}:((write_address[ADDRESS_BITS-1:0]+1) & {{(ADDRESS_BITS-4){1'b1}}, ~wlen[3:0]})):
(wburst[0]? (write_address[ADDRESS_BITS-1:0]+1):(write_address[ADDRESS_BITS-1:0]));
assign bram_we_w= w_nempty_ready && write_in_progress;
// assign start_write_burst_w=w_nempty_ready && aw_nempty_ready && (!write_in_progress || (w_nempty_ready && (write_left[3:0]==4'b0)));
// assign write_in_progress_w=w_nempty_ready && aw_nempty_ready || (write_in_progress && !(w_nempty_ready && (write_left[3:0]==4'b0)));
// adding wlast_out to take precedence over (write_left[3:0]==4'b0), maybe wlast_out itself is sufficient
assign start_write_burst_w=w_nempty_ready && aw_nempty_ready && (!write_in_progress || (w_nempty_ready && ((write_left[3:0]==4'b0) || wlast_out)));
assign write_in_progress_w=w_nempty_ready && aw_nempty_ready || (write_in_progress && !(w_nempty_ready && ((write_left[3:0]==4'b0) || wlast_out)));
assign pre_bram_wen = write_in_progress_w;
always @ (posedge aclk) begin
if (arst) wburst[1:0] <= 0;
else if (start_write_burst_w) wburst[1:0] <= awburst_out[1:0];
if (arst) wlen[3:0] <= 0;
else if (start_write_burst_w) wlen[3:0] <= awlen_out[3:0];
if (arst) write_in_progress <= 0;
else write_in_progress <= write_in_progress_w;
if (arst) write_left <= 0;
else if (start_write_burst_w) write_left <= awlen_out[3:0]; // precedence over inc
else if (bram_we_w) write_left <= write_left-1; //SuppressThisWarning ISExst Result of 32-bit expression is truncated to fit in 4-bit target.
if (arst) write_address <= {ADDRESS_BITS{1'b0}};
else if (start_write_burst_w) write_address <= awaddr_out[ADDRESS_BITS-1:0]; // precedence over inc
else if (bram_we_w) write_address <= next_wr_address_w;
if (arst) dev_ready_r <= 1'b0;
else dev_ready_r <= dev_ready;
end
// **** Write response channel ****
wire [ 1:0] bresp_in;
assign bresp_in=2'b0;
// external memory interface (write only)
assign pre_awaddr=awaddr_out[ADDRESS_BITS-1:0];
assign start_burst=start_write_burst_w;
assign bram_wclk = aclk;
assign bram_waddr = write_address[ADDRESS_BITS-1:0];
assign bram_wen = bram_we_w;
assign bram_wstb = wstb_out[3:0];
assign bram_wdata = wdata_out[31:0];
`ifdef DEBUG_FIFO
assign wleft=write_left;
assign wlength[3:0]=wlen[3:0];
always @ (posedge aclk) begin
wlen_in_dbg <= awlen[3:0];
end
`endif
fifo_same_clock #( .DATA_WIDTH(20+ADDRESS_BITS),.DATA_DEPTH(4))
waddr_i (
.rst (1'b0), //rst),
.clk (aclk),
.sync_rst (arst),
.we (awvalid && awready),
.re (start_write_burst_w),
.data_in ({awid[11:0], awburst[1:0],awsize[1:0],awlen[3:0],awaddr[ADDRESS_BITS+1:2]}),
.data_out ({awid_out[11:0], awburst_out[1:0],awsize_out[1:0],awlen_out[3:0],awaddr_out[ADDRESS_BITS-1:0]}), //SuppressThisWarning ISExst Assignment to awsize_out ignored, since the identifier is never used
.nempty (aw_nempty),
.half_full (aw_half_full)
`ifdef DEBUG_FIFO
,
.under (waddr_under), // output reg
.over (waddr_over), // output reg
.wcount (waddr_wcount), // output[3:0] reg
.rcount (waddr_rcount), // output[3:0] reg
.num_in_fifo(waddr_num_in_fifo) // output[3:0]
`endif
);
fifo_same_clock #( .DATA_WIDTH(49),.DATA_DEPTH(4))
wdata_i (
.rst(1'b0), //rst),
.clk(aclk),
.sync_rst (arst),
.we(wvalid && wready),
.re(bram_we_w), //start_write_burst_w), // wrong
.data_in({wid[11:0],wlast,wstb[3:0],wdata[31:0]}),
.data_out({wid_out[11:0],wlast_out,wstb_out[3:0],wdata_out[31:0]}), //SuppressThisWarning ISExst Assignment to wlast ignored, since the identifier is never used
.nempty(w_nempty),
.half_full(w_half_full)
`ifdef DEBUG_FIFO
,
.under (wdata_under), // output reg
.over (wdata_over), // output reg
.wcount (wdata_wcount), // output[3:0] reg
.rcount (wdata_rcount), // output[3:0] reg
.num_in_fifo(wdata_num_in_fifo) // output[3:0]
`endif
);
//debugging - slow down bresp
reg was_bresp_re=0;
wire bresp_re;
assign bresp_re=bready && bvalid && !was_bresp_re;
always @ (posedge aclk) begin
if (arst) was_bresp_re<=0;
else was_bresp_re <= bresp_re;
end
fifo_same_clock #( .DATA_WIDTH(14),.DATA_DEPTH(4))
wresp_i (
.rst(1'b0), //rst),
.clk(aclk),
.sync_rst (arst),
.we(bram_we_w &&((write_left[3:0]==4'b0) || wlast_out)), // added ((write_left[3:0]==4'b0) || wlast_out) - only last wrtite -> bresp
// .re(bready && bvalid),
.re(bresp_re), // not allowing RE next cycle after bvalid
.data_in({wid_out[11:0],bresp_in[1:0]}),
.data_out({bid[11:0],bresp[1:0]}),
.nempty(bvalid),
.half_full()
`ifdef DEBUG_FIFO
,
.under (wresp_under), // output reg
.over (wresp_over), // output reg
.wcount (wresp_wcount), // output[3:0] reg
.rcount (wresp_rcount), // output[3:0] reg
.num_in_fifo(wresp_num_in_fifo) // output[3:0]
`endif
);
endmodule
x393-02965e50741e81c59c7d4889186c0b0cef4cb564/axi/cmprs_afi_mux.v 0000664 0000000 0000000 00000076425 12651560150 0022644 0 ustar 00root root 0000000 0000000 /*******************************************************************************
* Module: cmprs_afi_mux
* Date:2015-06-26
* Author: Andrey Filippov
* Description: Writes comressor data from up to 4 channels to system memory over AXI_HP
*
* Copyright (c) 2015 Elphel, Inc.
* cmprs_afi_mux.v is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* cmprs_afi_mux.v is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*
* Additional permission under GNU GPL version 3 section 7:
* If you modify this Program, or any covered work, by linking or combining it
* with independent modules provided by the FPGA vendor only (this permission
* does not extend to any 3-rd party modules, "soft cores" or macros) under
* different license terms solely for the purpose of generating binary "bitstream"
* files and/or simulating the code, the copyright holders of this Program give
* you the right to distribute the covered work without those independent modules
* as long as the source code for them is available from the FPGA vendor free of
* charge, and there is no dependence on any encrypted modules for simulating of
* the combined code. This permission applies to you if the distributed code
* contains all the components and scripts required to completely simulate it
* with at least one of the Free Software programs.
*******************************************************************************/
`timescale 1ns/1ps
module cmprs_afi_mux#(
parameter CMPRS_AFIMUX_ADDR= 'h140, //TODO: assign valid address
parameter CMPRS_AFIMUX_MASK= 'h7f0,
parameter CMPRS_AFIMUX_EN= 'h0, // enables (global and per-channel)
/*
used 10 bits, in each pair [0] - value, [1] - set (0 - nop). [7:0] - per-channel control, [9:8] - common enable/disable (independent)
*/
parameter CMPRS_AFIMUX_RST= 'h1, // per-channel resets
/*
bits [3:0] - persistent per-channel reset (0 - run, 1 - reset)
*/
parameter CMPRS_AFIMUX_MODE= 'h2, // per-channel select - which register to return as status
/*
mode == 0 - show EOF pointer, internal
mode == 1 - show EOF pointer, confirmed
mode == 2 - show current pointer, internal
mode == 3 - show current pointer, confirmed
each group of 4 bits per channel : bits [1:0] - select, bit[2] - sset (0 - nop), bit[3] - not used
*/
parameter CMPRS_AFIMUX_STATUS_CNTRL= 'h4, // .. 'h7
/*
4 consecutive locations, per-channel status control
*/
parameter CMPRS_AFIMUX_SA_LEN= 'h8, // .. 'hf
/*
27-bit "chunk" addresses and lengths. 1 chunk = 32 bytes, so 27 bit covers all 2^32 address range
8 .. 11 - per-channel start adddresses,
12 .. 15 - per-channel buffer lengths (will roll over to start address)
(0..3 - start addresses, 4..7 - lengths)
*/
parameter CMPRS_AFIMUX_STATUS_REG_ADDR= 'h20, //Uses 4 locations TODO: assign valid address
parameter CMPRS_AFIMUX_WIDTH = 26, // maximal for status: currently only works with 26)
parameter CMPRS_AFIMUX_CYCBITS = 3,
parameter AFI_MUX_BUF_LATENCY = 4'd2 // buffers read latency from fifo_ren* to fifo_rdata* valid : 2 if no register layers are used
`ifdef DEBUG_RING
,parameter DEBUG_CMD_LATENCY = 2
`endif
)(
// input rst,
input mclk, // for command/status
input hclk, // global clock to run axi_hp @ 150MHz, shared by all compressor channels
input mrst, // @posedge mclk, sync reset
input hrst, // @posedge xclk, sync reset
// programming interface
input [7:0] cmd_ad, // byte-serial command address/data (up to 6 bytes: AL-AH-D0-D1-D2-D3
input cmd_stb, // strobe (with first byte) for the command a/d
output [7:0] status_ad, // status address/data - up to 5 bytes: A - {seq,status[1:0]} - status[2:9] - status[10:17] - status[18:25]
output status_rq, // input request to send status downstream
input status_start, // Acknowledge of the first status packet byte (address)
// compressor channel 0
output fifo_rst0, // reset FIFO (set read address to write, reset count)
output fifo_ren0,
input [63:0] fifo_rdata0,
// input fifo_eof0, // single rclk pulse signalling EOF
output eof_written0, // confirm frame written over AFI to the system memory (single hclk pulse)
input pre_flush0, // before last data chunk was written to FIFO
input fifo_flush0, // EOF, need to output all what is in FIFO (Stays active until enough data chunks are read)
input [7:0] fifo_count0, // number of 32-byte chunks in FIFO
// compressor channel 1
output fifo_rst1, // reset FIFO (set read address to write, reset count)
output fifo_ren1,
input [63:0] fifo_rdata1,
// input fifo_eof1, // single rclk pulse signalling EOF
output eof_written1, // confirm frame written over AFI to the system memory (single hclk pulse)
input pre_flush1, // before last data chunk was written to FIFO
input fifo_flush1, // EOF, need to output all what is in FIFO (Stays active until enough data chunks are read)
input [7:0] fifo_count1, // number of 32-byte chunks in FIFO
// compressor channel 2
output fifo_rst2, // reset FIFO (set read address to write, reset count)
output fifo_ren2,
input [63:0] fifo_rdata2,
// input fifo_eof2, // single rclk pulse signalling EOF
output eof_written2, // confirm frame written over AFI to the system memory (single hclk pulse)
input pre_flush2, // before last data chunk was written to FIFO
input fifo_flush2, // EOF, need to output all what is in FIFO (Stays active until enough data chunks are read)
input [7:0] fifo_count2, // number of 32-byte chunks in FIFO
// compressor channel 3
output fifo_rst3, // reset FIFO (set read address to write, reset count)
output fifo_ren3,
input [63:0] fifo_rdata3,
// input fifo_eof3, // single rclk pulse signalling EOF
output eof_written3, // confirm frame written over AFI to the system memory (single hclk pulse)
input pre_flush3, // before last data chunk was written to FIFO
input fifo_flush3, // EOF, need to output all what is in FIFO (Stays active until enough data chunks are read)
input [7:0] fifo_count3, // number of 32-byte chunks in FIFO
// axi_hp signals write channel
// write address
output [31:0] afi_awaddr,
output afi_awvalid,
input afi_awready, // @SuppressThisWarning VEditor unused - used FIF0 level
output [ 5:0] afi_awid,
output [ 1:0] afi_awlock,
output [ 3:0] afi_awcache,
output [ 2:0] afi_awprot,
output reg [ 3:0] afi_awlen,
output [ 1:0] afi_awsize,
output [ 1:0] afi_awburst,
output [ 3:0] afi_awqos,
// write data
output [63:0] afi_wdata,
output afi_wvalid,
input afi_wready, // @SuppressThisWarning VEditor unused - used FIF0 level
output [ 5:0] afi_wid,
output afi_wlast,
output [ 7:0] afi_wstrb,
// write response
input afi_bvalid,
output afi_bready,
input [ 5:0] afi_bid,
input [ 1:0] afi_bresp, // @SuppressThisWarning VEditor unused
// PL extra (non-AXI) signals
input [ 7:0] afi_wcount,
input [ 5:0] afi_wacount,
output afi_wrissuecap1en
`ifdef DEBUG_RING
,output debug_do, // output to the debug ring
input debug_sl, // 0 - idle, (1,0) - shift, (1,1) - load // SuppressThisWarning VEditor - not used
input debug_di // input from the debug ring
`endif
);
//`ifdef DEBUG_RING
// assign debug_do = debug_di; // just temporarily to short-circuit the ring
//`endif
reg en; // enable mux
reg en_d; // or use it to reset all channels?
reg [3:0] en_chn; // per-channel enable
wire [31:0] cmd_data;
wire [ 3:0] cmd_a;
wire cmd_we;
wire cmd_we_status_w;
wire cmd_we_mode_w;
wire cmd_we_sa_len_w;
wire cmd_we_en_w;
wire cmd_we_rst_w;
reg [26:0] sa_len_d;
reg [2:0] sa_len_wa;
reg [3:0] rst_mclk;
reg [9:0] en_mclk;
// hclk domain
// reg [26:0] sa_len_d;
// reg [2:0] sa_len_wa;
wire sa_len_we;
wire en_we;
wire en_rst;
wire [3:0] fifo_flush = {fifo_flush3, fifo_flush2, fifo_flush1, fifo_flush0};
wire [3:0] pre_flush = {pre_flush3, pre_flush2, pre_flush1, pre_flush0};
reg [3:0] ren_suspend_flush; // suspend buffer read until flush is finished
// reg [2:0] cur_chn; // 'b0xx - none, 'b1** - ** - channel number (should match fifo_ren*)
reg [1:0] cur_chn; // 'b0xx - none, 'b1** - ** - channel number (should match fifo_ren*)
reg [31:0] left_to_eof; // number of chunks left to end of frame (one less: 3 means 4 left)
reg [3:0] fifo_flush_d; // fifo_flush* delayed by 1 clk (to detect rising edge
reg [3:0] eof_stb; // single-cycle pulse after fifo_flush is asserted
// reg [1:0] w64_cnt; // count 64-bit words in a chunk
// adjusted counters used for channel arbitration
// pessimistic FIFO content counter - decrements (form FIFO counter) on FIFO reads, knows nothing of writes
reg [35:0] counts_corr0; // registers to hold corrected (decremented currently processed ones if any) fifo count values, MSB - needs flush
reg [17:0] counts_corr1; // first arbitration level winning values
reg [8:0] counts_corr2; // second arbitration level winning values
reg [1:0] winner1; // 2 first level arbitration winners
reg [1:0] winner2; // 2-bit second level arbitration winner
// reg [1:0] cur_chn; // Can it be the same as cur_chn?
wire [7:0] fifo_count0_m1 = fifo_count0 - 1;
wire [7:0] fifo_count1_m1 = fifo_count1 - 1;
wire [7:0] fifo_count2_m1 = fifo_count2 - 1;
wire [7:0] fifo_count3_m1 = fifo_count3 - 1;
// See if we need to bother - any channel needs flushing or has >= 4 of 32-byte chunks to transfer in a single AXI 16-burst 64 bit wide (latency = 4)
wire need_to_bother = |counts_corr2[8:2];
reg ready_to_start; // TBD: either idle or soon will finish the previous burst (include AFI FIFO level here too?)
// wire [3:0] last_chunk_w;
reg [3:0] busy; // TODO: adjust number of bits. During continuous run busy is deasseted for 1 clock cycle
wire done_burst_w; // de-asset busy
wire pre_busy_w;
reg first_busy; // cycle after pre_busy_w
reg [3:0] pend_last; // waiting for last chunk
reg last_burst_in_frame;
// reg [1:0] wlen32; // 2 high bits of burst len (LSB are always 2'b11)
reg [3:0] wleft; // number of 64-bit words left to be sent - also used as awlen (valid @ awvalid)
// reg [2:0] chunk_inc; // how much to increment chunk pointer (1..4)
// wire [2:0] pre_chunk_inc = (|counts_corr2[7:2])? // Would like to increment, if not roll-over
// 3'h4 :
// ({1'b0,left_to_eof[winner2 * 8 +: 2]} + 3'h1);
// Why it has priority for |counts_corr2[7:2] ? If next frame started, it may skip EOF? Or not?
// it is just to pass to a channel, actual transfer size will be decided here (depending on EOF)
wire [1:0] pre_chunk_inc_m1 = (|counts_corr2[7:2])? // Would like to increment, if not roll-over
2'h3 :
left_to_eof[winner2 * 8 +: 2];
reg [ 3:0] reset_pointers; // per-channel - after chunk_start_hclk or chunk_len_hclk were written or explicit fifo_rst*
wire ptr_resetting; // pointers are being reset in cmprs_afi_mux_ptr module
wire [26:0] chunk_addr;
reg [1:0] awvalid;
reg wvalid;
reg wlast;
reg [63:0] wdata; // registered data from one of the 4 buffers
wire wdata_en; // register enable for wdata
wire [1:0] wdata_sel; // source select for wdata
reg [3:0] fifo_ren;
wire [26:0] chunk_ptr_rd;
wire [ 3:0] chunk_ptr_ra;
// If flushing - whatever is left to EOF, otherwise corrected FIFO contents of the winner
wire [ 7:0] items_left = counts_corr2[8] ? left_to_eof[(winner2 * 8) +: 8] : counts_corr2[7:0];
reg [5:0] afi_awid_r;
// "rollover" - roll over destination memory range
wire [2:0] max_wlen; // 0,1,2,3,7 (7 - not limited by rollover) - calculated by cmprs_afi_mux_ptr
// wants to write (want_wleft32+1) 32-byte chunks (4,3,2,1)
wire [1:0] want_wleft32 = (|items_left[7:2])? 2'b11 : items_left[1:0]; // want to set wleft[3:2] if not roll-over (actually "3" means 2)
assign cmd_we_status_w = cmd_we && ((cmd_a & 'hc) == CMPRS_AFIMUX_STATUS_CNTRL);
assign cmd_we_mode_w = cmd_we && (cmd_a == CMPRS_AFIMUX_MODE);
assign cmd_we_sa_len_w = cmd_we && ((cmd_a & 'h8) == CMPRS_AFIMUX_SA_LEN);
assign cmd_we_en_w = cmd_we && (cmd_a == CMPRS_AFIMUX_EN);
assign cmd_we_rst_w = cmd_we && (cmd_a == CMPRS_AFIMUX_RST);
// use last_chunk_w to apply a special id to waddr and wdata and watch for it during readout
// compose ID of channel number, frame bumber LSBs and last/not last chunk
/*
assign last_chunk_w[3:0] = {(left_to_eof[3 * 8 +: 8]==1),
(left_to_eof[2 * 8 +: 8]==1),
(left_to_eof[1 * 8 +: 8]==1),
(left_to_eof[0 * 8 +: 8]==1)};
*/
assign pre_busy_w = !busy[0] && ready_to_start && need_to_bother && !ptr_resetting;
assign done_burst_w = busy[0] && !(|wleft[3:1]); // when wleft[3:0] == 0, busy is 0
assign {fifo_rst3, fifo_rst2, fifo_rst1, fifo_rst0} = reset_pointers;
assign {fifo_ren3, fifo_ren2, fifo_ren1, fifo_ren0} = fifo_ren;
assign afi_awaddr = {chunk_addr,5'b0};
assign afi_awid = afi_awid_r; // {1'b0,wleft[3:2],last_burst_in_frame,cur_chn};
assign afi_awvalid = awvalid[1];
// assign afi_awlen = {wleft[3:2],2'b11};
assign afi_wdata = wdata;
// assign afi_bready = 1'b1; // always ready
// other fixed-value AFI signals
assign afi_awlock = 2'h0;
assign afi_awcache = 4'h3;
assign afi_awprot = 3'h0;
assign afi_awsize = 2'h3;
assign afi_awburst = 2'h1;
assign afi_awqos = 4'h0;
assign afi_wstrb = 8'hff;
assign afi_wrissuecap1en = 1'b0;
`ifdef DEBUG_RING
debug_slave #(
.SHIFT_WIDTH (64),
.READ_WIDTH (64),
.WRITE_WIDTH (32),
.DEBUG_CMD_LATENCY (DEBUG_CMD_LATENCY)
) debug_slave_i (
.mclk (mclk), // input
.mrst (mrst), // input
.debug_di (debug_di), // input
.debug_sl (debug_sl), // input
.debug_do (debug_do), // output
.rd_data ({
left_to_eof[31:0],
24'b0,
fifo_count0[7:0]
}), // input[31:0]
.wr_data (), // output[31:0] - not used
.stb () // output - not used
);
`endif
always @ (posedge mclk) begin
if (cmd_we_sa_len_w) begin
sa_len_d <= cmd_data[26:0];
sa_len_wa <= cmd_a[2:0];
end
if (mrst) en_mclk <= 0;
else if (cmd_we_en_w) en_mclk <= cmd_data[9:0];
if (mrst) rst_mclk <= ~0;
else if (cmd_we_rst_w) rst_mclk <= cmd_data[3:0];
end
always @ (posedge hclk) begin
reset_pointers <= ((en && !en_d) || hrst)? 4'hf : (en_rst ? rst_mclk : 4'h0);
if (hrst) en_chn[0] <= 0;
else if (en_we && en_mclk[1]) en_chn[0] <= en_mclk[0];
if (hrst) en_chn[1] <= 0;
else if (en_we && en_mclk[3]) en_chn[1] <= en_mclk[2];
if (hrst) en_chn[2] <= 0;
else if (en_we && en_mclk[5]) en_chn[2] <= en_mclk[4];
if (hrst) en_chn[3] <= 0;
else if (en_we && en_mclk[7]) en_chn[3] <= en_mclk[6];
if (hrst) en <= 0;
else if (en_we && en_mclk[9]) en <= en_mclk[8];
end
always @ (posedge hclk) begin
en_d <= en;
ready_to_start <= en && // ready to strta a burst
!afi_wacount[5] && !(&afi_wacount[4:1]) && // >=2 free
!afi_wcount[7] && !(&afi_wcount[6:3]); // >=8 free (4 would be enough too)
fifo_flush_d <= {fifo_flush3,fifo_flush2,fifo_flush1,fifo_flush0};
eof_stb <= {fifo_flush3 & ~fifo_flush_d[3],
fifo_flush2 & ~fifo_flush_d[2],
fifo_flush1 & ~fifo_flush_d[1],
fifo_flush0 & ~fifo_flush_d[0]};
// TODO: change &w64_cnt[1:0] so left_to_eof[*] will be updated earlier and valid at pre_busy_w
// Done, updating at the first (not last) word of 4
// Now seems that eof_stb[i] & fifo_ren{i} == 0
// Seems needs to decrement fifo_count0_m1 regardless of &wleft[1:0] - if started, will eventually decrement
// How to make sure that decremented value always >0?
// if (eof_stb[0]) left_to_eof[0 * 8 +: 8] <= fifo_count0_m1 - (fifo_ren0 & (&wleft[1:0]));
if (eof_stb[0]) left_to_eof[0 * 8 +: 8] <= fifo_count0_m1 - fifo_ren0;
else if (fifo_ren0 & (&wleft[1:0])) left_to_eof[0 * 8 +: 8] <= left_to_eof[0 * 8 +: 8] - 1;
// if (eof_stb[1]) left_to_eof[1 * 8 +: 8] <= fifo_count1_m1 - (fifo_ren1 & (&wleft[1:0]));
if (eof_stb[1]) left_to_eof[1 * 8 +: 8] <= fifo_count1_m1 - fifo_ren1;
else if (fifo_ren1 & (&wleft[1:0])) left_to_eof[1 * 8 +: 8] <= left_to_eof[1 * 8 +: 8] - 1;
// if (eof_stb[2]) left_to_eof[2 * 8 +: 8] <= fifo_count2_m1 - (fifo_ren2 & (&wleft[1:0]));
if (eof_stb[2]) left_to_eof[2 * 8 +: 8] <= fifo_count2_m1 - fifo_ren2;
else if (fifo_ren2 & (&wleft[1:0])) left_to_eof[2 * 8 +: 8] <= left_to_eof[2 * 8 +: 8] - 1;
// if (eof_stb[3]) left_to_eof[3 * 8 +: 8] <= fifo_count3_m1 - (fifo_ren3 & (&wleft[1:0]));
if (eof_stb[3]) left_to_eof[3 * 8 +: 8] <= fifo_count3_m1 - fifo_ren3;
else if (fifo_ren3 & (&wleft[1:0])) left_to_eof[3 * 8 +: 8] <= left_to_eof[3 * 8 +: 8] - 1;
// Calculate corrected values decrementing currently served channel (if any) values by 1 (latency 1 clk)
// During ren_suspend_flush (from pre_flush to flush) 0 - effectively disable, after flush - highest priority
if ((fifo_count0 == 0) || !en_chn[0] ||ren_suspend_flush[0]) counts_corr0[0 * 9 +: 9] <= 0;
else if (fifo_ren[0]) counts_corr0[0 * 9 +: 9] <= (fifo_count0_m1 == 0)? 0 : {fifo_flush0,fifo_count0_m1};
else counts_corr0[0 * 9 +: 9] <= {fifo_flush0,fifo_count0};
if ((fifo_count1 == 0) || !en_chn[1] ||ren_suspend_flush[1]) counts_corr0[1 * 9 +: 9] <= 0;
else if (fifo_ren[1]) counts_corr0[1 * 9 +: 9] <= (fifo_count1_m1 == 0)? 0 : {fifo_flush1,fifo_count1_m1};
else counts_corr0[1 * 9 +: 9] <= {fifo_flush1,fifo_count1};
if ((fifo_count2 == 0) || !en_chn[2] ||ren_suspend_flush[2]) counts_corr0[2 * 9 +: 9] <= 0;
else if (fifo_ren[2]) counts_corr0[2 * 9 +: 9] <= (fifo_count2_m1 == 0)? 0 : {fifo_flush2,fifo_count2_m1};
else counts_corr0[2 * 9 +: 9] <= {fifo_flush2,fifo_count2};
if ((fifo_count3 == 0) || !en_chn[3] ||ren_suspend_flush[3]) counts_corr0[3 * 9 +: 9] <= 0;
else if (fifo_ren[3]) counts_corr0[3 * 9 +: 9] <= (fifo_count3_m1 == 0)? 0 : {fifo_flush3,fifo_count3_m1};
else counts_corr0[3 * 9 +: 9] <= {fifo_flush3,fifo_count3};
// 2-level arbitration
// first arbitration level (latency 2 clk)
if (counts_corr0[1 * 9 +: 9] > counts_corr0[0 * 9 +: 9]) begin
counts_corr1[0 * 9 +: 9] <= counts_corr0[1 * 9 +: 9];
winner1[0] <= 1;
end else begin
counts_corr1[0 * 9 +: 9] <= counts_corr0[0 * 9 +: 9];
winner1[0] <= 0;
end
if (counts_corr0[3 * 9 +: 9] > counts_corr0[2 * 9 +: 9]) begin
counts_corr1[1 * 9 +: 9] <= counts_corr0[3 * 9 +: 9];
winner1[1] <= 1;
end else begin
counts_corr1[1 * 9 +: 9] <= counts_corr0[2 * 9 +: 9];
winner1[1] <= 0;
end
// second arbitration level (latency 3 clk)
if (counts_corr1[1 * 9 +: 9] > counts_corr1[0 * 9 +: 9]) begin
counts_corr2 <= counts_corr1[1 * 9 +: 9];
winner2 <= {1'b1,winner1[1]};
end else begin
counts_corr2 <= counts_corr1[0 * 9 +: 9];
winner2 <= {1'b0,winner1[0]};
end
//ready_to_start need_to_bother
//done_burst
if (!en) busy <= 0;
// else if (pre_busy_w) busy <= {busy[2:0],1'b1};
// else if (done_burst_w) busy <= 0; // {busy[2:0],1'b0};
else busy <= {busy[2:0], pre_busy_w | (busy[0] & ~done_burst_w)};
if (!en) first_busy <= 0;
else first_busy <= pre_busy_w;
if (!en) pend_last <= 0;
else pend_last <= eof_stb | (pend_last & ~({4{first_busy & last_burst_in_frame}} & fifo_ren ));
//pend_last
if (!en) wleft <= 0;
/// else if (pre_busy_w) wleft <= {(|items_left[7:2])? 2'b11 : items_left[1:0], 2'b11}; // @@@******* different for roll over
/// else if (pre_busy_w) wleft <= {(max_wlen[2] || (max_wlen[1:0] > want_wleft32))? want_wleft32 : max_wlen[1:0], 2'b11};
else if (pre_busy_w) wleft <= {(max_wlen[1:0] > want_wleft32) ? want_wleft32 : max_wlen[1:0], 2'b11};
else if (wleft != 0) wleft <= wleft - 1;
/*
counts_corr2[8]
items_left
else if (pre_busy_w) wleft <= {(|counts_corr2[7:2])? 2'b11 : left_to_eof[winner2 * 8 +: 2], 2'b11};
else if (wleft != 0) wleft <= wleft - 1;
*/
if (!en) wvalid <= 0;
else if (pre_busy_w) wvalid <= 1;
else if (wlast) wvalid <= 0; // should be after pre_busy_w as both can happen simultaneously
if (!en) fifo_ren <= 0;
else if (pre_busy_w) fifo_ren <= {(winner2 == 3) ?1'b1:1'b0,
(winner2 == 2) ?1'b1:1'b0,
(winner2 == 1) ?1'b1:1'b0,
(winner2 == 0) ?1'b1:1'b0};
else if (wlast) fifo_ren <= 0;
// new mods
if (!en) ren_suspend_flush <= 0;
else ren_suspend_flush <= pre_flush | (ren_suspend_flush & ~fifo_flush );
awvalid <= {awvalid[0],pre_busy_w}; // no need to wait for afi_awready, will use fifo levels to enable pre_busy_w
if (pre_busy_w) begin
cur_chn <= winner2;
// last_burst_in_frame <= last_chunk_w[winner2] && pend_last[winner2];
last_burst_in_frame <= counts_corr2[8] && (left_to_eof[winner2 * 8 + 2 +: 6] == 0) && pend_last[winner2];
end
wlast <= done_burst_w; // when wleft==4'h1
// wdata register mux
if (wdata_en) wdata <= wdata_sel[1]?(wdata_sel[0]?fifo_rdata3:fifo_rdata2):(wdata_sel[0]?fifo_rdata1:fifo_rdata0);
// if (pre_busy_w) chunk_inc <= (|counts_corr2[7:2])? // Would like to increment, if not roll-over
// 3'h4 :
// ({1'b0,left_to_eof[winner2 * 8 +: 2]} + 3'h1);
if (awvalid[0]) afi_awid_r <={1'b0,wleft[3:2],last_burst_in_frame,cur_chn};
if (awvalid[0]) afi_awlen <= {wleft[3:2],2'b11};
end
// delay write channel controls signal to match data latency. wid bits will be optimized (6 -> 3)
dly_16 #(
.WIDTH(2) // 8)
) afi_wx_i (
.clk (hclk), // input
.rst (!en), // input
.dly (AFI_MUX_BUF_LATENCY), // input[3:0] will delay by AFI_MUX_BUF_LATENCY+1 (normally 3)
.din ({ wvalid, wlast}), // , afi_awid_r}), // afi_awid}), // input[0:0]
.dout ({afi_wvalid, afi_wlast}) //, afi_wid}) // output[0:0]
);
localparam [3:0] AFI_MUX_BUF_LATENCYM1 = AFI_MUX_BUF_LATENCY - 1;
dly_16 #(
.WIDTH(9) // 3)
) afi_wdata_i (
.clk (hclk), // input
.rst (!en), // input
.dly (AFI_MUX_BUF_LATENCYM1), // input[3:0] will delay by AFI_MUX_BUF_LATENCY+1 (normally 3)
.din ({wvalid, cur_chn, afi_awid_r}), //}), // input[0:0]
.dout ({wdata_en, wdata_sel, afi_wid}) // }) // output[0:0]
);
cmd_deser #(
.ADDR (CMPRS_AFIMUX_ADDR),
.ADDR_MASK (CMPRS_AFIMUX_MASK),
.NUM_CYCLES (6),
.ADDR_WIDTH (4),
.DATA_WIDTH (32)
) cmd_deser_32bit_i (
.rst (1'b0), // rst), // input
.clk (mclk), // input
.srst (mrst), // input
.ad (cmd_ad), // input[7:0]
.stb (cmd_stb), // input
.addr (cmd_a), // output[3:0]
.data (cmd_data), // output[31:0]
.we (cmd_we) // output
);
wire [53:0] chunk_ptr_rd01; // [0:1]; // combines 2 pointers - write one and write response one
cmprs_afi_mux_ptr cmprs_afi_mux_ptr_i (
.hclk (hclk), // input
.sa_len_di (sa_len_d[26:0]), // input[26:0]
.sa_len_wa (sa_len_wa[2:0]), // input[2:0]
.sa_len_we (sa_len_we), // input
.en (en), // input
.reset_pointers (reset_pointers), // input[3:0]
.pre_busy_w (pre_busy_w), // input
.winner_channel (winner2), // input[1:0]
.need_to_bother (need_to_bother), // input
// .chunk_inc (chunk_inc), // input[2:0]
.chunk_inc_want_m1 (pre_chunk_inc_m1), // input[1:0] Want to increment by this (0..3) + 1, if not roll over
.last_burst_in_frame (last_burst_in_frame), // input
.busy (busy), // input[3:0]
.ptr_resetting (ptr_resetting), // output
.chunk_addr (chunk_addr), // output[26:0] reg
.chunk_ptr_ra (chunk_ptr_ra[2:0]), // input[2:0]
.chunk_ptr_rd (chunk_ptr_rd01[0 * 27 +: 27]), // output[26:0]
.max_wlen (max_wlen) // output[2:0]: msb - no rollover (>3)
);
assign chunk_ptr_rd=chunk_ptr_ra[3]?chunk_ptr_rd01[1 * 27 +: 27]:chunk_ptr_rd01[0 * 27 +: 27];
cmprs_afi_mux_ptr_wresp cmprs_afi_mux_ptr_wresp_i (
.hclk (hclk), // input
.length_di (sa_len_d[26:0]), // input[26:0]
.length_wa (sa_len_wa[1:0]), // input[1:0]
.length_we (sa_len_we & sa_len_wa[2]), // input
.en (en), // input
.reset_pointers (reset_pointers), // input[3:0]
.chunk_ptr_ra (chunk_ptr_ra[2:0]), // input[2:0]
.chunk_ptr_rd (chunk_ptr_rd01[1* 27 +: 27]), // output[26:0]
.eof_written ({eof_written3,eof_written2,eof_written1,eof_written0}), // output[3:0] reg
.afi_bvalid (afi_bvalid), // input
.afi_bready (afi_bready), // output
.afi_bid (afi_bid) // input[5:0]
);
cmprs_afi_mux_status #(
.CMPRS_AFIMUX_STATUS_REG_ADDR (CMPRS_AFIMUX_STATUS_REG_ADDR), // uses 4 locations
.CMPRS_AFIMUX_WIDTH(CMPRS_AFIMUX_WIDTH),
.CMPRS_AFIMUX_CYCBITS(CMPRS_AFIMUX_CYCBITS)
) cmprs_afi_mux_status_i (
// .rst (rst), // input
.hclk (hclk), // input
.mclk (mclk), // input
.mrst (mrst), // input
.hrst (hrst), // input
.cmd_data (cmd_data[15:0]), // input[15:0]
.cmd_a (cmd_a[1:0]), // input[1:0]
.status_we (cmd_we_status_w), // input
.mode_we (cmd_we_mode_w), // input
.status_ad (status_ad), // output[7:0]
.status_rq (status_rq), // output
.status_start (status_start), // input
.en (en), // input
.chunk_ptr_ra (chunk_ptr_ra), // output[3:0] reg
.chunk_ptr_rd (chunk_ptr_rd[CMPRS_AFIMUX_WIDTH-1:0]) // input[25:0]
);
pulse_cross_clock sa_len_we_i (.rst(mrst), .src_clk(mclk), .dst_clk(hclk), .in_pulse(cmd_we_sa_len_w), .out_pulse(sa_len_we),.busy());
pulse_cross_clock en_we_i (.rst(mrst), .src_clk(mclk), .dst_clk(hclk), .in_pulse(cmd_we_en_w), .out_pulse(en_we), .busy());
pulse_cross_clock en_rst_i (.rst(mrst), .src_clk(mclk), .dst_clk(hclk), .in_pulse(cmd_we_rst_w), .out_pulse(en_rst),.busy());
endmodule
x393-02965e50741e81c59c7d4889186c0b0cef4cb564/axi/cmprs_afi_mux_ptr.v 0000664 0000000 0000000 00000023365 12651560150 0023524 0 ustar 00root root 0000000 0000000 /*******************************************************************************
* Module: cmprs_afi_mux_ptr
* Date:2015-06-28
* Author: Andrey Filippov
* Description: Maintain 4-channel chunk pointers (before AXI)
* Advance 32-byte chunk pointers for each AXI burst and each frame (4*2=8 pointers)
*
* Copyright (c) 2015 Elphel, Inc.
* cmprs_afi_mux_ptr.v is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* cmprs_afi_mux_ptr.v is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*
* Additional permission under GNU GPL version 3 section 7:
* If you modify this Program, or any covered work, by linking or combining it
* with independent modules provided by the FPGA vendor only (this permission
* does not extend to any 3-rd party modules, "soft cores" or macros) under
* different license terms solely for the purpose of generating binary "bitstream"
* files and/or simulating the code, the copyright holders of this Program give
* you the right to distribute the covered work without those independent modules
* as long as the source code for them is available from the FPGA vendor free of
* charge, and there is no dependence on any encrypted modules for simulating of
* the combined code. This permission applies to you if the distributed code
* contains all the components and scripts required to completely simulate it
* with at least one of the Free Software programs.
*******************************************************************************/
`timescale 1ns/1ps
module cmprs_afi_mux_ptr(
input hclk, // global clock to run axi_hp @ 150MHz, shared by all compressor channels
// Write dual port 8x27 channel start address/length RAM
input [26:0] sa_len_di, // data to write per-channle buffer sa/length in chunks
input [ 2:0] sa_len_wa, // channel address to write sa/lengths
input sa_len_we, // write enable sa/length data
input en, // 0 - resets, 0->1 resets all pointers. While reset allows write response
input [ 3:0] reset_pointers, // per-channel - reset pointers
input pre_busy_w, // combinatorial signal - one before busy[0] (depends on ptr_resetting)
input [ 1:0] winner_channel, // channel that won arbitration for AXI access, valid @ pre_busy_w
input need_to_bother, // whants to start access if address and data FIFO permit
input [1:0] chunk_inc_want_m1, // how much to increment chunk pointer (0..3) +1 - valid with busy[0] (w/o rollover)
input last_burst_in_frame, // valid with busy[0] (last_burst_in_frame<=last_chunk_w[winner2])
input [ 3:0] busy, // one cycle less than sending 1-4 bursts, [1] - delayed by 1, [2] - by 2
output ptr_resetting, // pointers will be reset next cycle (2-cycle-long pulse)
output reg [26:0] chunk_addr, // chunk absolute address, valid with busy[1]
input [ 2:0] chunk_ptr_ra, // chunk pointer read address {eof, chn[1:0]}
output [26:0] chunk_ptr_rd, // chunk pointer read data (non-registered
// output [ 2:0] max_inc // maximal increment to rollover (limited by 4)
output [ 2:0] max_wlen // maximal wlen[3:2], MSB - limited by rollover
);
reg [3:0] reset_rq; // request to reset pointers when ready
reg [3:0] reset_rq_pri; // one-hot reset rq
wire [1:0] reset_rq_enc; // encoded reset_rq_pri
wire start_resetting_w;
reg [1:0] resetting; // resetting chunk_pointer and eof_pointer
reg [2:0] ptr_wa; // pointer memory write port address, msb - eof/current, 2 LSB - channel
reg ptr_we; // pointer memory write enable
reg [26:0] ptr_ram[0:7]; // pointer (current and eof) memory (in 32-byte chunks
wire [26:0] ptr_ram_di; // data to be written to ptr_ram
reg [26:0] sa_len_ram[0:7]; // start chunk/num cunks in a buffer (write port @mclk)
reg [26:0] chunk_ptr_inc; // incremented by 1..4 chunk pointer
// reg [27:0] rollover_r; // incremented chunk pointer, decremented by length (MSB - sign)
reg en_d; //enable delayed by 1 cycle
wire [ 2:0] sa_len_ra; // start/len read address (0..3 - start addresses, 4..7 - lengths)
reg [ 2:0] max_inc_ram[0:3]; // maximal increment to rollover (limited by 4)
wire [ 1:0] pre_chunk_inc_m1;
reg [ 2:0] chunk_inc;
wire [26:0] chunks_to_rollover;
reg [3:0] chunks_to_rollover_r; // [3] >=8
wire [3:0] chunks_to_rollover_m1;
reg max_inc_ram_we;
reg [1:0] max_inc_ram_wa;
wire rollover_w; // this cycle causes rollover - valid at pre_busy_w
reg rollover_r; // this cycle causes rollover - valid at busy[0] and late
wire ptr_ram_wa = ptr_ram[ptr_wa]; // SuppressThisWarning VEditor debug - just to view
assign ptr_resetting = resetting[0];
assign sa_len_ra= {busy[1],ptr_wa[1:0]};
assign reset_rq_enc = {reset_rq_pri[3] | reset_rq_pri[2],
reset_rq_pri[3] | reset_rq_pri[1]};
// assign ptr_ram_di= resetting[1] ? 27'b0 : (chunk_ptr_rovr[27] ? chunk_ptr_inc : chunk_ptr_rovr[26:0]);
assign ptr_ram_di= (resetting[1] ||rollover_r) ? 27'b0 : chunk_ptr_inc ;
assign chunk_ptr_rd = ptr_ram[chunk_ptr_ra];
assign start_resetting_w = en && !busy[0] && !resetting[0] && (|reset_rq) && !need_to_bother;
// assign max_inc = max_inc_ram[winner_channel];
assign max_wlen = max_inc_ram[winner_channel]; // valid @pre_busy_w
//chunk_inc_want_m1
assign pre_chunk_inc_m1 = (max_wlen[1:0] >= chunk_inc_want_m1)? chunk_inc_want_m1 : max_wlen[1:0];
assign rollover_w = !max_wlen[2] && (max_wlen[1:0] <= chunk_inc_want_m1);
assign chunks_to_rollover = sa_len_ram[sa_len_ra] - ptr_ram_di;
assign chunks_to_rollover_m1 = chunks_to_rollover_r -1;
always @ (posedge hclk) begin
en_d <= en;
// ===== calculate and rollover channel addresses ====
// clear (during "resetting" or update 8x27 RAM that holds chunk pointers for the current burst and currenty frame
// uses (reads) additional memory with per-channel start addresses and lengths (both measured in 32-byte chunks
// read port of the ptr_ram will be used to monitor pointers through the status network
// TODO: Make sure correct RAM modules are inferred
// write length RAM
if (sa_len_we) sa_len_ram[sa_len_wa] <= sa_len_di;
if (start_resetting_w) reset_rq_pri <= {reset_rq[3] & ~(|reset_rq[2:0]),
reset_rq[2] & ~(|reset_rq[1:0]),
reset_rq[1] & ~reset_rq[0],
reset_rq[0]};
if (en && !en_d) reset_rq <= 4'hf;
else reset_rq <= reset_pointers | (reset_rq & ~({4{resetting[0] &~ resetting[1]}} & reset_rq_pri));
if (!en) resetting <= 0;
else resetting <= {resetting[0], start_resetting_w | (resetting[0] & ~resetting[1])};
if (resetting == 2'b1) ptr_wa[1:0] <= reset_rq_enc;
else if (pre_busy_w) ptr_wa[1:0] <= winner_channel;
if (start_resetting_w || pre_busy_w) ptr_wa[2] <= 0;
else if (ptr_we) ptr_wa[2] <= 1;
ptr_we <= resetting[0] || // a pair of cycles to reset chunk pointer and frame chunk pointer
(busy[1] && !busy[2]) || // always update chunk pointer
(busy[2] && !busy[3] && last_burst_in_frame); // optionally update frame chunk pointer (same value)
if (busy[0] && !busy[1]) begin // first clock of busy
// calculate full address for current AXI burst (valid 1 clk after busy)
chunk_addr <= ptr_ram[ptr_wa] + sa_len_ram[sa_len_ra];
chunk_ptr_inc <= ptr_ram[ptr_wa] + chunk_inc;
end
// if (busy[1] && !busy[2]) begin // first clock of busy
// chunk_ptr_rovr <={1'b0,chunk_ptr_inc} - {1'b0,sa_len_ram[sa_len_ra]}; // sa_len_ra now points at length
// end
// write to ptr_ram (1 or 2 locations - if eof)
if (ptr_we) ptr_ram[ptr_wa] <= ptr_ram_di;
if (pre_busy_w) chunk_inc <= {1'b0, pre_chunk_inc_m1} + 1;
if (pre_busy_w) rollover_r <= rollover_w;
// wire [26:0] chunks_to_rollover;
// reg [3:0] chunks_to_rollover_r; // [3] >=8
if (ptr_we) chunks_to_rollover_r <= {|chunks_to_rollover[26:3],chunks_to_rollover[2:0]};
max_inc_ram_we <= ptr_we & ~ptr_wa[2];
max_inc_ram_wa <= ptr_wa[1:0];
if (max_inc_ram_we) max_inc_ram[max_inc_ram_wa] <= (|chunks_to_rollover_m1[3:2])?3'h7:{1'b0,chunks_to_rollover_m1[1:0]};
end
endmodule
x393-02965e50741e81c59c7d4889186c0b0cef4cb564/axi/cmprs_afi_mux_ptr_wresp.v 0000664 0000000 0000000 00000022056 12651560150 0024740 0 ustar 00root root 0000000 0000000 /*******************************************************************************
* Module: cmprs_afi_mux_ptr_wresp
* Date:2015-06-28
* Author: Andrey Filippov
* Description: Maintain 4-channel chunk pointers for wrirte response
* Advance 32-byte chunk pointers for each AXI burst and each frame (4*2=8 pointers)
*
* Copyright (c) 2015 Elphel, Inc.
* cmprs_afi_mux_ptr_wresp.v is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* cmprs_afi_mux_ptr_wresp.v is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*
* Additional permission under GNU GPL version 3 section 7:
* If you modify this Program, or any covered work, by linking or combining it
* with independent modules provided by the FPGA vendor only (this permission
* does not extend to any 3-rd party modules, "soft cores" or macros) under
* different license terms solely for the purpose of generating binary "bitstream"
* files and/or simulating the code, the copyright holders of this Program give
* you the right to distribute the covered work without those independent modules
* as long as the source code for them is available from the FPGA vendor free of
* charge, and there is no dependence on any encrypted modules for simulating of
* the combined code. This permission applies to you if the distributed code
* contains all the components and scripts required to completely simulate it
* with at least one of the Free Software programs.
*******************************************************************************/
`timescale 1ns/1ps
module cmprs_afi_mux_ptr_wresp(
input hclk, // global clock to run axi_hp @ 150MHz, shared by all compressor channels
// Write dual port 4x27 channel length RAM (shadows 1/2 of the similar RAM for main pointers)
input [26:0] length_di, // data to write per-channle buffer length in chunks
input [ 1:0] length_wa, // channel address to write lengths
input length_we, // write enable length data
input en, // 0 - resets, 0->1 resets all pointers. While reset allows write response
input [ 3:0] reset_pointers, // per-channel - reset pointers
input [ 2:0] chunk_ptr_ra, // chunk pointer read address {eof, chn[1:0]}
output [26:0] chunk_ptr_rd, // chunk pointer read data (non-registered
output reg [ 3:0] eof_written, // per-channel end of frame confirmed written to system memory by write response
// AFI write response channels
input afi_bvalid,
output afi_bready,
input [ 5:0] afi_bid // encodes channel, eof, and burst size minus 1 in chunks (0..3)
);
reg [3:0] reset_rq; // request to reset pointers when ready
reg [3:0] reset_rq_pri; // one-hot reset rq
wire [1:0] reset_rq_enc; // encoded reset_rq_pri
wire start_resetting_w;
reg [1:0] resetting; // resetting chunk_pointer and eof_pointer
wire [2:0] ptr_wa; // pointer memory write port address, msb - eof/current, 2 LSB - channel
reg ptr_we; // pointer memory write enable
reg [26:0] ptr_ram[0:7]; // pointer (current and eof) memory (in 32-byte chunks
wire [26:0] ptr_ram_di; // data to be written to ptr_ram
reg [26:0] len_ram[0:3]; // start chunk/num cunks in a buffer (write port @mclk)
reg [26:0] chunk_ptr_inc; // incremented by 1..4 chunk pointer
reg [27:0] chunk_ptr_rovr; // incremented chunk pointer, decremented by length (MSB - sign)
/// reg [ 3:0] busy; // one-hot busy stages (usually end with [3]
reg [ 4:0] busy; // one-hot busy stages (usually end with [4]
reg [ 4:0] id_r; // registered ID data - MSB is unused
reg [1:0] chn; // selected channel valid @busy[2]
reg eof; // eof register being written
reg last_burst_in_frame; // this response is for eof
reg [2:0] chunk_inc;
reg afi_bready_r; //
reg afi_bvalid_r; // make it slow;
wire pre_busy;
wire pre_we;
reg en_d; //enable delayed by 1 cycle
assign reset_rq_enc = {reset_rq_pri[3] | reset_rq_pri[2],
reset_rq_pri[3] | reset_rq_pri[1]};
assign ptr_ram_di= resetting[1] ? 27'b0 : (chunk_ptr_rovr[27] ? chunk_ptr_inc : chunk_ptr_rovr[26:0]);
assign ptr_wa = {eof,chn}; // valid @busy[2]
assign afi_bready = afi_bready_r;
/// assign pre_we= resetting[0] || // a pair of cycles to reset chunk pointer and frame chunk pointer
/// busy[2] || // always update chunk pointer
/// (busy[3] && last_burst_in_frame); // optionally update frame chunk pointer (same value)
assign pre_we= resetting[0] || // a pair of cycles to reset chunk pointer and frame chunk pointer
busy[3] || // always update chunk pointer
(busy[4] && last_burst_in_frame); // optionally update frame chunk pointer (same value)
/// assign pre_busy= afi_bvalid_r && en && !(|busy[1:0]) && !pre_we;
/// assign start_resetting_w = !afi_bvalid_r && en && !(|busy[1:0]) && !pre_we && (|reset_rq);
assign pre_busy= afi_bvalid_r && en && !(|busy[2:0]) && !pre_we;
assign start_resetting_w = !afi_bvalid_r && en && !(|busy[2:0]) && !pre_we && (|reset_rq);
assign chunk_ptr_rd = ptr_ram[chunk_ptr_ra];
always @ (posedge hclk) begin
en_d <= en;
// write length RAM
if (length_we) len_ram[length_wa] <= length_di;
afi_bvalid_r <= afi_bvalid;
afi_bready_r <= !en || pre_busy; // (!busy[0] && !pre_busy && !resetting[0] && !start_resetting_w);
// busy <= {busy[2:0], pre_busy}; // adjust bits
busy <= {busy[3:0], pre_busy}; // adjust bits
// id_r <= afi_bid[4:0]; // id_r[5] is never used - revoved
if (afi_bready && afi_bvalid) id_r <= afi_bid[4:0]; // id_r[5] is never used - revoved
if (start_resetting_w) reset_rq_pri <= {reset_rq[3] & ~(|reset_rq[2:0]),
reset_rq[2] & ~(|reset_rq[1:0]),
reset_rq[1] & ~reset_rq[0],
reset_rq[0]};
if (en && !en_d) reset_rq <= 4'hf; // request reset all
else reset_rq <= reset_pointers | (reset_rq & ~({4{resetting[0] &~ resetting[1]}} & reset_rq_pri));
if (!en) resetting <= 0;
else resetting <= {resetting[0], start_resetting_w | (resetting[0] & ~resetting[1])};
if (resetting == 2'b01) chn <= reset_rq_enc;
/// else if (busy[0]) chn <= id_r[0 +: 2];
else if (busy[1]) chn <= id_r[0 +: 2];
/// if (busy[0]) begin // first busy cycle
if (busy[1]) begin // first busy cycle
last_burst_in_frame <= id_r[2];
chunk_inc <= {1'b0,id_r[3 +:2]} + 1;
end
ptr_we <= pre_we;
if ((resetting == 2'b01) || busy[0]) eof <= 0;
else if (ptr_we) eof <= 1; // always second write cycle
// @@@ delay by 1 clk
/// if (busy[1]) chunk_ptr_inc <= ptr_ram[ptr_wa] + chunk_inc; // second clock of busy
/// if (busy[2]) chunk_ptr_rovr <={1'b0,chunk_ptr_inc} - {1'b0,len_ram[chn]}; // third clock of busy
if (busy[2]) chunk_ptr_inc <= ptr_ram[ptr_wa] + chunk_inc; // second clock of busy
if (busy[3]) chunk_ptr_rovr <={1'b0,chunk_ptr_inc} - {1'b0,len_ram[chn]}; // third clock of busy
// write to ptr_ram (1 or 2 locations - if eof)
if (ptr_we) ptr_ram[ptr_wa] <= ptr_ram_di;
// Watch write response channel, detect EOF IDs, generate eof_written* output signals
eof_written[0] <= afi_bvalid_r && afi_bready_r && (id_r[2:0]== 3'h4);
eof_written[1] <= afi_bvalid_r && afi_bready_r && (id_r[2:0]== 3'h5);
eof_written[2] <= afi_bvalid_r && afi_bready_r && (id_r[2:0]== 3'h6);
eof_written[3] <= afi_bvalid_r && afi_bready_r && (id_r[2:0]== 3'h7);
end
endmodule
x393-02965e50741e81c59c7d4889186c0b0cef4cb564/axi/cmprs_afi_mux_status.v 0000664 0000000 0000000 00000026201 12651560150 0024232 0 ustar 00root root 0000000 0000000 /*******************************************************************************
* Module: cmprs_afi_mux_status
* Date:2015-06-28
* Author: Andrey Filippov
* Description: prepare and send per-channel chunk pointer information as status
* Using 4 consecutive locations. Each channel can provide one of the 4 pointers:
* frame pointer in the write channel, current chunk pointer in the write channel
* and the same for the write response channel (confirmed written to the system
* memory
*
* Copyright (c) 2015 Elphel, Inc.
* cmprs_afi_mux_status.v is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* cmprs_afi_mux_status.v is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*
* Additional permission under GNU GPL version 3 section 7:
* If you modify this Program, or any covered work, by linking or combining it
* with independent modules provided by the FPGA vendor only (this permission
* does not extend to any 3-rd party modules, "soft cores" or macros) under
* different license terms solely for the purpose of generating binary "bitstream"
* files and/or simulating the code, the copyright holders of this Program give
* you the right to distribute the covered work without those independent modules
* as long as the source code for them is available from the FPGA vendor free of
* charge, and there is no dependence on any encrypted modules for simulating of
* the combined code. This permission applies to you if the distributed code
* contains all the components and scripts required to completely simulate it
* with at least one of the Free Software programs.
*******************************************************************************/
`timescale 1ns/1ps
module cmprs_afi_mux_status #(
parameter CMPRS_AFIMUX_STATUS_REG_ADDR= 'h20, //Uses 4 locations TODO: assign valid address
parameter CMPRS_AFIMUX_WIDTH = 26, // maximal for status: currently only works with 26)
parameter CMPRS_AFIMUX_CYCBITS = 3
) (
// input rst,
input hclk, // global clock to run axi_hp @ 150MHz, shared by all compressor channels
input mclk, // for command/status
input mrst, // @posedge mclk, sync reset
input hrst, // @posedge xclk, sync reset
// mclk domain
input [15:0] cmd_data, //
input [ 1:0] cmd_a, //
input status_we, //
input mode_we, //
output [7:0] status_ad, // status address/data - up to 5 bytes: A - {seq,status[1:0]} - status[2:9] - status[10:17] - status[18:25]
output status_rq, // input request to send status downstream
input status_start, // Acknowledge of the first status packet byte (address)
// hclk domain
input en, // 1- enable, 0 - reset
output reg [3:0] chunk_ptr_ra, // full pointer address - {eof,wresp,chn[1:0]}
input [CMPRS_AFIMUX_WIDTH-1:0] chunk_ptr_rd // pointer data
);
localparam MODE_WIDTH = 15;
reg [MODE_WIDTH-1:0] mode_data_mclk; // some bits unused
wire mode_we_hclk;
reg [7:0] mode_hclk;
reg [1:0] index;
reg [CMPRS_AFIMUX_CYCBITS-1:0] cntr;
reg [CMPRS_AFIMUX_WIDTH-1:0] chunk_ptr_hclk; // pointer data
reg [1:0] chunk_chn_hclk; // pointer channel
reg [4 * CMPRS_AFIMUX_WIDTH-1:0] status_data;
wire stb_w;
reg stb_r;
wire stb_mclk;
wire [31:0] ad;
wire [3:0] rq;
wire [3:0] start;
assign stb_w = en && (cntr==0);
always @ (posedge mclk) begin
if (mode_we) mode_data_mclk <= cmd_data[MODE_WIDTH-1:0];
end
always @ (posedge hclk) begin
if (mode_we_hclk) begin
if (mode_data_mclk[ 2]) mode_hclk[1:0] <= mode_data_mclk[ 1: 0];
if (mode_data_mclk[ 6]) mode_hclk[3:2] <= mode_data_mclk[ 5: 4];
if (mode_data_mclk[10]) mode_hclk[5:4] <= mode_data_mclk[ 9: 8];
if (mode_data_mclk[14]) mode_hclk[7:6] <= mode_data_mclk[13:12];
end
if (stb_mclk) status_data[chunk_chn_hclk * CMPRS_AFIMUX_WIDTH +: CMPRS_AFIMUX_WIDTH] <= chunk_ptr_hclk;
// if (stb_mclk && (chunk_chn_hclk == 2'h0)) status_data[0 * CMPRS_AFIMUX_WIDTH +: CMPRS_AFIMUX_WIDTH] <= chunk_ptr_hclk;
// if (stb_mclk && (chunk_chn_hclk == 2'h1)) status_data[1 * CMPRS_AFIMUX_WIDTH +: CMPRS_AFIMUX_WIDTH] <= chunk_ptr_hclk;
// if (stb_mclk && (chunk_chn_hclk == 2'h2)) status_data[2 * CMPRS_AFIMUX_WIDTH +: CMPRS_AFIMUX_WIDTH] <= chunk_ptr_hclk;
// if (stb_mclk && (chunk_chn_hclk == 2'h3)) status_data[3 * CMPRS_AFIMUX_WIDTH +: CMPRS_AFIMUX_WIDTH] <= chunk_ptr_hclk;
if (!en) {index,cntr} <= 0;
else {index,cntr} <= {index,cntr} + 1;
if (stb_w) begin
chunk_ptr_ra[1:0] <= index;
case (index)
2'h0: chunk_ptr_ra[3:2] <= mode_hclk[1:0] ^ 1; // so 0 will be eof, internal
2'h1: chunk_ptr_ra[3:2] <= mode_hclk[3:2] ^ 1;
2'h2: chunk_ptr_ra[3:2] <= mode_hclk[5:4] ^ 1;
2'h3: chunk_ptr_ra[3:2] <= mode_hclk[7:6] ^ 1;
endcase
end
stb_r <= stb_w;
if (stb_r) begin
chunk_ptr_hclk <= {chunk_ptr_rd[23:0],chunk_ptr_rd[25:24]}; // bits 0,1 are sent to 25:24
chunk_chn_hclk <= index;
end
end
pulse_cross_clock mode_we_hclk_i (.rst(mrst), .src_clk(mclk), .dst_clk(hclk), .in_pulse(mode_we), .out_pulse(mode_we_hclk),.busy());
pulse_cross_clock stb_mclk_i (.rst(hrst), .src_clk(hclk), .dst_clk(mclk), .in_pulse(stb_r), .out_pulse(stb_mclk), .busy());
status_router4 status_router4_i (
.rst (1'b0), // rst), // input
.clk (mclk), // input
.srst (mrst), // input
.db_in0 (ad[0 * 8 +: 8]), // input[7:0]
.rq_in0 (rq[0]), // input
.start_in0 (start[0]), // output
.db_in1 (ad[1 * 8 +: 8]), // input[7:0]
.rq_in1 (rq[1]), // input
.start_in1 (start[1]), // output
.db_in2 (ad[2 * 8 +: 8]), // input[7:0]
.rq_in2 (rq[2]), // input
.start_in2 (start[2]), // output
.db_in3 (ad[3 * 8 +: 8]), // input[7:0]
.rq_in3 (rq[3]), // input
.start_in3 (start[3]), // output
.db_out (status_ad), // output[7:0]
.rq_out (status_rq), // output
.start_out (status_start) // input
);
status_generate #(
.STATUS_REG_ADDR (CMPRS_AFIMUX_STATUS_REG_ADDR+0),
.PAYLOAD_BITS (CMPRS_AFIMUX_WIDTH)
) status_generate0_i (
.rst (1'b0), //rst), // input
.clk (mclk), // input
.srst (mrst), // input
.we (status_we && (cmd_a==0)), // input
.wd (cmd_data[7:0]), // input[7:0]
.status (status_data[0 * CMPRS_AFIMUX_WIDTH +: CMPRS_AFIMUX_WIDTH]), // input[25:0]
.ad (ad[0 * 8 +: 8]), // output[7:0]
.rq (rq[0]), // output
.start (start[0]) // input
);
status_generate #(
.STATUS_REG_ADDR (CMPRS_AFIMUX_STATUS_REG_ADDR+1),
.PAYLOAD_BITS (CMPRS_AFIMUX_WIDTH)
) status_generate1_i (
.rst (1'b0), //rst), // input
.clk (mclk), // input
.srst (mrst), // input
.we (status_we && (cmd_a==1)), // input
.wd (cmd_data[7:0]), // input[7:0]
.status (status_data[1 * CMPRS_AFIMUX_WIDTH +: CMPRS_AFIMUX_WIDTH]), // input[25:0]
.ad (ad[1 * 8 +: 8]), // output[7:0]
.rq (rq[1]), // output
.start (start[1]) // input
);
status_generate #(
.STATUS_REG_ADDR (CMPRS_AFIMUX_STATUS_REG_ADDR+2),
.PAYLOAD_BITS (CMPRS_AFIMUX_WIDTH)
) status_generate2_i (
.rst (1'b0), //rst), // input
.clk (mclk), // input
.srst (mrst), // input
.we (status_we && (cmd_a==2)), // input
.wd (cmd_data[7:0]), // input[7:0]
.status (status_data[2 * CMPRS_AFIMUX_WIDTH +: CMPRS_AFIMUX_WIDTH]), // input[25:0]
.ad (ad[2 * 8 +: 8]), // output[7:0]
.rq (rq[2]), // output
.start (start[2]) // input
);
status_generate #(
.STATUS_REG_ADDR (CMPRS_AFIMUX_STATUS_REG_ADDR+3),
.PAYLOAD_BITS (CMPRS_AFIMUX_WIDTH)
) status_generate3_i (
.rst (1'b0), // rst), // input
.clk (mclk), // input
.srst (mrst), // input
.we (status_we && (cmd_a==3)), // input
.wd (cmd_data[7:0]), // input[7:0]
.status (status_data[3 * CMPRS_AFIMUX_WIDTH +: CMPRS_AFIMUX_WIDTH]), // input[25:0]
.ad (ad[3 * 8 +: 8]), // output[7:0]
.rq (rq[3]), // output
.start (start[3]) // input
);
endmodule
x393-02965e50741e81c59c7d4889186c0b0cef4cb564/axi/histogram_saxi.v 0000664 0000000 0000000 00000064633 12651560150 0023027 0 ustar 00root root 0000000 0000000 /*******************************************************************************
* Module: histogram_saxi
* Date:2015-06-04
* Author: Andrey Filippov
* Description: Histograms transfer to the system memory over S_AXI
*
* Copyright (c) 2015 Elphel, Inc.
* histogram_saxi.v is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* histogram_saxi.v is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*
* Additional permission under GNU GPL version 3 section 7:
* If you modify this Program, or any covered work, by linking or combining it
* with independent modules provided by the FPGA vendor only (this permission
* does not extend to any 3-rd party modules, "soft cores" or macros) under
* different license terms solely for the purpose of generating binary "bitstream"
* files and/or simulating the code, the copyright holders of this Program give
* you the right to distribute the covered work without those independent modules
* as long as the source code for them is available from the FPGA vendor free of
* charge, and there is no dependence on any encrypted modules for simulating of
* the combined code. This permission applies to you if the distributed code
* contains all the components and scripts required to completely simulate it
* with at least one of the Free Software programs.
*******************************************************************************/
`timescale 1ns/1ps
// Number of histograms per sensor is now statically defined by NUM_FRAME_BITS
// It may be modified to both reduce this number (by masking) or increase ( by
// keeping pointer locally)
module histogram_saxi#(
parameter HIST_SAXI_ADDR = 'h380, // 16 locations to write 20 bits of a 4KB page for the histogram
parameter HIST_SAXI_ADDR_MASK = 'h7f0,
parameter HIST_SAXI_MODE_ADDR = 'h390,
parameter HIST_SAXI_MODE_WIDTH = 8,
parameter HIST_SAXI_EN = 0,
parameter HIST_SAXI_NRESET = 1,
parameter HIST_CONFIRM_WRITE = 2, // wait write confirmation for each block
parameter HIST_SAXI_AWCACHE = 4, // Write 4'h3 there, //..7 cache mode (4 bits, default 4'h3)
parameter HIST_SAXI_MODE_ADDR_MASK = 'h7ff,
// parameter HIST_SAXI_STATUS_REG = 'h34,
parameter NUM_FRAME_BITS = 4 // number of bits use for frame number
`ifdef DEBUG_RING
,parameter DEBUG_CMD_LATENCY = 2
`endif
)(
// input rst,
input mclk, // for command/status
input aclk, // global clock to run s_axi (@150MHz?)
input mrst, // @posedge mclk, sync reset
input arst, // @posedge aclk, sync reset
// sensor 0, data valid @posedge mclk
input [NUM_FRAME_BITS-1:0] frame0, // frame number for which the histogram is provided
input hist_request0, // request to transfer a burst
output hist_grant0, // request to transfer over S_AXI granted
input [1:0] hist_chn0, // histogram (sub) channel, valid with request and transfer
input hist_dvalid0, // output data valid - active when sending a burst
input [31:0] hist_data0, // output[31:0] histogram data
// sensor 1, data valid @posedge mclk
input [NUM_FRAME_BITS-1:0] frame1, // frame number for which the histogram is provided
input hist_request1, // request to transfer a burst
output hist_grant1, // request to transfer over S_AXI granted
input [1:0] hist_chn1, // histogram (sub) channel, valid with request and transfer
input hist_dvalid1, // output data valid - active when sending a burst
input [31:0] hist_data1, // output[31:0] histogram data
// sensor 2, data valid @posedge mclk
input [NUM_FRAME_BITS-1:0] frame2, // frame number for which the histogram is provided
input hist_request2, // request to transfer a burst
output hist_grant2, // request to transfer over S_AXI granted
input [1:0] hist_chn2, // histogram (sub) channel, valid with request and transfer
input hist_dvalid2, // output data valid - active when sending a burst
input [31:0] hist_data2, // output[31:0] histogram data
// sensor 3, data valid @posedge mclk
input [NUM_FRAME_BITS-1:0] frame3, // frame number for which the histogram is provided
input hist_request3, // request to transfer a burst
output hist_grant3, // request to transfer over S_AXI granted
input [1:0] hist_chn3, // histogram (sub) channel, valid with request and transfer
input hist_dvalid3, // output data valid - active when sending a burst
input [31:0] hist_data3, // output[31:0] histogram data
// command interface
input [7:0] cmd_ad, // byte-serial command address/data (up to 6 bytes: AL-AH-D0-D1-D2-D3
input cmd_stb, // strobe (with first byte) for the command a/d
// S_AXI inerface w/o read channel
// write address
output [31:0] saxi_awaddr, // AXI PS Slave GP0 AWADDR[31:0], input
output saxi_awvalid, // AXI PS Slave GP0 AWVALID, input
input saxi_awready, // AXI PS Slave GP0 AWREADY, output
output [5:0] saxi_awid, // AXI PS Slave GP0 AWID[5:0], input
output [1:0] saxi_awlock, // AXI PS Slave GP0 AWLOCK[1:0], input
output [ 3:0] saxi_awcache, // AXI PS Slave GP0 AWCACHE[3:0], input
output [ 2:0] saxi_awprot, // AXI PS Slave GP0 AWPROT[2:0], input
output [ 3:0] saxi_awlen, // AXI PS Slave GP0 AWLEN[3:0], input
output [ 1:0] saxi_awsize, // AXI PS Slave GP0 AWSIZE[1:0], input
output [ 1:0] saxi_awburst, // AXI PS Slave GP0 AWBURST[1:0], input
output [ 3:0] saxi_awqos, // AXI PS Slave GP0 AWQOS[3:0], input
// write data
output [31:0] saxi_wdata, // AXI PS Slave GP0 WDATA[31:0], input
output saxi_wvalid, // AXI PS Slave GP0 WVALID, input
input saxi_wready, // AXI PS Slave GP0 WREADY, output
output [ 5:0] saxi_wid, // AXI PS Slave GP0 WID[5:0], input
output saxi_wlast, // AXI PS Slave GP0 WLAST, input
output [ 3:0] saxi_wstrb, // AXI PS Slave GP0 WSTRB[3:0], input
// write response
input saxi_bvalid, // AXI PS Slave GP0 BVALID, output
output saxi_bready, // AXI PS Slave GP0 BREADY, input
input [ 5:0] saxi_bid, // AXI PS Slave GP0 BID[5:0], output //TODO: Update range !!! // @SuppressThisWarning VEditor unused
input [ 1:0] saxi_bresp // AXI PS Slave GP0 BRESP[1:0], output // @SuppressThisWarning VEditor unused
`ifdef DEBUG_RING
,output debug_do, // output to the debug ring
input debug_sl, // 0 - idle, (1,0) - shift, (1,1) - load
input debug_di // input from the debug ring
`endif
);
/*
`ifdef DEBUG_RING
localparam DEBUG_RING_LENGTH = 1; // for now - just connect the histogram(s) module(s)
wire [DEBUG_RING_LENGTH:0] debug_ring; // TODO: adjust number of bits
assign debug_do = debug_ring[0];
assign debug_ring[DEBUG_RING_LENGTH] = debug_di;
`endif
*/
localparam ATTRIB_WIDTH = NUM_FRAME_BITS + 4 +2;
reg [HIST_SAXI_MODE_WIDTH-1:0] mode;
wire en = mode[HIST_SAXI_EN] & mode[HIST_SAXI_NRESET];
reg [3:0] awcache_mode;
reg confirm_write;
wire nreset = mode[HIST_SAXI_NRESET];
wire we_mode;
wire we_addr;
wire [31:0] cmd_data;
wire [3:0] cmd_wa;
reg [19:0] hist_start_page[0:15]; // start page (4KB) of the per-sensor histogram system memory
reg [2:0] burst;
wire [3:0] pri_rq;
reg [2:0] enc_rq;
wire busy_w;
reg busy_r;
reg [1:0] mux_sel;
wire start_w;
reg started;
reg [4*ATTRIB_WIDTH -1:0] attrib; // to hold frame number, sensor number and burst (color) for the histograms in the buffer
wire page_sent_mclk; // page sent over saxi - pulse in mclk domain
reg [1:0] page_wr; // page number being written
reg [7:0] page_wa; // 32-bit word address in page being written
reg [2:0] pages_in_buf_wr; // pages in buffer (as seen from write side), 0..4
wire buf_full = pages_in_buf_wr[2];
wire dav;
reg dav_r;
wire burst_done_w;
reg grant;
wire [31:0] din;
reg [31:0] din_r;
wire rq_in;
wire [1:0] sub_chn_w;
reg [1:0] sub_chn_r;
wire [NUM_FRAME_BITS-1:0] frame_w; // frame number for which the histogram is provided
reg [NUM_FRAME_BITS-1:0] frame_r; //
reg wr_attr; // in the beginning of the burst - write attributes to FIFO
wire [3:0] chn_sel;
reg [3:0] chn_grant;
// aclk domain
wire page_sent_aclk; // page sent over saxi
reg preen_aclk;
reg en_aclk;
reg prenreset_aclk;
reg nreset_aclk;
wire page_written_aclk;
reg [2:0] pages_in_buf_rd; // pages in buffer (as seen from read side), 0..4
reg [1:0] page_rd; // page number being read
reg [7:0] page_ra; // 32-bit word address in page being read
wire buf_empty = (pages_in_buf_rd==0);
reg [3:0] block_run; // TODO: adjust width
wire block_start_w;
reg [3:0] block_start_r;
wire block_end;
reg [NUM_FRAME_BITS + 4 +2 -1:0] attrib_r;
wire [3:0] attrib_chn;
wire [NUM_FRAME_BITS-1:0] attrib_frame;
wire [1:0] attrib_color;
reg [19:0] hist_start_page_r;
reg [31:10] hist_start_addr; // higher bits of the system memory address of the histogram (1024 bytes) start
reg [31: 6] start_addr_r; // higher bits of the system memory address of the saxi burst start address
wire saxi_start_burst_w;
reg first_burst;
wire [31:0] inter_buf_data; // data between bram buffer and a small FIFO
reg [3:0] wburst_cntr; // count words in output data burst (using max==16)
reg [4:0] num_bursts_in_buf; // number of 16-word bursts written no buffer but not yet sent to SAXI
reg [4:0] num_bursts_pending; // number of 16-word bursts written no buffer but not yet confirmed from SAXI
wire fifo_nempty;
wire fifo_half_full;
reg [2:0] buf_re; // {fifo_we, buf_regen, buf_re}
wire buf_re_w;
wire fifo_re;
reg saxi_bvalid_r;
reg page_read_run; // reading buffer page until page_ra reads 'hff
// reg [9:0] buf_raddr; // nuffer read address {page[1:0], addr [7:0]}
`ifdef DEBUG_RING
reg [7:0] extra_wa;
reg [7:0] extra_ra;
reg [15:0] num_addr_saxi;
reg [15:0] num_data_saxi;
always @ (posedge mclk) begin
if (!en) extra_wa <= 0;
else if (burst_done_w) extra_wa <= extra_wa + 1;
end
always @ (posedge aclk) begin
if (!en_aclk) extra_ra <= 0;
else if (page_sent_aclk) extra_ra <= extra_ra + 1;
if (!nreset_aclk) num_addr_saxi <= 0;
else if (saxi_awvalid && saxi_awready) num_addr_saxi <= num_addr_saxi + 1;
if (!nreset_aclk) num_data_saxi <= 0;
else if (saxi_wvalid && saxi_wready) num_data_saxi <= num_data_saxi + 1;
end
debug_slave #(
.SHIFT_WIDTH (160),
.READ_WIDTH (160),
.WRITE_WIDTH (32),
.DEBUG_CMD_LATENCY (DEBUG_CMD_LATENCY)
) debug_slave_i (
.mclk (mclk), // input
.mrst (mrst), // input
.debug_di (debug_di), // input
.debug_sl (debug_sl), // input
.debug_do (debug_do), // output
.rd_data ({
num_addr_saxi[15:0],
num_data_saxi[15:0],
extra_wa[7:0],page_wa[7:0],
extra_ra[7:0],page_ra[7:0],
// 16'b0,
3'b0,num_bursts_in_buf,
3'b0,num_bursts_pending,
page_wr[1:0],page_rd[1:0],3'b0, saxi_wlast,
saxi_wready, saxi_wvalid, saxi_wid[5:0],
6'b0,saxi_awready,saxi_awvalid,
saxi_awlock[1:0], saxi_awid[5:0],
saxi_awcache[3:0], 1'b0,saxi_awprot[2:0],
saxi_awlen[3:0], saxi_awburst[1:0], saxi_awsize[1:0],
2'b0 ,hist_chn0[1:0],frame0[3:0],
chn_grant[3:0],
1'b0, busy_w, busy_r, started,
1'b0, burst[2:0], 1'b0,pages_in_buf_wr[2:0],
start_w, enc_rq[2:0], pri_rq[3:0]
}), // input[31:0]
.wr_data (), // output[31:0] - not used
.stb () // output - not used
);
`endif
assign pri_rq = {hist_request3 & ~hist_request2 & ~hist_request1 & ~hist_request0,
hist_request2 & ~hist_request1 & ~ hist_request0,
hist_request1 & ~hist_request0,
hist_request0};
assign busy_w = |burst;
assign start_w = enc_rq[2] && !busy_r && !started;
assign chn_sel = {mux_sel[1] & mux_sel[0], mux_sel[1] & ~mux_sel[0], ~mux_sel[1] & mux_sel[0], ~mux_sel[1] & ~mux_sel[0]};
assign dav = mux_sel[1] ? (mux_sel[0] ? hist_dvalid3 : hist_dvalid2) : (mux_sel[0] ? hist_dvalid1 : hist_dvalid0);
assign din = mux_sel[1] ? (mux_sel[0] ? hist_data3 : hist_data2) : (mux_sel[0] ? hist_data1 : hist_data0);
assign rq_in = mux_sel[1] ? (mux_sel[0] ? hist_request3 : hist_request2) : (mux_sel[0] ? hist_request1 : hist_request0);
assign sub_chn_w = mux_sel[1] ? (mux_sel[0] ? hist_chn3 : hist_chn2) : (mux_sel[0] ? hist_chn1 : hist_chn0);
assign frame_w = mux_sel[1] ? (mux_sel[0] ? frame3 : frame2) : (mux_sel[0] ? frame1 : frame0);
assign burst_done_w = dav_r && !dav && en;
assign hist_grant0 = chn_grant[0];
assign hist_grant1 = chn_grant[1];
assign hist_grant2 = chn_grant[2];
assign hist_grant3 = chn_grant[3];
assign block_start_w = !(|block_run[2:0]) && !buf_empty && en_aclk ; // make it finish all started transactions
assign attrib_chn = attrib_r[NUM_FRAME_BITS+2+:4];
assign attrib_frame = attrib_r[2+:NUM_FRAME_BITS];
assign attrib_color = attrib_r[1:0];
assign saxi_start_burst_w = saxi_awvalid && saxi_awready;
assign saxi_awaddr = {start_addr_r[31:6],6'b0};
assign saxi_awvalid = (|start_addr_r[9:6]) || first_burst;
//{enc_rq[1:0], sub_chn_r, frame_r, burst[1:0]}
// assign block_end= ???;
assign saxi_awid[5:0] = {attrib_chn,attrib_color};
// TODO: assign static values:
assign saxi_awlock= 2'h0; // AXI PS Slave GP0 AWLOCK[1:0], input
assign saxi_awcache= awcache_mode; // 4'h3; // AXI PS Slave GP0 AWCACHE[3:0], input
assign saxi_awprot= 3'h0; // AXI PS Slave GP0 AWPROT[2:0], input
assign saxi_awlen= 4'hf; // 16 words AXI PS Slave GP0 AWLEN[3:0], input
assign saxi_awsize= 2'h2; // 4 bytes; AXI PS Slave GP0 AWSIZE[1:0], input
assign saxi_awburst= 2'h1; // Increment address bursts AXI PS Slave GP0 AWBURST[1:0], input
assign saxi_awqos= 4'h0; // AXI PS Slave GP0 AWQOS[3:0], input
// assign saxi_wvalid = en_aclk && fifo_nempty && (|num_bursts_in_buf);
assign saxi_wvalid = en_aclk && fifo_nempty; // && (|num_bursts_in_buf); - not needed, buffer read will stop at address 'hff
assign saxi_bready = 1'b1; // always ready
assign saxi_wlast = &wburst_cntr;
assign saxi_wid[5:0] = {attrib_chn,attrib_color}; // TODO: Verify they match FIFO output (otherwise save them in FIFO too) block_start waits for FIFO?
assign saxi_wstrb = 4'hf; // All bytes
// TODO: Maybe reduce pause between 16-burst pages? Allow some overlap?
assign buf_re_w = en_aclk && (|pages_in_buf_rd) && !fifo_half_full && !(&page_ra) && page_read_run; // will stay off until next page
assign fifo_re= saxi_wvalid && saxi_wready;
// currently waiting for SAXI to get confirmnation of all data in the current page before proceeding to the next
//
// assign confirm_write
assign block_end = !(|block_start_r) && (confirm_write? (!(|num_bursts_pending)):(!(|num_bursts_in_buf)));
// assign block_end = !(|block_start_r) && !(|num_bursts_pending);
assign page_sent_aclk = block_run[1] && !block_run[0];
// command interface
always @(posedge mclk) begin
if (mrst) mode <= 0;
else if (we_mode) mode <= cmd_data[HIST_SAXI_MODE_WIDTH-1:0];
end
always @(posedge mclk) begin
if (we_addr) hist_start_page[cmd_wa] <= cmd_data[19:0];
// en_aclk <= en;
end
// mclk (write) port of the buffer
// once started, will read full histogram from the same sensor
// Buffer write logic
always @(posedge mclk) begin
enc_rq <= {|pri_rq, pri_rq[3] | pri_rq[2], pri_rq[3] | pri_rq[1]};
busy_r <= busy_w;
if (!en || busy_r) started <= 0;
else if (enc_rq[2]) started <= 1;
if (start_w) mux_sel <= enc_rq[1:0];
if (!en) dav_r <= 0;
else dav_r <= dav;
din_r <= din;
sub_chn_r <=sub_chn_w;
frame_r <= frame_w;
if (!en) burst <= 0;
else if (start_w) burst <= 4;
else if (burst_done_w) burst <= burst + 1;
if (!en) page_wr <= 0;
else if (burst_done_w) page_wr <= page_wr + 1;
if (!en) pages_in_buf_wr <= 0;
else if ( burst_done_w && !page_sent_mclk) pages_in_buf_wr <= pages_in_buf_wr + 1;
else if (!burst_done_w && page_sent_mclk) pages_in_buf_wr <= pages_in_buf_wr - 1;
// grant <= en && rq_in && !buf_full && (!started || busy_r); // delay grant until chn_sel is set (first cycle of started)
grant <= en && rq_in && !buf_full && (grant || busy_r); // delay grant until chn_sel is set (first cycle of started)
if (!en) chn_grant <= 0;
else chn_grant <= {4{grant}} & chn_sel;
wr_attr <= en && !dav_r && dav;
if (wr_attr) attrib[page_wr * ATTRIB_WIDTH +: ATTRIB_WIDTH] <= {enc_rq[1:0], sub_chn_r, frame_r, burst[1:0]};
if (!dav_r) page_wa <= 0;
else page_wa <= page_wa + 1;
end
// Buffer read, SAXI send logic
always @(posedge aclk) begin
preen_aclk <= en;
en_aclk <= preen_aclk && en;
prenreset_aclk <= nreset;
nreset_aclk <= prenreset_aclk && nreset;
if (!en_aclk) page_rd <= 0;
else if (page_sent_aclk) page_rd <= page_rd + 1;
if (!en_aclk || block_start_r[0]) page_ra <= 0;
else if (buf_re[0]) page_ra <= page_ra + 1;
if (!en_aclk) page_read_run <= 0;
else page_read_run <= block_start_r[1] || (page_read_run && !(&page_ra)); // until page_ra is 8'hff
if (!en_aclk) pages_in_buf_rd <= 0;
else if ( page_written_aclk && !page_sent_aclk) pages_in_buf_rd <= pages_in_buf_rd + 1;
else if (!page_written_aclk && page_sent_aclk) pages_in_buf_rd <= pages_in_buf_rd - 1;
if (!nreset_aclk) block_run <= 0;
else block_run <= {block_run[2:0],block_start_w | (block_run[0] & ~ block_end)};
if (!nreset_aclk) block_start_r <= 0;
// else block_start_r <= {block_run[2:0], block_start_w};
else block_start_r <= {block_start_r[2:0], block_start_w};
if (block_start_r[0]) attrib_r <= attrib[page_rd * ATTRIB_WIDTH +: ATTRIB_WIDTH];
if (block_start_r[1]) hist_start_page_r <= hist_start_page[attrib_chn];
if (block_start_r[2]) hist_start_addr[31:12] <= hist_start_page_r + attrib_frame;
if (block_start_r[2]) hist_start_addr[11:10] <= attrib_color;
if (arst || block_start_r[3]) start_addr_r[31:6] <= {hist_start_addr[31:10], 4'b0};
else if (saxi_start_burst_w) start_addr_r[31:6] <= start_addr_r[31:6] + 1;
if (!nreset_aclk) first_burst <= 0;
else if (block_start_r[3]) first_burst <= 1; // block_start_r[3] - same as start_addr_r set
else if (saxi_start_burst_w) first_burst <= 0;
if (block_start_r[0]) awcache_mode <= mode[HIST_SAXI_AWCACHE+:4];
if (block_start_r[0]) confirm_write <= mode[HIST_CONFIRM_WRITE];
// wdata channel
saxi_bvalid_r <=saxi_bvalid;
buf_re <= {buf_re[1:0],buf_re_w};
if (!nreset_aclk) wburst_cntr <= 0;
else if (fifo_re) wburst_cntr <= wburst_cntr +1;
if (block_start_r[0]) num_bursts_in_buf <= 5'h10; // change [2]?
else if (saxi_wlast && fifo_re) num_bursts_in_buf <= num_bursts_in_buf - 1;
if (block_start_r[0]) num_bursts_pending <= 5'h10; // change [2]?
else if (saxi_bvalid_r) num_bursts_pending <= num_bursts_pending - 1;
end
pulse_cross_clock pulse_cross_clock_page_sent_i (
.rst (arst), // input
.src_clk (aclk), // input
.dst_clk (mclk), // input
.in_pulse (page_sent_aclk), // input
.out_pulse (page_sent_mclk), // output
.busy() // output
);
pulse_cross_clock pulse_cross_clock_page_written_aclk_i (
.rst (mrst), // input
.src_clk (mclk), // input
.dst_clk (aclk), // input
.in_pulse (burst_done_w), // input
.out_pulse (page_written_aclk), // output
.busy() // output
);
//burst_done_w
cmd_deser #(
.ADDR (HIST_SAXI_ADDR),
.ADDR_MASK (HIST_SAXI_ADDR_MASK),
.NUM_CYCLES (6),
.ADDR_WIDTH (4),
.DATA_WIDTH (32),
.ADDR1 (HIST_SAXI_MODE_ADDR),
.ADDR_MASK1 (HIST_SAXI_MODE_ADDR_MASK),
.ADDR2 (0),
.ADDR_MASK2 (0)
) cmd_deser_histogram_saxi_i (
.rst (1'b0), // input
.clk (mclk), // input
.srst (mrst), // input
.ad (cmd_ad), // input[7:0]
.stb (cmd_stb), // input
.addr (cmd_wa), // output[3:0]
.data (cmd_data), // output[31:0]
.we ({we_mode,we_addr}) // output
);
ram_var_w_var_r #(
.REGISTERS(1),
.LOG2WIDTH_WR(5),
.LOG2WIDTH_RD(5),
.DUMMY(0)
) ram_var_w_var_r_i (
.rclk (aclk), // input
.raddr ({page_rd[1:0],page_ra[7:0]}), // input[9:0]
.ren (buf_re[0]), // input
.regen (buf_re[1]), // input
.data_out (inter_buf_data), // output[31:0]
.wclk (mclk), // input
.waddr ({page_wr[1:0], page_wa[7:0]}), // input[9:0]
.we (dav_r), // input
.web (8'hff), // input[7:0]
.data_in (din_r) // input[31:0]
);
// Small extra FIFO to tolerate ram_var_w_var_r latency
fifo_same_clock #(
.DATA_WIDTH(32),
.DATA_DEPTH(4)
) fifo_same_clock_i (
.rst (1'b0), // input
.clk (aclk), // input
.sync_rst (!en_aclk), // input
.we (buf_re[2]), // input
.re (fifo_re), // input
.data_in (inter_buf_data), // input[31:0]
.data_out (saxi_wdata), // output[31:0]
.nempty (fifo_nempty), // output
.half_full (fifo_half_full) // output reg
);
endmodule
x393-02965e50741e81c59c7d4889186c0b0cef4cb564/axi/macros393.v 0000664 0000000 0000000 00000003141 12651560150 0021514 0 ustar 00root root 0000000 0000000 /*
** -----------------------------------------------------------------------------**
** macros353.v
**
** temporary, modules to be moved
**
** Copyright (C) 2002 Elphel, Inc
**
** -----------------------------------------------------------------------------**
** This file is part of X353
** X353 is free software - hardware description language (HDL) code.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see .
** -----------------------------------------------------------------------------**
**
*/
module ram_WxD
#(
parameter integer DATA_WIDTH=16,
parameter integer DATA_DEPTH=4,
parameter integer DATA_2DEPTH=(1<