程序主要实现以下功能:
功能:通过 PLL(锁相环)产生多组时钟,满足不同模块的时序需求,如 ADC 采样时钟、网络协议栈时钟等。
功能:
ad_data_gen:arm_cap信号高电平到来后,start_ad置1,LED 点亮,开始采集;total_sample_cnt记录已采集的样本数,采样模式为单次模式下,达到total_sample_num后停止,流式模式下,通过stop_trigger强制中断采集流程。
b64_data_gen:模块接收6个32通道16位数据,通过sampling_len实现降采样,例如sample_coef=2时,每 2 个原始样本取 1 个;all_ch_counter根据掩码计算总有效通道数ch_len;之后循环遍历 6 个模块的 32 通道,每次处理 1 个 16 位通道数据,4 次拼接成 64 位帧,b64_cnt跟踪拼接进度,完成 4 次拼接后输出有效 64 位帧;异步 FIFO 实现从 96MHz 到 100MHz 时钟域的转换,read_b64_ready控制数据读出。
功能:
每次输入 4 通道数据,将其封装为 BLOB,若 BLOB 总长度超过 UDP 负载上限,自动计算切片数量和每切片采样点数;之后通过状态机进行切片处理,最终输出 AXI Stream 格式数据。
// BLOB数据缓存与UDP传输
blob_fifo_udp_transmit blob_fifo_udp_transmit_inst(
.s_data_slice_axis_tdata(...) // 输入数据切片
.m_udp_payload_axis_tdata(...) // 输出UDP负载数据
);
// UDP/IP协议栈
UDP_IP_MAC #(
.LOCAL_IP({8'd192, 8'd168, 8'd1, 8'd10}) // 本地IP地址
) UDP_IP_MAC_0_inst(...);
// UDP回环测试(用于调试)
UDP_ECHO #(
.LOCAL_PORT(16'd8010) // 本地端口号
) UDP_ECHO_inst(...);
功能: blob_fifo_udp_transmit将 BLOB 数据通过 FIFO 缓存后,转换为 UDP 负载; UDP_IP_MAC实现 IP 层与 UDP 层协议,支持数据发送与接收; UDP_ECHO实现数据回环,用于测试网络链路连通性。
功能:控制 SFP 光模块的电气特性,实现光纤信号的收发,并生成网络物理层所需的时钟。
该模块用于模拟产生32通道ADC采集数据。
输入输出信号:
module ad_data_gen(
input ad_clk, // 100mhz时钟
input ad_rst, // 100mhz时钟对应的复位信号,高电平有效
input arm_cap, // 触发信号,该信号的高电平脉冲到来后开始产生模拟采集数据
input [31:0]sample_rate, // 32位采样率,设定的是32'd2_000_000,即2M
input [7:0] stream_mode, // 工作模式,为0时采样total_sample_num次后就停止采样,不为0时接收到stop_trigger信号后停止采样
input stop_trigger, // 停止触发信号
input [31:0]total_sample_num, // 每次采样次数
output led_o, // 工作状态与led关联,led亮起时表明正在模拟产生adc采样数据
output start_ad, // 高电平时表明正在模拟产生adc采集数据
// sample data output.
input ad_data_ready, // 阅读这个模块,ad_data_ready信号没有用上
output ad_data_valid, // 每次上升沿表示更新一次ad_data_32ch数据
output ad_data_32ch // 输出的32通道数据
);
系统工作流程:
输入输出信号:
module b64_data_gen(
input clk_100m, // 100mhz时钟信号
input clk_384m, // 384mhz时钟信号,用于b16数据产生
input clk_96m, // 96mhz时钟信号,用于b64数据产生
input rst, // 复位信号,与384mhz时钟、96mhz时钟关联
input rst_locked, // 与100mhz时钟关联的复位信号
// 复制6次32通道adc采集数据
input [511:0] module1_data,
input [511:0] module2_data,
input [511:0] module3_data,
input [511:0] module4_data,
input [511:0] module5_data,
input [511:0] module6_data,
input ad_data_valid, // ad采集数据更新信号
input [31:0]total_sample_num, // 总采样数,程序中设置为5次
// 通过掩码指示32*6个通道数据中,哪些通道数据有效,用于屏蔽不需要的通道,只处理有效通道的数据
input [31:0] module1_mask,
input [31:0] module2_mask,
input [31:0] module3_mask,
input [31:0] module4_mask,
input [31:0] module5_mask,
input [31:0] module6_mask,
input [7:0] sr_coef, // 二次调整采样率相关的时间参数,与sample_coef配合使用
input [7:0] sample_coef, // 数据采集的下采样比率,用于降低原始采样数据的频率,例如,若sample_coef=4,则每 4 个原始采样点仅保留 1 个,采样率降为原来的 1/4
//程序中上面两个变量已经设定的值都是1,那就不用进行降采样,直接按照原始采样率即可
output [7:0] channel_num, // 显示当前有效通道的数量,由掩码中1计数得到
output [63:0] b64_data_reg,
output b64_valid_reg,
output sample_end_reg, // 指向新采样周期的开始,用于同步后续处理模块
output sample_last_reg, // 标记真正的最后一个有效数据,用于数据帧边界识别。
output sample_last_last_reg, // 通知系统 “下一个是最后一个有效数据”,用于提前准备结束逻辑
//ila data,用于ila进行的调试
output reg [15:0] b16_data, // 单通道数据,是b64数据生成的中间数据
output reg b16_data_valid, //指示单通道数据是否有效
output reg [63:0] b64_data,
output reg b64_valid,
output reg [63:0] b64_data_long,
output reg b64_valid_long,
output reg b64_valid_short,
input read_b64_ready, // ad_data_blob_generator模块输入的信号,用于控制本模块中fifo读出数据
output b64_en_sync_wire, //高电平时表示正在将数据转换成为4通道64b格式数据
output [7:0] sampling_cnt_wire,
output [31:0] total_sample_cnt_wire, // 总采样计数器,显示已完成的采样点数
output [63:0] sampling_data_wire,
output [7:0] down_sample_cnt_wire, // 下采样分频计数器,显示当前分频计数状态
output [5:0] module_ch_cnt_wire, // 模块通道计数器,指示当前处理的通道号
output [3:0] module_cnt_wire, // 模块计数器,指示当前处理的模块号
output [63:0] module_data_wire,
output [31:0] module_mask_wire,
output finish_wire, // 整个采样过程结束标志(所有样本采集完成)
output sample_end_wire, // 样本结束标志(单个样本处理完成)
output sample_end_long_wire
);
系统工作流程:
输入输出信号:
module ad_data_blob_generator #
(
// maximum UDP payload length
parameter MAX_PAYLOAD_LENGTH = 40,
// one data blob's sample length.
parameter BLOB_SAMPLE_LENGTH = 8,
// input channel number.
parameter AD_CHANNEL = 4,
// input ad data length in bytes
parameter AD_DATA_LENGTH = 2,
// input and output data width
parameter DATA_WIDTH = 64,
// AXIS output KEEP_WIDTH = DATA_WDITH/8
parameter KEEP_WIDTH = 8,
// AXIS user signal width.
parameter USER_WIDTH = 1,
// config information request send interval.
parameter REQUEST_SEND_INTERVAL = {32'd100000000}
)
(
// 使用100mhz时钟
input wire clk,
input wire rst,
// request for AD blob generators config signals.
input wire config_request_send,
input wire config_request_succed,
// ADC data input.
input wire [63:0] ad_data_4ch, // 即上面生成的b64_data
output wire ad_blob_ready,
input b64_valid, // 高电平时可以读b64_data
input sample_end, // 采样周期结束信号
input sample_last, // 采样周期内最后一个信号标记
input sample_last_last, //倒数第二个信号标记
output read_b64_ready,
output read_b64_ready_nxt,
input start_ad, // 前面ad_data_gen开始产生ADC采集数据
// AD parameter
input [7:0] job_id,
input wire [31:0] sample_rate, // 采样率
input wire [7:0] channel_num, // 通道数
input wire [31:0] sample_point_num, // 每个 Blob 包含的采样点数
input wire [7:0] sample_coef, // 降采样倍率
// slice and blob output via axis.
output wire [DATA_WIDTH-1:0] m_data_slice_axis_tdata,
output wire [KEEP_WIDTH-1:0] m_data_slice_axis_tkeep,
output wire m_data_slice_axis_tvalid,
input wire m_data_slice_axis_tready,
output wire m_data_slice_axis_tlast,
output wire [USER_WIDTH-1:0] m_data_slice_axis_tuser,
output wire [7:0] m_data_slice_sa_len,
output wire [15:0] m_data_slice_axis_tlen,
output data_blob_sa_len,
output data_blob_payload_len,
output data_slice_number,
output data_slice_prev_sa_len,
output data_slice_last_sa_len,
output data_slice_divisible,
output state_ge_reg,
output state_ge_next,
output data_blob_cnt,
output data_blob_cnt_next,
output data_slice_cnt,
output data_slice_cnt_next,
output data_slice_sa_cnt,
output data_slice_sa_cnt_next,
output config_request_send_timer,
output config_request_send_timer_next,
output wire m_data_slice_ready,
output wire m_data_blob_ready
);
工作流程:
Blob:
Slice分割规则:
状态机状态设置如下:
localparam [3:0]
STATE_GE_IDLE = 4'd0, // 空闲
STATE_GE_CONFIG = 4'd1, // 配置信息发送
STATE_GE_CONFIG_LAST = 4'd2, // 配置信息发送最后一拍
STATE_GE_HEADER = 4'd3, // Blob/Slice 头部生成
STATE_GE_HEADER_LAST = 4'd8, // 头部生成分两周期发送
STATE_GE_SLICE = 4'd4, // 采样数据传输(普通 Slice)
STATE_GE_SLICE_LAST = 4'd5, // 采样数据传输(最后一个 Slice)
STATE_GE_SLICE_END = 4'd6, // Slice 传输结束
STATE_GE_BLOB_END = 4'd7; // Blob 传输结束
状态机跳转逻辑正在理解,可以结合龙哥的论文来看。
目前程序可以考虑将ad_data_gen模块修改为数据解码模块后的数据处理模块,数据解码模块需要根据ad_data_gen的逻辑调整。
原来的数据解码模块是通过fifo依次输出32通道16位数据,如果要对接过来,需要设置逻辑,将单词采样的所有数据组装成32通道的512位数据,组装完成后输出,同时提供ad_data_valid信号表明传输后的采集数据已更新。本质上就是需要将传输后的数据转换成便于打包的形式。
现在还需要注意程序中时钟、采样率等问题,而且最后要做成的目标也得结合龙哥论文、杰哥limfx文章来明确清楚。
本文章使用limfx的vscode插件快速发布