cndm: Add support for Napatech NT200A01/NT200A02

Signed-off-by: Alex Forencich <alex@alexforencich.com>
This commit is contained in:
Alex Forencich
2026-04-06 23:58:50 -07:00
parent cf9c5d5ff3
commit 2ae6e22c2c
27 changed files with 7724 additions and 0 deletions

View File

@@ -0,0 +1,351 @@
# Si534x/7x/8x/9x Registers Script
#
# Part: Si5340
# Project File: X:\Projects\taxi-corundum\src\eth\example\NT200A02\fpga\pll\Si5340-RevD-NT200-Project.slabtimeproj
# Design ID: NT200
# Includes Pre/Post Download Control Register Writes: Yes
# Die Revision: B1
# Creator: ClockBuilder Pro v4.1 [2021-09-22]
# Created On: 2026-04-04 21:47:23 GMT-07:00
Address,Data
#
# Start configuration preamble
0x0B24,0xC0
0x0B25,0x00
# Rev D stuck divider fix
0x0502,0x01
0x0505,0x03
0x0957,0x17
0x0B4E,0x1A
# End configuration preamble
#
# Delay 300 msec
# Delay is worst case time for device to complete any calibration
# that is running due to device state change previous to this script
# being processed.
#
# Start configuration registers
0x0006,0x00
0x0007,0x00
0x0008,0x00
0x000B,0x74
0x0017,0xD0
0x0018,0xFF
0x0021,0x0F
0x0022,0x00
0x002B,0x02
0x002C,0x20
0x002D,0x00
0x002E,0x00
0x002F,0x00
0x0030,0x00
0x0031,0x00
0x0032,0x00
0x0033,0x00
0x0034,0x00
0x0035,0x00
0x0036,0x00
0x0037,0x00
0x0038,0x00
0x0039,0x00
0x003A,0x00
0x003B,0x00
0x003C,0x00
0x003D,0x00
0x0041,0x00
0x0042,0x00
0x0043,0x00
0x0044,0x00
0x009E,0x00
0x0102,0x01
0x0112,0x06
0x0113,0x09
0x0114,0x3B
0x0115,0x28
0x0117,0x06
0x0118,0x09
0x0119,0x3B
0x011A,0x29
0x0126,0x06
0x0127,0x09
0x0128,0x3B
0x0129,0x29
0x012B,0x06
0x012C,0x09
0x012D,0x3B
0x012E,0x29
0x013F,0x00
0x0140,0x00
0x0141,0x40
0x0206,0x00
0x0208,0x00
0x0209,0x00
0x020A,0x00
0x020B,0x00
0x020C,0x00
0x020D,0x00
0x020E,0x00
0x020F,0x00
0x0210,0x00
0x0211,0x00
0x0212,0x00
0x0213,0x00
0x0214,0x00
0x0215,0x00
0x0216,0x00
0x0217,0x00
0x0218,0x00
0x0219,0x00
0x021A,0x00
0x021B,0x00
0x021C,0x00
0x021D,0x00
0x021E,0x00
0x021F,0x00
0x0220,0x00
0x0221,0x00
0x0222,0x00
0x0223,0x00
0x0224,0x00
0x0225,0x00
0x0226,0x00
0x0227,0x00
0x0228,0x00
0x0229,0x00
0x022A,0x00
0x022B,0x00
0x022C,0x00
0x022D,0x00
0x022E,0x00
0x022F,0x00
0x0235,0xA0
0x0236,0x2A
0x0237,0xCD
0x0238,0xD8
0x0239,0xAD
0x023A,0x00
0x023B,0x00
0x023C,0x80
0x023D,0x96
0x023E,0x98
0x0250,0x00
0x0251,0x00
0x0252,0x00
0x0253,0x00
0x0254,0x00
0x0255,0x00
0x025C,0x00
0x025D,0x00
0x025E,0x00
0x025F,0x00
0x0260,0x00
0x0261,0x00
0x026B,0x4E
0x026C,0x54
0x026D,0x32
0x026E,0x30
0x026F,0x30
0x0270,0x00
0x0271,0x00
0x0272,0x00
0x0302,0x00
0x0303,0x00
0x0304,0x00
0x0305,0x00
0x0306,0x0F
0x0307,0x00
0x0308,0x00
0x0309,0x00
0x030A,0x00
0x030B,0x80
0x030C,0x00
0x030D,0xAA
0x030E,0xD2
0x030F,0x8C
0x0310,0xDD
0x0311,0x0A
0x0312,0x00
0x0313,0xFC
0x0314,0x8D
0x0315,0x0E
0x0316,0x80
0x0317,0x00
0x0318,0x00
0x0319,0x00
0x031A,0x00
0x031B,0x00
0x031C,0x00
0x031D,0x00
0x031E,0x00
0x031F,0x00
0x0320,0x00
0x0321,0x00
0x0322,0x00
0x0323,0x00
0x0324,0x00
0x0325,0x00
0x0326,0x00
0x0327,0x00
0x0328,0x00
0x0329,0x00
0x032A,0x00
0x032B,0x00
0x032C,0x00
0x032D,0x00
0x0338,0x00
0x0339,0x1F
0x033B,0x00
0x033C,0x00
0x033D,0x00
0x033E,0x00
0x033F,0x00
0x0340,0x00
0x0341,0x00
0x0342,0x00
0x0343,0x00
0x0344,0x00
0x0345,0x00
0x0346,0x00
0x0347,0x00
0x0348,0x00
0x0349,0x00
0x034A,0x00
0x034B,0x00
0x034C,0x00
0x034D,0x00
0x034E,0x00
0x034F,0x00
0x0350,0x00
0x0351,0x00
0x0352,0x00
0x0359,0x00
0x035A,0x00
0x035B,0x00
0x035C,0x00
0x035D,0x00
0x035E,0x00
0x035F,0x00
0x0360,0x00
0x0802,0x00
0x0803,0x00
0x0804,0x00
0x0805,0x00
0x0806,0x00
0x0807,0x00
0x0808,0x00
0x0809,0x00
0x080A,0x00
0x080B,0x00
0x080C,0x00
0x080D,0x00
0x080E,0x00
0x080F,0x00
0x0810,0x00
0x0811,0x00
0x0812,0x00
0x0813,0x00
0x0814,0x00
0x0815,0x00
0x0816,0x00
0x0817,0x00
0x0818,0x00
0x0819,0x00
0x081A,0x00
0x081B,0x00
0x081C,0x00
0x081D,0x00
0x081E,0x00
0x081F,0x00
0x0820,0x00
0x0821,0x00
0x0822,0x00
0x0823,0x00
0x0824,0x00
0x0825,0x00
0x0826,0x00
0x0827,0x00
0x0828,0x00
0x0829,0x00
0x082A,0x00
0x082B,0x00
0x082C,0x00
0x082D,0x00
0x082E,0x00
0x082F,0x00
0x0830,0x00
0x0831,0x00
0x0832,0x00
0x0833,0x00
0x0834,0x00
0x0835,0x00
0x0836,0x00
0x0837,0x00
0x0838,0x00
0x0839,0x00
0x083A,0x00
0x083B,0x00
0x083C,0x00
0x083D,0x00
0x083E,0x00
0x083F,0x00
0x0840,0x00
0x0841,0x00
0x0842,0x00
0x0843,0x00
0x0844,0x00
0x0845,0x00
0x0846,0x00
0x0847,0x00
0x0848,0x00
0x0849,0x00
0x084A,0x00
0x084B,0x00
0x084C,0x00
0x084D,0x00
0x084E,0x00
0x084F,0x00
0x0850,0x00
0x0851,0x00
0x0852,0x00
0x0853,0x00
0x0854,0x00
0x0855,0x00
0x0856,0x00
0x0857,0x00
0x0858,0x00
0x0859,0x00
0x085A,0x00
0x085B,0x00
0x085C,0x00
0x085D,0x00
0x085E,0x00
0x085F,0x00
0x0860,0x00
0x0861,0x00
0x090E,0x02
0x091C,0x04
0x0943,0x00
0x0949,0x00
0x094A,0x00
0x094E,0x49
0x094F,0x02
0x095E,0x00
0x0A02,0x00
0x0A03,0x03
0x0A04,0x01
0x0A05,0x03
0x0A14,0x00
0x0A1A,0x00
0x0A20,0x00
0x0A26,0x00
0x0B44,0x0F
0x0B4A,0x0C
0x0B57,0x0E
0x0B58,0x01
# End configuration registers
#
# Start configuration postamble
0x001C,0x01
0x0B24,0xC3
0x0B25,0x02
# End configuration postamble

View File

@@ -0,0 +1,642 @@
#!/usr/bin/env python
"""
Generates an I2C init module for multiple chips
"""
from jinja2 import Template
def si5340_cmds(regs, dev_addr=0x77):
cur_page = None
cur_addr = None
cmds = []
print(f"Reading register list file '{regs}'...")
with open(regs, "r") as f:
for line in f:
line = line.strip()
if not line or line == "Address,Data":
continue
if line[0] == '#':
cmds.append(f"// {line[1:].strip()}")
if line.startswith("# Delay"):
cmds.append("cmd_delay(10); // delay 300 ms")
cur_addr = None
continue
d = line.split(",")
addr = int(d[0], 0)
page = (addr >> 8) & 0xff
data = int(d[1], 0)
if page != cur_page:
cmds.append(f"cmd_start(7'h{dev_addr:02x});")
cmds.append("cmd_wr(8'h01);")
cmds.append(f"cmd_wr(8'h{page:02x}); // set page {page:#04x}")
cur_page = page
cur_addr = None
if addr != cur_addr:
cmds.append(f"cmd_start(7'h{dev_addr:02x});")
cmds.append(f"cmd_wr(8'h{addr & 0xff:02x});")
cur_addr = addr
cmds.append(f"cmd_wr(8'h{data:02x}); // write {data:#04x} to {addr:#06x}")
cur_addr += 1
return cmds
def mux_cmds(val, dev_addr):
cmds = []
cmds.append(f"cmd_start(7'h{dev_addr:02x});")
cmds.append(f"cmd_wr(8'h{val:02x});")
cmds.append("cmd_stop(); // I2C stop")
return cmds
def main():
cmds = []
cmds.append("// Initial delay")
cmds.append("cmd_delay(6); // delay 30 ms")
cmds.extend(si5340_cmds("Si5340-RevD-NT200-Registers.txt", 0x74))
generate(cmds, output="si5340_i2c_init.sv")
def generate(cmds=None, name=None, output=None):
if cmds is None:
raise Exception("Command list is required")
if name is None:
name = "si5340_i2c_init"
if output is None:
output = name + ".sv"
print(f"Generating Si5340 I2C init module {name}...")
cmds = cmds.copy()
cmds.append("cmd_halt(); // end")
cmd_str = ""
cmd_count = 0
for cmd in cmds:
if cmd.startswith('//'):
cmd_str += f" {cmd}\n"
else:
cmd_str += f" init_data[{cmd_count}] = {cmd}\n"
cmd_count += 1
t = Template(u"""// SPDX-License-Identifier: CERN-OHL-S-2.0
/*
Copyright (c) 2015-2026 FPGA Ninja, LLC
Authors:
- Alex Forencich
*/
`resetall
`timescale 1ns / 1ps
`default_nettype none
/*
* {{name}}
*/
module {{name}} #
(
parameter logic SIM_SPEEDUP = 1'b0
)
(
input wire logic clk,
input wire logic rst,
/*
* I2C master interface
*/
taxi_axis_if.src m_axis_cmd,
taxi_axis_if.src m_axis_tx,
/*
* Status
*/
output wire logic busy,
/*
* Configuration
*/
input wire logic start
);
/*
Generic module for I2C bus initialization. Good for use when multiple devices
on an I2C bus must be initialized on system start without intervention of a
general-purpose processor.
Copy this file and change init_data and INIT_DATA_LEN as needed.
This module can be used in two modes: simple device initialization, or multiple
device initialization. In multiple device mode, the same initialization sequence
can be performed on multiple different device addresses.
To use single device mode, only use the start write to address and write data commands.
The module will generate the I2C commands in sequential order. Terminate the list
with a 0 entry.
To use the multiple device mode, use the start data and start address block commands
to set up lists of initialization data and device addresses. The module enters
multiple device mode upon seeing a start data block command. The module stores the
offset of the start of the data block and then skips ahead until it reaches a start
address block command. The module will store the offset to the address block and
read the first address in the block. Then it will jump back to the data block
and execute it, substituting the stored address for each current address write
command. Upon reaching the start address block command, the module will read out the
next address and start again at the top of the data block. If the module encounters
a start data block command while looking for an address, then it will store a new data
offset and then look for a start address block command. Terminate the list with a 0
entry. Normal address commands will operate normally inside a data block.
Commands:
00 0000000 : stop
00 0000001 : exit multiple device mode
00 0000011 : start write to current address
00 0001000 : start address block
00 0001001 : start data block
00 001dddd : delay 2**(16+d) cycles
00 1000001 : send I2C stop
01 aaaaaaa : start write to address
1 dddddddd : write 8-bit data
Examples
write 0x11223344 to register 0x0004 on device at 0x50
01 1010000 start write to 0x50
1 00000000 write address 0x0004
1 00000100
1 00010001 write data 0x11223344
1 00100010
1 00110011
1 01000100
0 00000000 stop
write 0x11223344 to register 0x0004 on devices at 0x50, 0x51, 0x52, and 0x53
00 0001001 start data block
00 0000011 start write to current address
1 00000000 write address 0x0004
1 00000100
1 00010001 write data 0x11223344
1 00100010
1 00110011
1 01000100
00 0001000 start address block
01 1010000 address 0x50
01 1010001 address 0x51
01 1010010 address 0x52
01 1010011 address 0x53
00 0000001 exit multi-dev mode
00 0000000 stop
*/
// check configuration
if (m_axis_cmd.DATA_W < 12)
$fatal(0, "Command interface width must be at least 12 bits (instance %m)");
if (m_axis_tx.DATA_W != 8)
$fatal(0, "Data interface width must be 8 bits (instance %m)");
function [8:0] cmd_start(input [6:0] addr);
cmd_start = {2'b01, addr};
endfunction
function [8:0] cmd_wr(input [7:0] data);
cmd_wr = {1'b1, data};
endfunction
function [8:0] cmd_stop();
cmd_stop = {2'b00, 7'b1000001};
endfunction
function [8:0] cmd_delay(input [3:0] d);
cmd_delay = {2'b00, 3'b001, d};
endfunction
function [8:0] cmd_halt();
cmd_halt = 9'd0;
endfunction
function [8:0] blk_start_data();
blk_start_data = {2'b00, 7'b0001001};
endfunction
function [8:0] blk_start_addr();
blk_start_addr = {2'b00, 7'b0001000};
endfunction
function [8:0] cmd_start_cur();
cmd_start_cur = {2'b00, 7'b0000011};
endfunction
function [8:0] cmd_exit();
cmd_exit = {2'b00, 7'b0000001};
endfunction
// init_data ROM
localparam INIT_DATA_LEN = {{cmd_count}};
reg [8:0] init_data [INIT_DATA_LEN-1:0];
initial begin
{{cmd_str-}}
end
typedef enum logic [2:0] {
STATE_IDLE,
STATE_RUN,
STATE_TABLE_1,
STATE_TABLE_2,
STATE_TABLE_3
} state_t;
state_t state_reg = STATE_IDLE, state_next;
localparam AW = $clog2(INIT_DATA_LEN);
logic [8:0] init_data_reg = '0;
logic [AW-1:0] address_reg = '0, address_next;
logic [AW-1:0] address_ptr_reg = '0, address_ptr_next;
logic [AW-1:0] data_ptr_reg = '0, data_ptr_next;
logic [6:0] cur_address_reg = '0, cur_address_next;
logic [31:0] delay_counter_reg = '0, delay_counter_next;
logic [6:0] m_axis_cmd_address_reg = '0, m_axis_cmd_address_next;
logic m_axis_cmd_start_reg = 1'b0, m_axis_cmd_start_next;
logic m_axis_cmd_write_reg = 1'b0, m_axis_cmd_write_next;
logic m_axis_cmd_stop_reg = 1'b0, m_axis_cmd_stop_next;
logic m_axis_cmd_valid_reg = 1'b0, m_axis_cmd_valid_next;
logic [7:0] m_axis_tx_tdata_reg = '0, m_axis_tx_tdata_next;
logic m_axis_tx_tvalid_reg = 1'b0, m_axis_tx_tvalid_next;
logic start_flag_reg = 1'b0, start_flag_next;
logic busy_reg = 1'b0;
assign m_axis_cmd.tdata[6:0] = m_axis_cmd_address_reg;
assign m_axis_cmd.tdata[7] = m_axis_cmd_start_reg;
assign m_axis_cmd.tdata[8] = 1'b0; // read
assign m_axis_cmd.tdata[9] = m_axis_cmd_write_reg;
assign m_axis_cmd.tdata[10] = 1'b0; // write multi
assign m_axis_cmd.tdata[11] = m_axis_cmd_stop_reg;
assign m_axis_cmd.tvalid = m_axis_cmd_valid_reg;
assign m_axis_cmd.tlast = 1'b1;
assign m_axis_cmd.tid = '0;
assign m_axis_cmd.tdest = '0;
assign m_axis_cmd.tuser = '0;
assign m_axis_tx.tdata = m_axis_tx_tdata_reg;
assign m_axis_tx.tvalid = m_axis_tx_tvalid_reg;
assign m_axis_tx.tlast = 1'b1;
assign m_axis_tx.tid = '0;
assign m_axis_tx.tdest = '0;
assign m_axis_tx.tuser = '0;
assign busy = busy_reg;
always_comb begin
state_next = STATE_IDLE;
address_next = address_reg;
address_ptr_next = address_ptr_reg;
data_ptr_next = data_ptr_reg;
cur_address_next = cur_address_reg;
delay_counter_next = delay_counter_reg;
m_axis_cmd_address_next = m_axis_cmd_address_reg;
m_axis_cmd_start_next = m_axis_cmd_start_reg && !(m_axis_cmd.tvalid && m_axis_cmd.tready);
m_axis_cmd_write_next = m_axis_cmd_write_reg && !(m_axis_cmd.tvalid && m_axis_cmd.tready);
m_axis_cmd_stop_next = m_axis_cmd_stop_reg && !(m_axis_cmd.tvalid && m_axis_cmd.tready);
m_axis_cmd_valid_next = m_axis_cmd_valid_reg && !m_axis_cmd.tready;
m_axis_tx_tdata_next = m_axis_tx_tdata_reg;
m_axis_tx_tvalid_next = m_axis_tx_tvalid_reg && !m_axis_tx.tready;
start_flag_next = start_flag_reg;
if (m_axis_cmd.tvalid || m_axis_tx.tvalid) begin
// wait for output registers to clear
state_next = state_reg;
end else if (delay_counter_reg != 0) begin
// delay
delay_counter_next = delay_counter_reg - 1;
state_next = state_reg;
end else begin
case (state_reg)
STATE_IDLE: begin
// wait for start signal
if (!start_flag_reg && start) begin
address_next = '0;
start_flag_next = 1'b1;
state_next = STATE_RUN;
end else begin
state_next = STATE_IDLE;
end
end
STATE_RUN: begin
// process commands
if (init_data_reg[8] == 1'b1) begin
// write data
m_axis_cmd_write_next = 1'b1;
m_axis_cmd_stop_next = 1'b0;
m_axis_cmd_valid_next = 1'b1;
m_axis_tx_tdata_next = init_data_reg[7:0];
m_axis_tx_tvalid_next = 1'b1;
address_next = address_reg + 1;
state_next = STATE_RUN;
end else if (init_data_reg[8:7] == 2'b01) begin
// write address
m_axis_cmd_address_next = init_data_reg[6:0];
m_axis_cmd_start_next = 1'b1;
address_next = address_reg + 1;
state_next = STATE_RUN;
end else if (init_data_reg[8:4] == 5'b00001) begin
// delay
if (SIM_SPEEDUP) begin
delay_counter_next = 32'd1 << (init_data_reg[3:0]);
end else begin
delay_counter_next = 32'd1 << (init_data_reg[3:0]+16);
end
address_next = address_reg + 1;
state_next = STATE_RUN;
end else if (init_data_reg == 9'b001000001) begin
// send stop
m_axis_cmd_write_next = 1'b0;
m_axis_cmd_start_next = 1'b0;
m_axis_cmd_stop_next = 1'b1;
m_axis_cmd_valid_next = 1'b1;
address_next = address_reg + 1;
state_next = STATE_RUN;
end else if (init_data_reg == 9'b000001001) begin
// data table start
data_ptr_next = address_reg + 1;
address_next = address_reg + 1;
state_next = STATE_TABLE_1;
end else if (init_data_reg == 9'd0) begin
// stop
m_axis_cmd_start_next = 1'b0;
m_axis_cmd_write_next = 1'b0;
m_axis_cmd_stop_next = 1'b1;
m_axis_cmd_valid_next = 1'b1;
state_next = STATE_IDLE;
end else begin
// invalid command, skip
address_next = address_reg + 1;
state_next = STATE_RUN;
end
end
STATE_TABLE_1: begin
// find address table start
if (init_data_reg == 9'b000001000) begin
// address table start
address_ptr_next = address_reg + 1;
address_next = address_reg + 1;
state_next = STATE_TABLE_2;
end else if (init_data_reg == 9'b000001001) begin
// data table start
data_ptr_next = address_reg + 1;
address_next = address_reg + 1;
state_next = STATE_TABLE_1;
end else if (init_data_reg == 1) begin
// exit mode
address_next = address_reg + 1;
state_next = STATE_RUN;
end else if (init_data_reg == 9'd0) begin
// stop
m_axis_cmd_start_next = 1'b0;
m_axis_cmd_write_next = 1'b0;
m_axis_cmd_stop_next = 1'b1;
m_axis_cmd_valid_next = 1'b1;
state_next = STATE_IDLE;
end else begin
// invalid command, skip
address_next = address_reg + 1;
state_next = STATE_TABLE_1;
end
end
STATE_TABLE_2: begin
// find next address
if (init_data_reg[8:7] == 2'b01) begin
// write address command
// store address and move to data table
cur_address_next = init_data_reg[6:0];
address_ptr_next = address_reg + 1;
address_next = data_ptr_reg;
state_next = STATE_TABLE_3;
end else if (init_data_reg == 9'b000001001) begin
// data table start
data_ptr_next = address_reg + 1;
address_next = address_reg + 1;
state_next = STATE_TABLE_1;
end else if (init_data_reg == 9'd1) begin
// exit mode
address_next = address_reg + 1;
state_next = STATE_RUN;
end else if (init_data_reg == 9'd0) begin
// stop
m_axis_cmd_start_next = 1'b0;
m_axis_cmd_write_next = 1'b0;
m_axis_cmd_stop_next = 1'b1;
m_axis_cmd_valid_next = 1'b1;
state_next = STATE_IDLE;
end else begin
// invalid command, skip
address_next = address_reg + 1;
state_next = STATE_TABLE_2;
end
end
STATE_TABLE_3: begin
// process data table with selected address
if (init_data_reg[8] == 1'b1) begin
// write data
m_axis_cmd_write_next = 1'b1;
m_axis_cmd_stop_next = 1'b0;
m_axis_cmd_valid_next = 1'b1;
m_axis_tx_tdata_next = init_data_reg[7:0];
m_axis_tx_tvalid_next = 1'b1;
address_next = address_reg + 1;
state_next = STATE_TABLE_3;
end else if (init_data_reg[8:7] == 2'b01) begin
// write address
m_axis_cmd_address_next = init_data_reg[6:0];
m_axis_cmd_start_next = 1'b1;
address_next = address_reg + 1;
state_next = STATE_TABLE_3;
end else if (init_data_reg == 9'b000000011) begin
// write current address
m_axis_cmd_address_next = cur_address_reg;
m_axis_cmd_start_next = 1'b1;
address_next = address_reg + 1;
state_next = STATE_TABLE_3;
end else if (init_data_reg[8:4] == 5'b00001) begin
// delay
if (SIM_SPEEDUP) begin
delay_counter_next = 32'd1 << (init_data_reg[3:0]);
end else begin
delay_counter_next = 32'd1 << (init_data_reg[3:0]+16);
end
address_next = address_reg + 1;
state_next = STATE_TABLE_3;
end else if (init_data_reg == 9'b001000001) begin
// send stop
m_axis_cmd_write_next = 1'b0;
m_axis_cmd_start_next = 1'b0;
m_axis_cmd_stop_next = 1'b1;
m_axis_cmd_valid_next = 1'b1;
address_next = address_reg + 1;
state_next = STATE_TABLE_3;
end else if (init_data_reg == 9'b000001001) begin
// data table start
data_ptr_next = address_reg + 1;
address_next = address_reg + 1;
state_next = STATE_TABLE_1;
end else if (init_data_reg == 9'b000001000) begin
// address table start
address_next = address_ptr_reg;
state_next = STATE_TABLE_2;
end else if (init_data_reg == 9'd1) begin
// exit mode
address_next = address_reg + 1;
state_next = STATE_RUN;
end else if (init_data_reg == 9'd0) begin
// stop
m_axis_cmd_start_next = 1'b0;
m_axis_cmd_write_next = 1'b0;
m_axis_cmd_stop_next = 1'b1;
m_axis_cmd_valid_next = 1'b1;
state_next = STATE_IDLE;
end else begin
// invalid command, skip
address_next = address_reg + 1;
state_next = STATE_TABLE_3;
end
end
default: begin
// invalid state
state_next = STATE_IDLE;
end
endcase
end
end
always_ff @(posedge clk) begin
state_reg <= state_next;
// read init_data ROM
init_data_reg <= init_data[address_next];
address_reg <= address_next;
address_ptr_reg <= address_ptr_next;
data_ptr_reg <= data_ptr_next;
cur_address_reg <= cur_address_next;
delay_counter_reg <= delay_counter_next;
m_axis_cmd_address_reg <= m_axis_cmd_address_next;
m_axis_cmd_start_reg <= m_axis_cmd_start_next;
m_axis_cmd_write_reg <= m_axis_cmd_write_next;
m_axis_cmd_stop_reg <= m_axis_cmd_stop_next;
m_axis_cmd_valid_reg <= m_axis_cmd_valid_next;
m_axis_tx_tdata_reg <= m_axis_tx_tdata_next;
m_axis_tx_tvalid_reg <= m_axis_tx_tvalid_next;
start_flag_reg <= start && start_flag_next;
busy_reg <= (state_reg != STATE_IDLE);
if (rst) begin
state_reg <= STATE_IDLE;
init_data_reg <= '0;
address_reg <= '0;
address_ptr_reg <= '0;
data_ptr_reg <= '0;
cur_address_reg <= '0;
delay_counter_reg <= '0;
m_axis_cmd_valid_reg <= 1'b0;
m_axis_tx_tvalid_reg <= 1'b0;
start_flag_reg <= 1'b0;
busy_reg <= 1'b0;
end
end
endmodule
`resetall
""")
print(f"Writing file '{output}'...")
with open(output, 'w') as f:
f.write(t.render(
cmd_str=cmd_str,
cmd_count=cmd_count,
name=name
))
f.flush()
print("Done")
if __name__ == "__main__":
main()

File diff suppressed because it is too large Load Diff