wip: internal working as normal
diff --git a/configure.py b/configure.py
index b5c5865..3d35a39 100755
--- a/configure.py
+++ b/configure.py
@@ -263,32 +263,34 @@
assigns = """
localparam NUM_MACROS = {};
wire [NUM_MACROS:0] data, scan, latch, clk;
- wire ready, slow_clk;
- wire [8:0] active_select = io_in[20:12];
- wire [7:0] inputs = io_in[28:21];
- wire set_clk_div = io_in[11];
- wire [7:0] outputs;
- assign io_out[36:29] = outputs;
- assign io_out[37] = ready;
- assign io_out[10] = slow_clk;
"""
scan_controller_template = """
scan_controller #(.NUM_DESIGNS(NUM_MACROS)) scan_controller(
- .clk (wb_clk_i),
- .reset (wb_rst_i),
- .active_select (active_select),
- .inputs (inputs),
- .outputs (outputs),
- .ready (ready),
- .slow_clk (slow_clk),
- .set_clk_div (set_clk_div),
- .scan_clk (clk[0]),
- .scan_data_out (data[0]),
- .scan_data_in (data[NUM_MACROS]),
- .scan_select (scan[0]),
- .scan_latch_enable(latch[0]),
- .oeb (io_oeb[37:29])
+ .clk (wb_clk_i),
+ .reset (wb_rst_i),
+ .active_select (io_in[20:12]),
+ .inputs (io_in[28:21]),
+ .outputs (io_out[36:29]),
+ .ready (io_out[37]),
+ .slow_clk (io_out[10]),
+ .set_clk_div (io_in[11]),
+
+ .scan_clk (clk[0]),
+ .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_data_in (la_data_in[1]),
+ .la_scan_data_out (la_data_out[0]),
+ .la_scan_select (la_data_in[2]),
+ .la_scan_latch_en (la_data_in[3]),
+
+ .driver_sel (io_in[9:8]),
+
+ .oeb (io_oeb)
);
"""
diff --git a/verilog/dv/scan_controller/test_scan_controller.py b/verilog/dv/scan_controller/test_scan_controller.py
index 9c5616d..fd64c35 100644
--- a/verilog/dv/scan_controller/test_scan_controller.py
+++ b/verilog/dv/scan_controller/test_scan_controller.py
@@ -33,12 +33,13 @@
return '?'
@cocotb.test()
-async def test(dut):
+async def internal_controller(dut):
clock = Clock(dut.clk, 100, units="ns") # 10 MHz
cocotb.fork(clock.start())
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
await ClockCycles(dut.clk, 10)
dut.reset.value = 0
@@ -62,3 +63,4 @@
#assert decode_seg(dut.seven_seg.value) == i
#await single_cycle(dut)
await FallingEdge(dut.slow_clk)
+
diff --git a/verilog/dv/scan_controller/test_scan_controller_tb.v b/verilog/dv/scan_controller/test_scan_controller_tb.v
index c8cea33..15e5082 100644
--- a/verilog/dv/scan_controller/test_scan_controller_tb.v
+++ b/verilog/dv/scan_controller/test_scan_controller_tb.v
@@ -8,6 +8,7 @@
input wire clk,
input wire reset,
+ input wire [1:0] driver_sel,
input wire [8:0] active_select,
input wire [7:0] inputs,
input wire set_clk_div,
@@ -25,6 +26,7 @@
assign io_in[20:12] = active_select;
assign io_in[28:21] = inputs;
assign io_in[11] = set_clk_div;
+ assign io_in[9:8] = driver_sel;
assign outputs = io_out[36:29];
assign ready = io_out[37];
assign slow_clk = io_out[10];
diff --git a/verilog/rtl/scan_controller/scan_controller.v b/verilog/rtl/scan_controller/scan_controller.v
index 8883c35..60b366b 100644
--- a/verilog/rtl/scan_controller/scan_controller.v
+++ b/verilog/rtl/scan_controller/scan_controller.v
@@ -5,22 +5,30 @@
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
+ input wire [7: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
+ output wire [7: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, // see diagrams below for how the scan chain works
- output wire scan_data_out,
- input wire scan_data_in,
- output wire scan_select,
- output wire scan_latch_enable,
+ output wire scan_clk, // scan chain interface for the tiny designs
+ output wire scan_data_out, // see diagrams below for how the scan chain works
+ 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 wire [8:0] oeb // caravel harness needs output enable bar set low to enable outputs
+ input wire la_scan_clk, // logic analyser scan chain driver, driven by firmware running on Caravel's VexRisc
+ input wire la_scan_data_in,
+ 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
+
+ output wire [`MPRJ_IO_PADS-1:0] oeb // caravel harness needs output enable bar set low to enable outputs
);
- assign oeb = 8'b0;
+ assign oeb = {`MPRJ_IO_PADS{1'b0}};
parameter NUM_DESIGNS = 8;
parameter NUM_IOS = 8;
@@ -31,6 +39,19 @@
localparam CAPTURE_STATE = 3;
localparam LATCH = 4;
+ // scan chain muxing
+ wire ext_scan_clk;
+ wire ext_scan_data_out;
+ wire ext_scan_data_in;
+ wire ext_scan_select;
+ wire ext_scan_latch_en;
+
+ 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_out : driver_sel == 2'b01 ? int_scan_data_out : la_scan_data_out;
+ 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;
// reg
reg [8:0] current_design;
@@ -47,10 +68,10 @@
assign outputs = outputs_r;
wire [8:0] active_select_rev = NUM_DESIGNS - 1 - active_select;
assign ready = state == START;
- assign scan_latch_enable = state == LATCH;
- assign scan_clk = scan_clk_r;
- assign scan_data_out = (state == LOAD && current_design == active_select_rev ) ? inputs_r[NUM_IOS-1-num_io] : 0;
- assign scan_select = scan_select_out_r;
+ 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 (
@@ -141,7 +162,7 @@
if(scan_clk_r) begin
num_io <= num_io + 1;
if(current_design == active_select_rev)
- output_buf[NUM_IOS-1-num_io] <= scan_data_in;
+ output_buf[NUM_IOS-1-num_io] <= int_scan_data_in;
if(num_io == NUM_IOS - 1) begin
num_io <= 0;