mirror of
https://github.com/fpganinja/taxi.git
synced 2026-04-09 05:18:44 -07:00
cndm: Add support for Napatech NT200A01/NT200A02
Signed-off-by: Alex Forencich <alex@alexforencich.com>
This commit is contained in:
BIN
src/cndm/board/NT200A02/fpga/pll/Si5340-RevD-NT200-Project.slabtimeproj
Executable file
BIN
src/cndm/board/NT200A02/fpga/pll/Si5340-RevD-NT200-Project.slabtimeproj
Executable file
Binary file not shown.
351
src/cndm/board/NT200A02/fpga/pll/Si5340-RevD-NT200-Registers.txt
Executable file
351
src/cndm/board/NT200A02/fpga/pll/Si5340-RevD-NT200-Registers.txt
Executable 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
|
||||
642
src/cndm/board/NT200A02/fpga/pll/si5340_i2c_init.py
Executable file
642
src/cndm/board/NT200A02/fpga/pll/si5340_i2c_init.py
Executable 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()
|
||||
1013
src/cndm/board/NT200A02/fpga/pll/si5340_i2c_init.sv
Normal file
1013
src/cndm/board/NT200A02/fpga/pll/si5340_i2c_init.sv
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user