add semi-working trigger block autogen
This commit is contained in:
parent
8f08dffc70
commit
aab1b5ac10
|
|
@ -1,6 +1,9 @@
|
|||
# macOS being lame
|
||||
.DS_Store
|
||||
|
||||
# VSCode being lame
|
||||
*.vscode/
|
||||
|
||||
# Vivado output products
|
||||
*.log
|
||||
*.jou
|
||||
|
|
|
|||
|
|
@ -467,11 +467,108 @@ class LogicAnalyzerCore:
|
|||
|
||||
return hdl
|
||||
|
||||
def generate_trigger_block(self):
|
||||
trigger_block_hdl = pkgutil.get_data(__name__, "trigger_block_template.v").decode()
|
||||
|
||||
# add probe ports to module declaration
|
||||
# - these are the ports that belong to the logic analyzer, but
|
||||
# need to be included in the trigger_block module declaration
|
||||
probe_ports = []
|
||||
for name, width in self.probes.items():
|
||||
if width == 1:
|
||||
probe_ports.append(f"input wire {name}")
|
||||
else:
|
||||
probe_ports.append(f"input wire [{width-1}:0] {name}")
|
||||
|
||||
probe_ports = ",\n\t".join(probe_ports)
|
||||
probe_ports = probe_ports + ","
|
||||
trigger_block_hdl = trigger_block_hdl.replace("// @PROBE_PORTS", probe_ports)
|
||||
|
||||
# add trigger cores to module definition
|
||||
# - these are instances of the trigger module, of which one gets wired
|
||||
# into each probe
|
||||
trigger_module_insts = []
|
||||
for name, width in self.probes.items():
|
||||
trigger_module_inst = f"reg [3:0] {name}_trigger_op = 0;\n\t"
|
||||
|
||||
if width == 1:
|
||||
trigger_module_inst += f"reg {name}_trigger_arg = 0;\n\t"
|
||||
|
||||
else:
|
||||
trigger_module_inst += f"reg [{width-1}:0] {name}_trigger_arg = 0;\n\t"
|
||||
|
||||
trigger_module_inst += f"reg {name}_trig;\n\t"
|
||||
trigger_module_inst += f"""
|
||||
trigger #(.INPUT_WIDTH({width})) {name}_trigger (
|
||||
.clk(clk),
|
||||
|
||||
.probe({name}),
|
||||
.op({name}_trigger_op),
|
||||
.arg({name}_trigger_arg),
|
||||
.trig({name}_trig)
|
||||
);
|
||||
"""
|
||||
trigger_module_insts.append(trigger_module_inst)
|
||||
|
||||
trigger_module_insts = "".join(trigger_module_insts)
|
||||
trigger_module_insts = trigger_module_insts.rstrip()
|
||||
trigger_block_hdl = trigger_block_hdl.replace("// @TRIGGER_MODULE_INSTS", trigger_module_insts)
|
||||
|
||||
# add combined individual triggers
|
||||
combined_individual_triggers = [f"{name}_trig" for name in self.probes]
|
||||
combined_individual_triggers = " || ".join(combined_individual_triggers)
|
||||
combined_individual_triggers = f"assign trig = {combined_individual_triggers};"
|
||||
trigger_block_hdl = trigger_block_hdl.replace("// @COMBINE_INDIV_TRIGGERS", combined_individual_triggers)
|
||||
|
||||
# add read and write block case statement bodies
|
||||
rcsb = "" # read case statement body
|
||||
wcsb = "" # write case statement body
|
||||
addr = 0
|
||||
for i, name in enumerate(self.probes):
|
||||
addr = 2 * i
|
||||
rcsb += f"\t\t\t\t\tBASE_ADDR + {addr}: rdata_o <= {name}_trigger_op;\n"
|
||||
wcsb += f"\t\t\t\t\tBASE_ADDR + {addr}: {name}_trigger_op <= wdata_i;\n"
|
||||
|
||||
addr = (2 * i) + 1
|
||||
rcsb += f"\t\t\t\t\tBASE_ADDR + {addr}: rdata_o <= {name}_trigger_arg;\n"
|
||||
wcsb += f"\t\t\t\t\tBASE_ADDR + {addr}: {name}_trigger_arg <= wdata_i;\n"
|
||||
|
||||
rcsb = rcsb.strip()
|
||||
wcsb = wcsb.strip()
|
||||
|
||||
trigger_block_hdl = trigger_block_hdl.replace("// @READ_CASE_STATEMENT_BODY", rcsb)
|
||||
trigger_block_hdl = trigger_block_hdl.replace("// @WRITE_CASE_STATEMENT_BODY", wcsb)
|
||||
trigger_block_hdl = trigger_block_hdl.replace("// @MAX_ADDR", str(addr))
|
||||
return trigger_block_hdl
|
||||
|
||||
def hdl_def(self):
|
||||
# Return an autogenerated verilog module definition for the core.
|
||||
# load source files
|
||||
logic_analyzer_hdl = pkgutil.get_data(__name__, "logic_analyzer.v").decode()
|
||||
la_fsm_hdl = pkgutil.get_data(__name__, "la_fsm.v").decode()
|
||||
sample_mem_hdl = pkgutil.get_data(__name__, "sample_mem.v").decode()
|
||||
xilinx_bram_hdl = pkgutil.get_data(__name__, "xilinx_true_dual_port_read_first_2_clock_ram.v").decode()
|
||||
trigger_hdl = pkgutil.get_data(__name__, "trigger.v").decode()
|
||||
|
||||
# generate trigger block
|
||||
trigger_block_hdl = self.generate_trigger_block()
|
||||
|
||||
return logic_analyzer_hdl + la_fsm_hdl + sample_mem_hdl + xilinx_bram_hdl + trigger_block_hdl + trigger_hdl
|
||||
|
||||
def hdl_top_level_ports(self):
|
||||
# this should return the probes that we want to connect to top-level, but as a list of verilog ports
|
||||
|
||||
ports = []
|
||||
for name, width in self.probes.items():
|
||||
if width == 1:
|
||||
ports.append(f"input wire {name}")
|
||||
else:
|
||||
ports.append(f"input wire [{width-1}:0] {name}")
|
||||
|
||||
return ports
|
||||
|
||||
def run(self):
|
||||
self.interface.open()
|
||||
self.interface.flushInput()
|
||||
self.interface.write(b"\x30")
|
||||
data = self.interface.read(4096)
|
||||
pass
|
||||
|
||||
def part_select(self, data, width):
|
||||
top, bottom = width
|
||||
|
|
@ -538,29 +635,6 @@ class LogicAnalyzerCore:
|
|||
writer.change(probe, timestamp, val)
|
||||
vcd_file.close()
|
||||
|
||||
def hdl_def(self):
|
||||
# Return an autogenerated verilog module definition for the core.
|
||||
# load source files
|
||||
logic_analyzer_hdl = pkgutil.get_data(__name__, "logic_analyzer.v").decode()
|
||||
la_fsm_hdl = pkgutil.get_data(__name__, "la_fsm.v").decode()
|
||||
sample_mem_hdl = pkgutil.get_data(__name__, "sample_mem.v").decode()
|
||||
xilinx_bram_hdl = pkgutil.get_data(__name__, "xilinx_true_dual_port_read_first_2_clock_ram.v").decode()
|
||||
trigger_block_hdl= pkgutil.get_data(__name__, "trigger_block.v").decode()
|
||||
trigger_hdl = pkgutil.get_data(__name__, "trigger.v").decode()
|
||||
|
||||
return logic_analyzer_hdl + la_fsm_hdl + sample_mem_hdl + xilinx_bram_hdl + trigger_block_hdl + trigger_hdl
|
||||
|
||||
def hdl_top_level_ports(self):
|
||||
# this should return the probes that we want to connect to top-level, but as a list of verilog ports
|
||||
|
||||
ports = []
|
||||
for name, width in self.probes.items():
|
||||
if width == 1:
|
||||
ports.append(f"input wire {name}")
|
||||
else:
|
||||
ports.append(f"input wire [{width-1}:0] {name}")
|
||||
|
||||
return ports
|
||||
|
||||
class Manta:
|
||||
def __init__(self, config_filepath):
|
||||
|
|
|
|||
|
|
@ -0,0 +1,66 @@
|
|||
`default_nettype none
|
||||
`timescale 1ns/1ps
|
||||
|
||||
module trigger_block (
|
||||
input wire clk,
|
||||
|
||||
// probes
|
||||
// @PROBE_PORTS
|
||||
|
||||
// trigger
|
||||
output reg trig,
|
||||
|
||||
// input port
|
||||
input wire [15:0] addr_i,
|
||||
input wire [15:0] wdata_i,
|
||||
input wire [15:0] rdata_i,
|
||||
input wire rw_i,
|
||||
input wire valid_i,
|
||||
|
||||
// output port
|
||||
output reg [15:0] addr_o,
|
||||
output reg [15:0] wdata_o,
|
||||
output reg [15:0] rdata_o,
|
||||
output reg rw_o,
|
||||
output reg valid_o);
|
||||
|
||||
parameter BASE_ADDR = 0;
|
||||
localparam MAX_ADDR = // @MAX_ADDR;
|
||||
|
||||
// trigger configuration registers
|
||||
// - each probe gets an operation and a compare register
|
||||
// - at the end we OR them all together. along with any custom probes the user specs
|
||||
|
||||
// @TRIGGER_MODULE_INSTS
|
||||
|
||||
// @COMBINE_INDIV_TRIGGERS
|
||||
|
||||
// perform register operations
|
||||
always @(posedge clk) begin
|
||||
addr_o <= addr_i;
|
||||
wdata_o <= wdata_i;
|
||||
rdata_o <= rdata_i;
|
||||
rw_o <= rw_i;
|
||||
valid_o <= valid_i;
|
||||
rdata_o <= rdata_i;
|
||||
|
||||
if( (addr_i >= BASE_ADDR) && (addr_i <= BASE_ADDR + MAX_ADDR) ) begin
|
||||
|
||||
// reads
|
||||
if(valid_i && !rw_i) begin
|
||||
case (addr_i)
|
||||
// @READ_CASE_STATEMENT_BODY
|
||||
endcase
|
||||
end
|
||||
|
||||
// writes
|
||||
else if(valid_i && rw_i) begin
|
||||
case (addr_i)
|
||||
// @WRITE_CASE_STATEMENT_BODY
|
||||
endcase
|
||||
end
|
||||
end
|
||||
end
|
||||
endmodule
|
||||
|
||||
`default_nettype wire
|
||||
Loading…
Reference in New Issue