lint
diff --git a/configure.py b/configure.py
index cc0ce65..28479fb 100755
--- a/configure.py
+++ b/configure.py
@@ -6,7 +6,6 @@
from signal import signal, SIGPIPE, SIG_DFL
signal(SIGPIPE, SIG_DFL)
-filler_project_url = 'https://github.com/mattvenn/wokwi_filler'
tmp_dir = '/tmp/tt'
DEFAULT_NUM_PROJECTS = 498
@@ -15,8 +14,9 @@
projects_db = "projects.pkl"
- def __init__(self, update_cache=False, update_single=None):
+ def __init__(self, update_cache=False, update_single=None, test=False):
self.default_project = 0
+ self.test = test
if update_cache:
self.update_cache(update_single)
else:
@@ -92,12 +92,22 @@
def get_wokwi_ids(self):
return self.wokwi_ids
+ def get_giturl(self, id):
+ try:
+ return self.get_project_urls()[id]
+ except IndexError:
+ return self.get_project_urls()[self.default_project]
+
@classmethod
def build_wokwi_url(Project, wokwi_id):
return "https://wokwi.com/projects/{}".format(wokwi_id)
def get_project_urls(self):
- from project_urls import project_urls
+ if self.test:
+ from project_urls_test import project_urls, filler_project_url
+ else:
+ from project_urls import project_urls, filler_project_url
+
return [filler_project_url] + project_urls
# the latest artifact isn't necessarily the one related to the latest commit, as github
@@ -149,7 +159,7 @@
exit(1)
else:
# only get artifacts called GDS
- artifacts = [ a for a in data['artifacts'] if a['name'] == 'GDS']
+ artifacts = [a for a in data['artifacts'] if a['name'] == 'GDS']
logging.debug("found {} artifacts".format(len(artifacts)))
download_url = Projects.get_most_recent_action_url(commits, artifacts)
@@ -294,13 +304,14 @@
.slow_clk (io_out[10]),
.set_clk_div (io_in[11]),
- .scan_clk (clk[0]),
+ .scan_clk_out (clk[0]),
+ .scan_clk_in (clk[NUM_MACROS]),
.scan_data_out (data[0]),
.scan_data_in (data[NUM_MACROS]),
.scan_select (scan[0]),
.scan_latch_en (latch[0]),
- .la_scan_clk (la_data_in[0]),
+ .la_scan_clk_in (la_data_in[0]),
.la_scan_data_in (la_data_in[1]),
.la_scan_data_out (la_data_out[0]),
.la_scan_select (la_data_in[2]),
@@ -313,6 +324,7 @@
"""
lesson_template = """
+ // {giturl}
{name} #(.NUM_IOS(8)) {instance} (
.clk_in (clk [{id}]),
.data_in (data [{id}]),
@@ -337,7 +349,7 @@
for i in range(self.num_projects):
logging.debug("instance {} {}".format(i, self.projects.get_macro_name(i)))
# instantiate template
- instance = lesson_template.format(instance=self.projects.get_macro_instance(i), name=self.projects.get_macro_name(i), id=i, next_id=i + 1)
+ instance = lesson_template.format(giturl=self.projects.get_giturl(i), instance=self.projects.get_macro_instance(i), name=self.projects.get_macro_name(i), id=i, next_id=i + 1)
fh.write(instance)
fh.write(post)
@@ -382,6 +394,7 @@
parser.add_argument('--update-single', help='only fetch a single repo for debug')
parser.add_argument('--update-caravel', help='configure caravel for build', action='store_const', const=True)
parser.add_argument('--limit-num-projects', help='only configure for the first n projects', type=int, default=DEFAULT_NUM_PROJECTS)
+ parser.add_argument('--test', help='use test projects', action='store_const', const=True)
parser.add_argument('--debug', help="debug logging", action="store_const", dest="loglevel", const=logging.DEBUG, default=logging.INFO)
args = parser.parse_args()
@@ -402,7 +415,7 @@
ch.setFormatter(log_format)
log.addHandler(ch)
- projects = Projects(update_cache=args.update_projects, update_single=args.update_single)
+ projects = Projects(update_cache=args.update_projects, test=args.test, update_single=args.update_single)
caravel = CaravelConfig(projects, num_projects=args.limit_num_projects)
if args.update_caravel:
diff --git a/openlane/scan_controller/base.sdc b/openlane/scan_controller/base.sdc
new file mode 100644
index 0000000..7324dd0
--- /dev/null
+++ b/openlane/scan_controller/base.sdc
@@ -0,0 +1,70 @@
+# SDC file, in TCL
+# declare clocks and relationships between them
+# Create main clock of the scan controller, locally named the same clock
+create_clock [get_ports $::env(CLOCK_PORT)] -name $::env(CLOCK_PORT) -period $::env(CLOCK_PERIOD)
+
+# Create our generated clock that drives the scan chain
+# derived from clk, present on edge 3 5 7
+# multicycle path, only data transition on falling edge of scan clock
+create_generated_clock -edges {3 5 7} -source $::env(CLOCK_PORT) -name clk_scan_out [get_ports scan_clk_out]
+set_multicycle_path -start -hold -from [get_clocks $::env(CLOCK_PORT)] -to [get_clocks clk_scan_out] 1
+
+# Create feedback clock - scan_clk_in. we don't know what it will arrive, but we know the period
+create_clock [get_ports scan_clk_in] -name clk_scan_in -period [expr {$::env(CLOCK_PERIOD) * 2}]
+
+# CDC
+# receiving data into shift register and clocked by clk_scan_in
+# constrain to a reasonable range
+set_min_delay 0.25 -from [get_clocks clk_scan_in] -to [get_clocks $::env(CLOCK_PORT)]
+set_max_delay [expr {$::env(CLOCK_PERIOD) / 2}] -from [get_clocks clk_scan_in] -to [get_clocks $::env(CLOCK_PORT)]
+
+# IO delays
+# Scan chain input 0.5 ns setup time, 0.5 ns hold time
+set_input_delay -min 0.5 -clock [get_clocks clk_scan_in] [get_ports {scan_data_in}]
+set_input_delay -max 0.5 -clock [get_clocks clk_scan_in] [get_ports {scan_data_in}]
+
+# Scan chain output 1.5 ns setup time, 1.5 ns hold time
+# scan_data_out cannot change in this window around clk_scan_out rising edge
+set_output_delay -min -1.5 -clock [get_clocks clk_scan_out] [get_ports {scan_data_out}]
+set_output_delay -max 1.5 -clock [get_clocks clk_scan_out] [get_ports {scan_data_out}]
+
+# Limit the max output delay on other outputs
+# Probably not important, but useful because then these paths will be reported
+set_output_delay -max 1.5 -clock [get_clocks $::env(CLOCK_PORT)] [get_ports {scan_select scan_latch_en}]
+
+# All the other IOs we consider asynchronous so ... no point in constraining
+# https://open-source-silicon.slack.com/archives/C02K4RD241Y/p1661983399157329?thread_ts=1661978191.926169&cid=C02K4RD241Y
+set_false_path -from [get_ports {active_select inputs set_clk_div la_* driver_sel}]
+
+
+# Misc
+# most copied from default OpenLane SDC
+set_max_fanout $::env(SYNTH_MAX_FANOUT) [current_design]
+
+if { ![info exists ::env(SYNTH_CLK_DRIVING_CELL)] } {
+ set ::env(SYNTH_CLK_DRIVING_CELL) $::env(SYNTH_DRIVING_CELL)
+}
+
+if { ![info exists ::env(SYNTH_CLK_DRIVING_CELL_PIN)] } {
+ set ::env(SYNTH_CLK_DRIVING_CELL_PIN) $::env(SYNTH_DRIVING_CELL_PIN)
+}
+
+set_driving_cell -lib_cell $::env(SYNTH_DRIVING_CELL) -pin $::env(SYNTH_DRIVING_CELL_PIN) [get_ports {scan_data_in}]
+set_driving_cell -lib_cell $::env(SYNTH_CLK_DRIVING_CELL) -pin $::env(SYNTH_CLK_DRIVING_CELL_PIN) [get_ports "$::env(CLOCK_PORT) scan_clk_in"]
+
+set cap_load [expr $::env(SYNTH_CAP_LOAD) / 1000.0]
+puts "\[INFO\]: Setting load to: $cap_load"
+set_load $cap_load [all_outputs]
+
+# clock jitter
+puts "\[INFO\]: Setting clock uncertainity to: $::env(SYNTH_CLOCK_UNCERTAINITY)"
+set_clock_uncertainty $::env(SYNTH_CLOCK_UNCERTAINITY) [get_clocks "$::env(CLOCK_PORT) clk_scan_in clk_scan_out"]
+
+# clock slew
+puts "\[INFO\]: Setting clock transition to: $::env(SYNTH_CLOCK_TRANSITION)"
+set_clock_transition $::env(SYNTH_CLOCK_TRANSITION) [get_clocks "$::env(CLOCK_PORT) clk_scan_in clk_scan_out"]
+
+# make everything worse by SYNTH_TIMING_DERATE
+puts "\[INFO\]: Setting timing derate to: [expr {$::env(SYNTH_TIMING_DERATE) * 100}] %"
+set_timing_derate -early [expr {1-$::env(SYNTH_TIMING_DERATE)}]
+set_timing_derate -late [expr {1+$::env(SYNTH_TIMING_DERATE)}]
diff --git a/openlane/scan_controller/config.tcl b/openlane/scan_controller/config.tcl
index b51552f..c52bd12 100644
--- a/openlane/scan_controller/config.tcl
+++ b/openlane/scan_controller/config.tcl
@@ -31,6 +31,11 @@
set ::env(CLOCK_PERIOD) "10"
set ::env(CLOCK_PORT) "clk"
+set ::env(BASE_SDC_FILE) $::env(DESIGN_DIR)/base.sdc
+
+set ::env(SYNTH_CLOCK_UNCERTAINITY) 0.20
+set ::env(SYNTH_CLOCK_TRANSITION) 0.15
+
# macro needs to work inside Caravel, so can't be core and can't use metal 5
set ::env(DESIGN_IS_CORE) 0
set ::env(RT_MAX_LAYER) {met4}
diff --git a/project_urls.py b/project_urls.py
index 5853b70..b1bc202 100644
--- a/project_urls.py
+++ b/project_urls.py
@@ -1,4 +1,4 @@
-# name must be valid verilog module name set in scan_wrapper.v
+filler_project_url = 'https://github.com/mattvenn/wokwi_filler'
project_urls = [
'https://github.com/mattvenn/wokwi-verilog-gds-test',
'https://github.com/mattvenn/animation_tinytapeout_demo',
diff --git a/project_urls_test.py b/project_urls_test.py
new file mode 100644
index 0000000..a10723a
--- /dev/null
+++ b/project_urls_test.py
@@ -0,0 +1,5 @@
+filler_project_url = 'https://github.com/mattvenn/tinytapeout-test-straight'
+project_urls = [
+ 'https://github.com/mattvenn/tinytapeout-7seg-seconds-counter',
+ 'https://github.com/mattvenn/tinytapeout-test-invert',
+ ]
diff --git a/verilog/dv/scan_controller/test_scan_controller.gtkw b/verilog/dv/scan_controller/test_scan_controller.gtkw
index f4509d8..c90cbc9 100644
--- a/verilog/dv/scan_controller/test_scan_controller.gtkw
+++ b/verilog/dv/scan_controller/test_scan_controller.gtkw
@@ -1,19 +1,18 @@
[*]
[*] GTKWave Analyzer v3.3.103 (w)1999-2019 BSI
-[*] Sat Aug 27 16:09:50 2022
+[*] Wed Aug 31 19:31:00 2022
[*]
[dumpfile] "/home/matt/work/asic-workshop/shuttle7/tinytapeout-mpw7/verilog/dv/scan_controller/test_scan_controller.vcd"
-[dumpfile_mtime] "Sat Aug 27 16:09:19 2022"
-[dumpfile_size] 86352838
+[dumpfile_mtime] "Wed Aug 31 19:30:43 2022"
+[dumpfile_size] 14402588
[savefile] "/home/matt/work/asic-workshop/shuttle7/tinytapeout-mpw7/verilog/dv/scan_controller/test_scan_controller.gtkw"
[timestart] 0
[size] 1848 1016
[pos] -1 -1
-*-27.000000 91200000 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
+*-30.000000 3209000000 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
[treeopen] test_scan_controller_tb.
[treeopen] test_scan_controller_tb.user_project_wrapper.
[treeopen] test_scan_controller_tb.user_project_wrapper.scan_wrapper_339501025136214612_0.
-[treeopen] test_scan_controller_tb.user_project_wrapper.scan_wrapper_340805072482992722_12.
[sst_width] 507
[signals_width] 265
[sst_expanded] 1
@@ -21,76 +20,19 @@
@28
test_scan_controller_tb.clk
test_scan_controller_tb.reset
-@24
-test_scan_controller_tb.user_project_wrapper.active_select[8:0]
-@c00022
-test_scan_controller_tb.user_project_wrapper.inputs[7:0]
-@28
-(0)test_scan_controller_tb.user_project_wrapper.inputs[7:0]
-(1)test_scan_controller_tb.user_project_wrapper.inputs[7:0]
-(2)test_scan_controller_tb.user_project_wrapper.inputs[7:0]
-(3)test_scan_controller_tb.user_project_wrapper.inputs[7:0]
-(4)test_scan_controller_tb.user_project_wrapper.inputs[7:0]
-(5)test_scan_controller_tb.user_project_wrapper.inputs[7:0]
-(6)test_scan_controller_tb.user_project_wrapper.inputs[7:0]
-(7)test_scan_controller_tb.user_project_wrapper.inputs[7:0]
-@1401200
--group_end
-@c00022
-test_scan_controller_tb.user_project_wrapper.outputs[7:0]
-@28
-(0)test_scan_controller_tb.user_project_wrapper.outputs[7:0]
-(1)test_scan_controller_tb.user_project_wrapper.outputs[7:0]
-(2)test_scan_controller_tb.user_project_wrapper.outputs[7:0]
-(3)test_scan_controller_tb.user_project_wrapper.outputs[7:0]
-(4)test_scan_controller_tb.user_project_wrapper.outputs[7:0]
-(5)test_scan_controller_tb.user_project_wrapper.outputs[7:0]
-(6)test_scan_controller_tb.user_project_wrapper.outputs[7:0]
-(7)test_scan_controller_tb.user_project_wrapper.outputs[7:0]
-@1401200
--group_end
-@28
-test_scan_controller_tb.user_project_wrapper.ready
-@800200
--scan controller
-@28
-test_scan_controller_tb.user_project_wrapper.scan_controller.scan_clk
-test_scan_controller_tb.user_project_wrapper.scan_controller.state[2:0]
-@22
-test_scan_controller_tb.user_project_wrapper.scan_controller.current_design[8:0]
-@1000200
--scan controller
-@c00200
--module 0
-@28
-test_scan_controller_tb.user_project_wrapper.scan_wrapper_339501025136214612_0.data_in
-test_scan_controller_tb.user_project_wrapper.scan_wrapper_339501025136214612_0.data_out
-@800022
-test_scan_controller_tb.user_project_wrapper.scan_wrapper_339501025136214612_0.scan_data_in[7:0]
-@28
-(0)test_scan_controller_tb.user_project_wrapper.scan_wrapper_339501025136214612_0.scan_data_in[7:0]
-(1)test_scan_controller_tb.user_project_wrapper.scan_wrapper_339501025136214612_0.scan_data_in[7:0]
-(2)test_scan_controller_tb.user_project_wrapper.scan_wrapper_339501025136214612_0.scan_data_in[7:0]
-(3)test_scan_controller_tb.user_project_wrapper.scan_wrapper_339501025136214612_0.scan_data_in[7:0]
-(4)test_scan_controller_tb.user_project_wrapper.scan_wrapper_339501025136214612_0.scan_data_in[7:0]
-(5)test_scan_controller_tb.user_project_wrapper.scan_wrapper_339501025136214612_0.scan_data_in[7:0]
-(6)test_scan_controller_tb.user_project_wrapper.scan_wrapper_339501025136214612_0.scan_data_in[7:0]
-(7)test_scan_controller_tb.user_project_wrapper.scan_wrapper_339501025136214612_0.scan_data_in[7:0]
-test_scan_controller_tb.user_project_wrapper.scan_wrapper_339501025136214612_0.scan_select_in
-@1001200
--group_end
-@1401200
--module 0
-@800200
--scan chain
-@28
-test_scan_controller_tb.user_project_wrapper.scan_controller.clk
-test_scan_controller_tb.user_project_wrapper.scan_controller.scan_clk
+test_scan_controller_tb.user_project_wrapper.scan_controller.scan_clk_in
+test_scan_controller_tb.user_project_wrapper.scan_controller.scan_clk_out
test_scan_controller_tb.user_project_wrapper.scan_controller.scan_data_in
test_scan_controller_tb.user_project_wrapper.scan_controller.scan_data_out
-test_scan_controller_tb.user_project_wrapper.scan_controller.scan_latch_enable
+test_scan_controller_tb.user_project_wrapper.scan_controller.scan_latch_en
test_scan_controller_tb.user_project_wrapper.scan_controller.scan_select
-@1000200
--scan chain
+@22
+test_scan_controller_tb.user_project_wrapper.scan_controller.inputs[7:0]
+test_scan_controller_tb.user_project_wrapper.scan_controller.outputs[7:0]
+test_scan_controller_tb.user_project_wrapper.scan_controller.active_select[8:0]
+@28
+test_scan_controller_tb.user_project_wrapper.scan_controller.ready
+@29
+test_scan_controller_tb.user_project_wrapper.scan_controller.proj_done
[pattern_trace] 1
[pattern_trace] 0
diff --git a/verilog/dv/scan_controller/test_scan_controller.py b/verilog/dv/scan_controller/test_scan_controller.py
index ba1da90..3cfe4da 100644
--- a/verilog/dv/scan_controller/test_scan_controller.py
+++ b/verilog/dv/scan_controller/test_scan_controller.py
@@ -39,14 +39,13 @@
dut.reset.value = 1
dut.set_clk_div.value = 0
- dut.driver_sel.value = 0b01 # internal controller
- dut.active_select.value = 12 # 7 seg seconds
+ dut.driver_sel.value = 0b10 # internal controller
+ dut.active_select.value = 1 # 7 seg seconds
await ClockCycles(dut.clk, 10)
dut.reset.value = 0
dut.inputs.value = 0
dut.set_clk_div.value = 1 # lock in the new clock divider value
await ClockCycles(dut.clk, 1)
-# dut.set_clk_div.value = 0
dut.inputs.value = 0
# reset: set bit 1 high, wait for one cycle of slow_clk, then set bit 1 low
@@ -60,7 +59,40 @@
await FallingEdge(dut.slow_clk)
for i in range(2):
print("clock {:2} 7seg {}".format(i, decode_seg(dut.seven_seg.value)))
- #assert decode_seg(dut.seven_seg.value) == i
- #await single_cycle(dut)
+ assert decode_seg(dut.seven_seg.value) == i
await FallingEdge(dut.slow_clk)
+ print("straight test")
+ dut.set_clk_div.value = 0 # no clock div
+ dut.active_select.value = 0 # straight
+ await FallingEdge(dut.ready)
+ for i in range(11):
+ dut.inputs.value = i
+ await FallingEdge(dut.ready)
+ print(i, int(dut.outputs))
+ if i > 0:
+ assert i == int(dut.outputs) + 1
+
+ print("invert test")
+ dut.active_select.value = 2 # invert
+ dut.inputs.value = 0
+ await FallingEdge(dut.ready)
+ await FallingEdge(dut.ready)
+ for i in range(11):
+ dut.inputs.value = i
+ await FallingEdge(dut.ready)
+ print(i, int(dut.outputs))
+ if i > 0:
+ assert 256 - i == int(dut.outputs)
+
+ for design in range(10): # next 10 designs are all straight
+ print("straight test at pos {}".format(design))
+ dut.active_select.value = 3 + design
+ await FallingEdge(dut.ready)
+ for i in range(11):
+ dut.inputs.value = i
+ await FallingEdge(dut.ready)
+ print(i, int(dut.outputs))
+ if i > 0:
+ assert i == int(dut.outputs) + 1
+
diff --git a/verilog/dv/scan_controller_int/scan_controller_int.gtkw b/verilog/dv/scan_controller_int/scan_controller_int.gtkw
index 30bde20..2007495 100644
--- a/verilog/dv/scan_controller_int/scan_controller_int.gtkw
+++ b/verilog/dv/scan_controller_int/scan_controller_int.gtkw
@@ -1,23 +1,23 @@
[*]
[*] GTKWave Analyzer v3.3.103 (w)1999-2019 BSI
-[*] Sun Aug 28 04:38:22 2022
+[*] Wed Aug 31 20:59:40 2022
[*]
[dumpfile] "/home/matt/work/asic-workshop/shuttle7/tinytapeout-mpw7/verilog/dv/scan_controller_int/scan_controller_tb.vcd"
-[dumpfile_mtime] "Sun Aug 28 04:37:55 2022"
-[dumpfile_size] 1813865
+[dumpfile_mtime] "Wed Aug 31 20:58:10 2022"
+[dumpfile_size] 830785
[savefile] "/home/matt/work/asic-workshop/shuttle7/tinytapeout-mpw7/verilog/dv/scan_controller_int/scan_controller_int.gtkw"
[timestart] 0
[size] 1848 1016
[pos] -1 -1
-*-29.000000 696514800 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
+*-28.000000 744000000 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
[treeopen] scan_controller_tb.
[treeopen] scan_controller_tb.uut.
[treeopen] scan_controller_tb.uut.mprj.
[treeopen] scan_controller_tb.uut.mprj.scan_controller.
-[sst_width] 423
-[signals_width] 261
+[sst_width] 708
+[signals_width] 329
[sst_expanded] 1
-[sst_vpaned_height] 254
+[sst_vpaned_height] 646
@28
scan_controller_tb.clk
@22
@@ -32,10 +32,14 @@
@28
scan_controller_tb.set_clk_div
scan_controller_tb.slow_clk
+scan_controller_tb.uut.mprj.scan_controller.slow_clk
+scan_controller_tb.uut.mprj.scan_controller.slow_clk_ena
+scan_controller_tb.uut.mprj.scan_controller.reset
+scan_controller_tb.uut.mprj.scan_controller.clk_divider_I.reset
+scan_controller_tb.uut.mprj.scan_controller.clk_divider_I.clk
@800200
-scan chain
@28
-scan_controller_tb.uut.mprj.scan_controller.scan_clk
scan_controller_tb.uut.mprj.scan_controller.scan_data_in
scan_controller_tb.uut.mprj.scan_controller.scan_data_out
scan_controller_tb.uut.mprj.scan_controller.scan_latch_en
@@ -46,13 +50,16 @@
scan_controller_tb.uut.mprj.scan_controller.active_select[8:0]
scan_controller_tb.uut.mprj.scan_controller.inputs[7:0]
scan_controller_tb.uut.mprj.scan_controller.outputs[7:0]
-@28
-scan_controller_tb.uut.mprj.scan_controller.clk_divider.last_set
-@22
-scan_controller_tb.uut.mprj.scan_controller.clk_divider.compare[7:0]
-@8024
-scan_controller_tb.uut.mprj.scan_controller.clk_divider.counter[21:0]
@20000
-
+@28
+scan_controller_tb.uut.mprj.scan_wrapper_339501025136214612_0.data_in
+scan_controller_tb.uut.mprj.scan_controller.clk_divider_I.slow_clk
+>-4100000
+scan_controller_tb.uut.mprj.scan_controller.clk_divider_I.match
+@22
+>0
+scan_controller_tb.uut.mprj.scan_controller.clk_divider_I.compare[7:0]
+scan_controller_tb.uut.mprj.scan_controller.clk_divider_I.counter[7:0]
[pattern_trace] 1
[pattern_trace] 0
diff --git a/verilog/dv/scan_controller_int/test_scan_controller.py b/verilog/dv/scan_controller_int/test_scan_controller.py
index 1dcdf71..9c87630 100644
--- a/verilog/dv/scan_controller_int/test_scan_controller.py
+++ b/verilog/dv/scan_controller_int/test_scan_controller.py
@@ -7,7 +7,7 @@
clock = Clock(dut.clk, 25, units="ns") # 40M
cocotb.fork(clock.start())
- dut.driver_sel.value = 0b01 # internal
+ dut.driver_sel.value = 0b10 # internal
dut.set_clk_div.value = 0
dut.inputs.value = 0
dut.active_sel.value = 0
@@ -43,13 +43,18 @@
assert dut.outputs.value == 0xAA
# use the clock divider
+ await ClockCycles(dut.clk, 100)
print("checking clock divider")
+ dut.RSTB.value = 0
await RisingEdge(dut.clk)
dut.inputs.value = 1
dut.set_clk_div.value = 1
+ await ClockCycles(dut.clk, 100)
+ dut.RSTB.value = 1
await ClockCycles(dut.clk, 2)
dut.inputs.value = 0
+ print("waiting for slow clock")
# check slow clock output
for i in range(2):
await RisingEdge(dut.slow_clk)
diff --git a/verilog/dv/scan_controller_la/test_scan_controller.py b/verilog/dv/scan_controller_la/test_scan_controller.py
index 9d7907e..6eadd7e 100644
--- a/verilog/dv/scan_controller_la/test_scan_controller.py
+++ b/verilog/dv/scan_controller_la/test_scan_controller.py
@@ -7,7 +7,7 @@
clock = Clock(dut.clk, 25, units="ns") # 40M
cocotb.fork(clock.start())
- dut.driver_sel.value = 0b10 # logic analyser
+ dut.driver_sel.value = 0b01 # logic analyser
dut.RSTB.value = 0
dut.power1.value = 0
dut.power2.value = 0
diff --git a/verilog/rtl/scan_controller/properties.v b/verilog/rtl/scan_controller/properties.v
index c104f6a..a14d115 100644
--- a/verilog/rtl/scan_controller/properties.v
+++ b/verilog/rtl/scan_controller/properties.v
@@ -1,22 +1,24 @@
always @(*) begin
if(driver_sel == 2'b00) begin // external driver
- assert(outputs[0] == scan_data_in);
- assert(scan_clk == ext_scan_clk);
+ assert(outputs[0] == scan_clk_in);
+ assert(outputs[1] == scan_data_in);
+ assert(scan_clk_out == inputs[0]);
assert(scan_data_out == inputs[1]);
assert(scan_select == inputs[2]);
assert(scan_latch_en == inputs[3]);
end else
- if(driver_sel == 2'b10) begin // external driver
+ if(driver_sel == 2'b01) begin // la
assert(la_scan_data_out == scan_data_in);
- assert(scan_clk == la_scan_clk);
+ assert(scan_clk_out == la_scan_clk_in);
assert(scan_data_out == la_scan_data_in);
assert(scan_select == la_scan_select);
assert(scan_latch_en == la_scan_latch_en);
end else
- if(driver_sel == 2'b01) begin // internal driver
+ if(driver_sel == 2'b10) begin // internal driver
assert(int_scan_data_out == scan_data_out);
- assert(scan_clk == int_scan_clk);
+ assert(scan_clk_out == int_scan_clk_out);
assert(scan_data_in == int_scan_data_in);
+ assert(scan_clk_in == int_scan_clk_in);
assert(scan_select == int_scan_select);
assert(scan_latch_en == int_scan_latch_en);
end
diff --git a/verilog/rtl/scan_controller/scan_controller.v b/verilog/rtl/scan_controller/scan_controller.v
index 1591991..e1d75a8 100644
--- a/verilog/rtl/scan_controller/scan_controller.v
+++ b/verilog/rtl/scan_controller/scan_controller.v
@@ -1,226 +1,451 @@
+`timescale 1ns / 100ps
`default_nettype none
-module scan_controller (
+module scan_controller #(
+ parameter integer NUM_DESIGNS = 8,
+ parameter integer NUM_IOS = 8,
+
+ // auto-set
+ parameter integer PL = NUM_IOS - 1
+)(
input wire clk,
input wire reset,
input wire [8:0] active_select, // which design is connected to the inputs and outputs
- input wire [7:0] inputs, // inputs to the design (or external scan chain)
+ input wire [PL:0] inputs, // inputs to the design (or external scan chain)
input wire set_clk_div, // set clock divider. See module below
- output wire [7:0] outputs, // outputs from the design (or external scan chain)
+ output wire [PL:0] outputs, // outputs from the design (or external scan chain)
output wire ready, // debug output that goes high once per refresh
output wire slow_clk, // debug clock divider output
- output wire scan_clk, // scan chain interface for the tiny designs, from perspective of this module
- output wire scan_data_out, // see diagrams below for how the scan chain works
+ output reg scan_clk_out, // scan chain interface for the tiny designs, from perspective of this module
+ output reg scan_data_out, // see diagrams below for how the scan chain works
+ input wire scan_clk_in, // feedback clock after having done the whole round
input wire scan_data_in, // will be driven by internal driver, external gpio pins, or Caravel logic analyser
- output wire scan_select, // external scan chain driver muxes with ins/outs, eg microcontroller outside the ASIC
- output wire scan_latch_en,
+ output reg scan_select, // external scan chain driver muxes with ins/outs, eg microcontroller outside the ASIC
+ output reg scan_latch_en,
- input wire la_scan_clk, // logic analyser scan chain driver, driven by firmware running on Caravel's VexRisc
- input wire la_scan_data_in, // signal names from perspective of this module
+ input wire la_scan_clk_in, // logic analyser scan chain driver, driven by firmware running on Caravel's VexRisc
+ input wire la_scan_data_in, // signal names from perspective of this module toward scan chain
output wire la_scan_data_out,
input wire la_scan_select,
input wire la_scan_latch_en,
- input wire [1:0] driver_sel, // 00 = external, 01 = internal, 10 = logic analyser
+ input wire [1:0] driver_sel, // 00 = external, 01 = logic analyzer, 1x = internal
output wire [`MPRJ_IO_PADS-1:0] oeb // caravel harness needs output enable bar set low to enable outputs
- );
+);
+ // Signals
+ // -------
+ assign ready = active && state == ST_IDLE;
+
+ // Reset
+ reg [2:0] rst_shift;
+ wire rst_i;
+
+ // Muxing
+ // _in / _out are from the perspecitve of this module toward the scan
+ // chain. So all _in are FROM the scan chain (and either input to this
+ // module from there, or output from this module to LA / External)
+
+ wire ext_scan_clk_in;
+ wire ext_scan_data_in;
+ wire ext_scan_clk_out;
+ wire ext_scan_data_out;
+ wire ext_scan_select;
+ wire ext_scan_latch_en;
+
+ wire int_scan_clk_in;
+ wire int_scan_data_in;
+ reg int_scan_clk_out;
+ reg int_scan_data_out;
+ reg int_scan_select;
+ reg int_scan_latch_en;
+
+ // FSM
+ localparam [3:0]
+ ST_IDLE = 0, // Idle
+ ST_IN_LOAD = 1, // Capture input
+ ST_IN_SHIFT_LO = 2, // Shift input to design: lo-clk
+ ST_IN_SHIFT_HI = 3, // Shift input to design: hi-clk
+ ST_IN_LATCH_WAIT = 4, // Wait before latching
+ ST_IN_LATCH = 5, // Latch
+ ST_OUT_LOAD_PRE = 6, // Prepare load
+ ST_OUT_LOAD = 7, // Clock once to load
+ ST_OUT_LOAD_POST = 8, // Wait for load to be done
+ ST_OUT_LOAD_CLR = 9, // Restore chain to shift mode
+ ST_OUT_SHIFT_LO = 10, // Shift output to us: lo-clk
+ ST_OUT_SHIFT_HI = 11, // Shift output to us: hi-clk
+ ST_OUT_CAP_WAIT = 12, // Wait for capture
+ ST_OUT_CAP = 13; // Capture to out local register
+
+ reg active;
+
+ reg [3:0] state;
+ reg [3:0] state_nxt;
+
+ // Scan progress
+ reg [$clog2(NUM_IOS)-1:0] bit_cnt;
+ wire bit_last;
+
+ reg [8:0] proj_cnt;
+ wire proj_sel;
+ wire proj_done;
+
+ // Auto IO
+ reg [PL:0] aio_input_sync;
+ reg [PL:0] aio_input_reg;
+ reg [PL:0] aio_input_shift;
+
+ reg [PL:0] aio_output_shift;
+ reg [PL:0] aio_output_reg;
+
+ wire aio_input_sh;
+ wire aio_input_ld;
+ wire aio_output_cap;
+
+ // Wait state config
+ reg [7:0] ws_cnt;
+ wire ws_cnt_done;
+ wire ws_cnt_run;
+
+ // Wait state config
+ reg [2:0] ws_set_sync;
+ reg ws_set_now;
+ reg [7:0] ws_cfg;
+
+ // Clock divider
+ wire slow_clk_ena;
+
+
+ // Misc
+ // ----
+
+ // Generate internal ties for the IO blocks
assign oeb = {`MPRJ_IO_PADS{1'b0}};
- parameter NUM_DESIGNS = 8;
- parameter NUM_IOS = 8;
-
- localparam START = 0;
- localparam LOAD = 1;
- localparam READ = 2;
- localparam CAPTURE_STATE = 3;
- localparam LATCH = 4;
-
- // scan chain muxing
- // signal names in perspective of this module
- wire ext_scan_clk = inputs[0];
- wire ext_scan_data_in = inputs[1];
- wire ext_scan_data_out = scan_data_in;
- wire ext_scan_select = inputs[2];
- wire ext_scan_latch_en = inputs[3];
-
- assign scan_clk = driver_sel == 2'b00 ? ext_scan_clk : driver_sel == 2'b01 ? int_scan_clk : la_scan_clk;
- assign scan_data_out = driver_sel == 2'b00 ? ext_scan_data_in : driver_sel == 2'b01 ? int_scan_data_out : la_scan_data_in;
- assign scan_select = driver_sel == 2'b00 ? ext_scan_select : driver_sel == 2'b01 ? int_scan_select : la_scan_select;
- assign scan_latch_en = driver_sel == 2'b00 ? ext_scan_latch_en : driver_sel == 2'b01 ? int_scan_latch_en : la_scan_latch_en;
-
- wire int_scan_data_in = scan_data_in;
- assign la_scan_data_out = scan_data_in;
- assign outputs = driver_sel == 2'b01 ? outputs_r : {7'b0, ext_scan_data_out};
-
`ifdef FORMAL
`include "properties.v"
`endif
- // reg
- reg [8:0] current_design;
- reg [2:0] state;
- reg [3:0] num_io;
- reg scan_clk_r;
- reg scan_select_out_r;
+ // Generate our own reset, with de-assertion
+ // synchronized to clock
+ always @(negedge clk or posedge reset)
+ if (reset)
+ rst_shift <= 3'b111;
+ else
+ rst_shift <= { rst_shift[1:0], 1'b0 };
- reg [7:0] inputs_r;
- reg [7:0] outputs_r;
- reg [7:0] output_buf;
-
- // wires
- wire [8:0] active_select_rev = NUM_DESIGNS - 1 - active_select;
- assign ready = state == START;
- wire int_scan_latch_en = state == LATCH;
- wire int_scan_clk = scan_clk_r;
- wire int_scan_data_out = (state == LOAD && current_design == active_select_rev ) ? inputs_r[NUM_IOS-1-num_io] : 0;
- wire int_scan_select = scan_select_out_r;
-
- // clock divider
- clk_divider clk_divider (
- .clk (clk),
- .set (set_clk_div),
- .reset (reset),
- .divider (inputs),
- .slow_clk (slow_clk)
- );
- wire [7:0] inputs_and_clk = set_clk_div ? { inputs[7:1], slow_clk } : inputs;
-
- /*
-
- LOAD
-
- ┌──┐ ┌──┐ ┌──┐ ┌──┐
- clk : ┘ └──┘ └──┘ └──┘ └──────────────
- ┐
- scan en: └───────────────────────────────────
- ┐ ┌─────┐
- latch : └───────────────────────┘ └─────
- ┐ ┌─────┐ ┌─────┐
- data o : └─────┘ └─────┘ └───────────
- xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
- data i : xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+ assign rst_i = rst_shift[2];
- READ
+ // Scan chain and IO muxing
+ // ------------------------
- ┌──┐ ┌──┐ ┌──┐ ┌──┐ ┌──┐ ┌──┐
- clk : ┘ └──┘ └──┘ └──┘ └──┘ └──┘ └──
- ┐ ┌─────┐
- scan en: └─────┘ └───────────────────────
- ┐
- latch : └───────────────────────────────────
- xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
- data o : xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
- ┐ ┌─────┐ ┌─────┐
- data i : └───────────┘ └─────┘ └─────
+ // To ensure we get something working, the scan chain can be driven
+ // three different ways. Automatic, from caravel LA and fully
+ // externally (see driver_sel input)
- */
+ // External interface
+ assign ext_scan_clk_out = inputs[0];
+ assign ext_scan_data_out = inputs[1];
+ assign ext_scan_select = inputs[2];
+ assign ext_scan_latch_en = inputs[3];
- // FSM, only run it if driver_sel is set to internal
- always @(posedge clk) begin
- if(reset) begin
- current_design <= 0;
- state <= START;
- inputs_r <= 0;
- outputs_r <= 0;
- scan_clk_r <= 0;
- num_io <= 0;
- output_buf <= 0;
- end else if (driver_sel == 2'b01) begin
- case(state)
- START: begin
- state <= LOAD;
- inputs_r <= inputs_and_clk;
- outputs_r <= output_buf;
- current_design <= 0;
- scan_select_out_r <= 0;
- end
+ assign ext_scan_clk_in = scan_clk_in;
+ assign ext_scan_data_in = scan_data_in;
- LOAD: begin
- scan_clk_r <= ~scan_clk_r;
- if(scan_clk_r) begin
- num_io <= num_io + 1;
+ // Internal interface
+ assign int_scan_clk_in = scan_clk_in;
+ assign int_scan_data_in = scan_data_in;
- if(num_io == NUM_IOS - 1) begin
- num_io <= 0;
- current_design <= current_design + 1;
-
- if(current_design == NUM_DESIGNS - 1)
- state <= LATCH;
- end
+ // LA interface
+ assign la_scan_data_out = scan_data_in;
- end
-
- end
- LATCH: begin
- state <= READ;
- current_design <= 0;
- scan_select_out_r <= 1;
- end
-
- READ: begin
- scan_select_out_r <= 0;
- scan_clk_r <= ~scan_clk_r;
- if(scan_clk_r) begin
- num_io <= num_io + 1;
- if(current_design == active_select_rev)
- output_buf[NUM_IOS-1-num_io] <= int_scan_data_in;
-
- if(num_io == NUM_IOS - 1) begin
- num_io <= 0;
- current_design <= current_design + 1;
-
-
- if(current_design == NUM_DESIGNS - 1) begin
- state <= START;
- end
- end
- end
- end
- endcase
- end
- end
-
-endmodule
-
-module clk_divider (
- input clk,
- input reset,
- input set,
- input [DIV_WIDTH-1:0] divider,
- output slow_clk
- );
-
- // fastest useful clock period must be < max refresh rate: 750Hz
- // 10M with 14bit divider (min) gives ~610Hz
- // 10M with 22bit divider (max) gives ~2.4Hz
- localparam MIN_WIDTH = 13;
- localparam DIV_WIDTH = 8;
-
- reg [MIN_WIDTH+8:0] counter;
- reg [DIV_WIDTH-1:0] compare;
- reg last_set;
-
- assign slow_clk = counter[MIN_WIDTH + compare];
-
- always @(posedge clk) begin
- if(reset) begin
- counter <= 0;
- compare <= 0;
- last_set <= 0;
- end
- else begin
- // update divider on positive edge of set
- if(set && !last_set) begin
- compare <= divider;
+ // Mux toward scan-schain
+ always @(*)
+ begin
+ casez (driver_sel)
+ // External
+ 2'b00: begin
+ scan_clk_out = ext_scan_clk_out;
+ scan_data_out = ext_scan_data_out;
+ scan_select = ext_scan_select;
+ scan_latch_en = ext_scan_latch_en;
end
- counter <= counter + 1'b1;
- last_set <= set;
- end
+
+ // Caravel LA
+ 2'b01: begin
+ scan_clk_out = la_scan_clk_in;
+ scan_data_out = la_scan_data_in;
+ scan_select = la_scan_select;
+ scan_latch_en = la_scan_latch_en;
+ end
+
+ // Internal
+ 2'b1z: begin
+ scan_clk_out = int_scan_clk_out;
+ scan_data_out = int_scan_data_out;
+ scan_select = int_scan_select;
+ scan_latch_en = int_scan_latch_en;
+ end
+ endcase
end
-endmodule
+ // Synchronizer for inputs
+ always @(posedge clk)
+ begin
+ aio_input_sync <= inputs;
+ aio_input_reg <= driver_sel[1] ? aio_input_sync : 0;
+ end
+
+ // Mux for outputs
+ assign outputs = driver_sel[1] ? aio_output_reg : {6'b0, ext_scan_data_in, ext_scan_clk_in};
+
+
+ // FSM & control
+ // -------------
+
+ // Check if we're active
+ always @(posedge clk or posedge rst_i)
+ if (rst_i)
+ active <= 1'b0;
+ else
+ active <= driver_sel[1];
+
+ // State register
+ always @(posedge clk or posedge rst_i)
+ if (rst_i)
+ state <= ST_IDLE;
+ else
+ state <= state_nxt;
+
+ // State transitions
+ always @(*)
+ begin
+ // Defaults
+ state_nxt = state;
+
+ // Transitions
+ case (state)
+ ST_IDLE:
+ if (active)
+ state_nxt = ST_IN_LOAD;
+
+ ST_IN_LOAD:
+ state_nxt = ST_IN_SHIFT_LO;
+
+ ST_IN_SHIFT_LO:
+ state_nxt = ST_IN_SHIFT_HI;
+
+ ST_IN_SHIFT_HI:
+ state_nxt = (proj_sel & bit_last) ? ST_IN_LATCH_WAIT : ST_IN_SHIFT_LO;
+
+ ST_IN_LATCH_WAIT:
+ if (ws_cnt_done)
+ state_nxt = ST_IN_LATCH;
+
+ ST_IN_LATCH:
+ state_nxt = ST_OUT_LOAD_PRE;
+
+ ST_OUT_LOAD_PRE:
+ if (ws_cnt_done)
+ state_nxt = ST_OUT_LOAD;
+
+ ST_OUT_LOAD:
+ state_nxt = ST_OUT_LOAD_POST;
+
+ ST_OUT_LOAD_POST:
+ if (ws_cnt_done)
+ state_nxt = ST_OUT_LOAD_CLR;
+
+ ST_OUT_LOAD_CLR:
+ if (ws_cnt_done)
+ state_nxt = ST_OUT_SHIFT_LO;
+
+ ST_OUT_SHIFT_LO:
+ state_nxt = ST_OUT_SHIFT_HI;
+
+ ST_OUT_SHIFT_HI:
+ state_nxt = (proj_done & bit_last) ? ST_OUT_CAP_WAIT : ST_OUT_SHIFT_LO;
+
+ ST_OUT_CAP_WAIT:
+ if (ws_cnt_done)
+ state_nxt = ST_OUT_CAP;
+
+ ST_OUT_CAP:
+ state_nxt = ST_IDLE;
+ endcase
+ end
+
+
+ // Scan progress tracking
+ // ----------------------
+
+ // Keep track of IO number
+ always @(posedge clk)
+ if (state == ST_IDLE)
+ bit_cnt <= 0;
+ else if ((state == ST_IN_SHIFT_HI) | (state == ST_OUT_SHIFT_HI))
+ bit_cnt <= bit_last ? 0 : (bit_cnt + 1);
+
+ assign bit_last = (bit_cnt == (NUM_IOS - 1));
+
+ // Keep track of project number
+ always @(posedge clk)
+ if (state == ST_IDLE)
+ proj_cnt <= 0;
+ else if (((state == ST_IN_SHIFT_HI) | (state == ST_OUT_SHIFT_HI)) & bit_last)
+ proj_cnt <= proj_cnt + 1;
+
+ assign proj_sel = (proj_cnt == active_select);
+ assign proj_done = (proj_cnt == NUM_DESIGNS);
+
+
+ // Scan chain control
+ // ------------------
+
+ always @(posedge clk)
+ begin
+ int_scan_clk_out <= (state == ST_IN_SHIFT_HI) | (state == ST_OUT_LOAD) | (state == ST_OUT_SHIFT_HI);
+ int_scan_data_out <= aio_input_shift[PL];
+ int_scan_select <= (state == ST_OUT_LOAD_PRE) | (state == ST_OUT_LOAD) | (state == ST_OUT_LOAD_POST);
+ int_scan_latch_en <= (state == ST_IN_LATCH);
+ end
+
+
+ // Shift registers
+ // ---------------
+
+ // Local control from FSM
+ assign aio_input_sh = (state == ST_IN_SHIFT_HI);
+ assign aio_input_ld = (state == ST_IN_LOAD);
+ assign aio_output_cap = (state == ST_OUT_CAP);
+
+ // Input
+ always @(posedge clk)
+ if (aio_input_ld)
+ aio_input_shift <= slow_clk_ena ? { aio_input_reg[PL-1:1], slow_clk } : aio_input_reg;
+ else if (aio_input_sh)
+ aio_input_shift <= { aio_input_shift[PL-1:0], 1'b0 };
+
+ // Output
+ always @(posedge int_scan_clk_in)
+ aio_output_shift <= { aio_output_shift[PL-1:0], int_scan_data_in };
+
+ always @(posedge clk)
+ if (aio_output_cap)
+ aio_output_reg <= aio_output_shift;
+
+
+ // Wait state counter
+ // ------------------
+
+ always @(posedge clk)
+ if (~ws_cnt_run | ws_cnt_done)
+ ws_cnt <= 0;
+ else
+ ws_cnt <= ws_cnt + 1;
+
+ assign ws_cnt_done = (ws_cnt == ws_cfg);
+
+ assign ws_cnt_run = (
+ (state == ST_IN_LATCH_WAIT) |
+ (state == ST_OUT_LOAD_PRE) |
+ (state == ST_OUT_LOAD_POST) |
+ (state == ST_OUT_LOAD_CLR) |
+ (state == ST_OUT_CAP_WAIT)
+ );
+
+
+ // Wait state config
+ // -----------------
+
+ // This dictates how many wait cycle we insert in various state
+ // of the load process. We have a sane default, but also allow
+ // override externally.
+
+ always @(posedge clk or posedge rst_i)
+ if (rst_i)
+ ws_set_sync <= 3'b000;
+ else
+ ws_set_sync <= { ws_set_sync[1:0], (driver_sel == 2'b11) };
+
+ always @(posedge clk)
+ ws_set_now <= ~ws_set_sync[2] & ws_set_sync[1];
+
+ always @(posedge clk or posedge rst_i)
+ if (rst_i)
+ ws_cfg <= 8'd10;
+ else if (ws_set_now)
+ ws_cfg <= inputs;
+
+
+ // Clock Divider
+ // -------------
+
+ clk_divider clk_divider_I (
+ .clk (clk),
+ .ce (aio_input_ld),
+ .set (set_clk_div),
+ .reset (rst_i),
+ .divider (inputs),
+ .active (slow_clk_ena),
+ .slow_clk (slow_clk)
+ );
+
+endmodule // scan_controller
+
+
+module clk_divider #(
+ parameter integer DIV_WIDTH = 8
+)(
+ input wire clk,
+ input wire ce,
+ input wire reset,
+ input wire set,
+ input wire [DIV_WIDTH-1:0] divider,
+ output wire active,
+ output reg slow_clk
+);
+
+ reg [DIV_WIDTH-1:0] counter;
+ reg [DIV_WIDTH-1:0] compare;
+ wire match;
+
+ reg [2:0] set_sync;
+ reg set_now;
+
+ // Detect rising edge (with synchronizer)
+ always @(posedge clk)
+ begin
+ set_sync <= { set_sync[1:0], set };
+ set_now <= ~set_sync[2] & set_sync[1];
+ end
+
+ assign active = set_sync[2];
+
+ // Latch divider
+ always @(posedge clk)
+ if (set_now)
+ compare <= divider;
+
+ // Compare
+ assign match = (counter == compare);
+
+ // Counter
+ always @(posedge clk or posedge reset)
+ if (reset)
+ counter <= 0;
+ else if (ce)
+ counter <= match ? 0 : (counter + 1);
+
+ // Clock gen
+ always @(posedge clk or posedge reset)
+ if (reset)
+ slow_clk <= 1'b0;
+ else if (ce)
+ slow_clk <= slow_clk ^ match;
+
+endmodule // clk_divider
diff --git a/verilog/rtl/user_project_wrapper.v b/verilog/rtl/user_project_wrapper.v
index 7ea4afa..2079594 100644
--- a/verilog/rtl/user_project_wrapper.v
+++ b/verilog/rtl/user_project_wrapper.v
@@ -96,13 +96,14 @@
.slow_clk (io_out[10]),
.set_clk_div (io_in[11]),
- .scan_clk (clk[0]),
+ .scan_clk_out (clk[0]),
+ .scan_clk_in (clk[NUM_MACROS]),
.scan_data_out (data[0]),
.scan_data_in (data[NUM_MACROS]),
.scan_select (scan[0]),
.scan_latch_en (latch[0]),
- .la_scan_clk (la_data_in[0]),
+ .la_scan_clk_in (la_data_in[0]),
.la_scan_data_in (la_data_in[1]),
.la_scan_data_out (la_data_out[0]),
.la_scan_select (la_data_in[2]),