目录
一.基本信息
参赛厂商:AMD
参赛平台:基于AMD的FPGA/Zynq/Versal器件(无资源限制)
开发方向:基于AMD板卡的综合类赛道
开发平台:正点原子 DFZU2EG MPSoc 开发板
平台资源:
Application Processing Unit | Quad-core Arm® Cortex®-A53 MPCore™ up to 1.5GHz |
---|---|
Real-Time Processing Unit | Dual-core Arm Cortex-R5F MPCore™ up to 600MHz |
Graphics Processing Unit | Arm Mali™-400 MP2 up to 667MHz |
Dynamic Memory Interface | DDR4, LPDDR4, DDR3, DDR3L, LPDDR3 |
High-Speed Peripherals | PCIe® Gen2, USB3.0, SATA 3.1, DisplayPort, Gigabit |
Ethernet |
103k System Logic Cells,6.5MB Total RAM,240 DSP Slices,252 Maximum I/O Pins
作品名称:基于FPGA的图神经网络传感器系统
作品简介:
对传感器系统进行建模,生成图模型并利用图神经网络对传感器系统运行状态进行评估。作品首先采集大量传感器数据,并根据事先对传感器群建模成图的模型,将传感器输出信号进行分析,主要分析图网络频域特性,进行初步判断然后用深度学习训练数据集,分析系统的状态。应用场景比如复杂环境因素影响下的农作物种植情况分析,工厂机械臂分析运行出错过热,太空站或基地的外壳完整性检测等。
二.设计记录
1.任务分解
信号采集接口(多路信号采集、多种信号类型接口:通信协议接口、电压接口),数据打包模块,上层数据处理,结果显示模块。
2.模块设计
<1>ADC模块
输入:多路电压采集
输出:采用通信协议进行串行/时分复用并行输出
实现:利用stm32的ADC通道采集多路传感器信息,利用usart发送数据。
<2>数据接收模块
输入:下位机(stm32)usart串行输入数据
输出:每字节数据及数据有效位
实现:Verillog编写usart解码模块
<3>数据解包模块
输入:数据接收模块输出的每字节数据及数据有效位
输出:10个传感器并行的120位数据
实现:解析数据流识别数据包头(“FF”)和有效数据
<4>数据处理模块
输入:10个传感器并行的120位数据
输出:10bit的10个传感器异常与否判断
实现:利用HLS综合C语言算法实现输入到输出的转换函数(IP 核)
三.设计实践
1.adc_stm32 信号采集模块
利用 stm32 最小系统板上 ADC1 的 10 个通道资源,利用 DMA1 数据转运,通过1路 usart 串行发送出去。
stm32关键代码:
(1)初始化stm32的多个ADC外设并启用DMA转运
void AD_Init(void)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
// RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
RCC_ADCCLKConfig(RCC_PCLK2_Div6); //72M/6=12,ADC最大时间不能超过14M
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN; //设置模拟输入模式
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3 | GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1;
GPIO_Init(GPIOB, &GPIO_InitStructure);
// GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3 | GPIO_Pin_4 | GPIO_Pin_5;
// GPIO_Init(GPIOC, &GPIO_InitStructure);
//ADC1,ADC通道x,规则采样顺序值为y,采样时间为55.5周期
ADC_RegularChannelConfig(ADC1, ADC_Channel_0, 1, ADC_SampleTime_55Cycles5);
ADC_RegularChannelConfig(ADC1, ADC_Channel_1, 2, ADC_SampleTime_55Cycles5);
ADC_RegularChannelConfig(ADC1, ADC_Channel_2, 3, ADC_SampleTime_55Cycles5);
ADC_RegularChannelConfig(ADC1, ADC_Channel_3, 4, ADC_SampleTime_55Cycles5);
ADC_RegularChannelConfig(ADC1, ADC_Channel_4, 5, ADC_SampleTime_55Cycles5);
ADC_RegularChannelConfig(ADC1, ADC_Channel_5, 6, ADC_SampleTime_55Cycles5);
ADC_RegularChannelConfig(ADC1, ADC_Channel_6, 7, ADC_SampleTime_55Cycles5);
ADC_RegularChannelConfig(ADC1, ADC_Channel_7, 8, ADC_SampleTime_55Cycles5);
ADC_RegularChannelConfig(ADC1, ADC_Channel_8, 9, ADC_SampleTime_55Cycles5);
ADC_RegularChannelConfig(ADC1, ADC_Channel_9, 10, ADC_SampleTime_55Cycles5);
// ADC_RegularChannelConfig(ADC1, ADC_Channel_10, 11, ADC_SampleTime_55Cycles5);
// ADC_RegularChannelConfig(ADC1, ADC_Channel_11, 12, ADC_SampleTime_55Cycles5);
// ADC_RegularChannelConfig(ADC1, ADC_Channel_12, 13, ADC_SampleTime_55Cycles5);
// ADC_RegularChannelConfig(ADC1, ADC_Channel_13, 14, ADC_SampleTime_55Cycles5);
// ADC_RegularChannelConfig(ADC1, ADC_Channel_14, 15, ADC_SampleTime_55Cycles5);
// ADC_RegularChannelConfig(ADC1, ADC_Channel_15, 16, ADC_SampleTime_55Cycles5);
ADC_InitTypeDef ADC_InitStructure;
ADC_InitStructure.ADC_Mode = ADC_Mode_Independent; //ADC工作在独立模式
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; //ADC数据右对齐
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None; //外部触发转换关闭
ADC_InitStructure.ADC_ContinuousConvMode = ENABLE; //模数转换工作在连续转换模式
ADC_InitStructure.ADC_ScanConvMode = ENABLE; //是否使用扫描模式
ADC_InitStructure.ADC_NbrOfChannel = CHANNEL_NUM; //顺序进行规则转换的ADC通道的数目
ADC_Init(ADC1, &ADC_InitStructure);
//DMA初始化
DMA_InitTypeDef DMA_InitStructure;
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&ADC1->DR; //DMA外设ADC基地址
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord; //数据宽度为16位
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; //外设地址寄存器不变
DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)AD_Value; //DMA外设ADC基地址
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord; //数据宽度为16位
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; //内存地址寄存器递增
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC; //内存作为数据传输的目的地
DMA_InitStructure.DMA_BufferSize = CHANNEL_NUM; //DMA通道的DMA缓存的大小
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular; //工作在循环缓存模式
//M2M是否使用软件触发
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; //DMA通道x没有设置为内存到内存传输
DMA_InitStructure.DMA_Priority = DMA_Priority_Medium; //DMA通道 x拥有中优先级
DMA_Init(DMA1_Channel1, &DMA_InitStructure);
//外设使能
DMA_Cmd(DMA1_Channel1, ENABLE);
ADC_DMACmd(ADC1, ENABLE);
ADC_Cmd(ADC1, ENABLE);
//复位校准寄存器
ADC_ResetCalibration(ADC1);
while (ADC_GetResetCalibrationStatus(ADC1) == SET);
ADC_StartCalibration(ADC1);
while (ADC_GetCalibrationStatus(ADC1) == SET);
ADC_SoftwareStartConvCmd(ADC1, ENABLE);
}
(2)初始化stm32的多个ADC外设并启用DMA转运
void Get_Voltage()
{
int i=0;
//数据包起始标志
Usart_TransmitByte(0xFF);
Usart_TransmitByte(0xFF);
for(i=0;i<CHANNEL_NUM;i++)
{
Usart_TransmitByte(AD_Value[i]>>8);
Usart_TransmitByte(AD_Value[i]&0x00FF);
}
}
2.proc_fpga FPGA主体模块
利用 xilinx zynq 接收 stm32 发送的数据并进行处理。
系统框图:
实际本体是uart_rx——decoder——signal_proc三部分,rs232与电脑通信测试时使用。
<1>uart协议数据接收模块——uart_rx
这里uart_rx、uart_tx、rs232模块代码沿用之前学习代码。
<2>串行数据解码模块——decoder
代码解析:
`timescale 1ns / 1ps
module decoder
#(
parameter CHANNEL_NUM = 4'd10 //传感器通道数
)
(
input wire sys_rst_n ,
input wire [7:0] data_serial ,
input wire in_flag ,
output reg [119:0] data_parallel ,
output reg out_flag
);
reg [3:0] channel_cnt ;
reg byte_cnt ;
reg r_en ;
//r_en串行数据解码标志
always@(posedge in_flag or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
r_en <= 1'b0;
else if(data_serial == 8'hFF && byte_cnt == 1'b1)
r_en <= 1'b1;
else if(channel_cnt > CHANNEL_NUM)
r_en <= 1'b0;
else
r_en <= r_en;
//byte_cnt数据高低字节计数
always@(posedge in_flag or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
byte_cnt <= 1'b0;
else if(r_en == 1'b1)
byte_cnt <= ~byte_cnt;
else if(r_en == 1'b0&&data_serial == 8'hFF)
byte_cnt <= 1'b1;
else
byte_cnt <= 1'b0;
//channel_cnt处理通道数计数
always@(negedge byte_cnt or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
channel_cnt <= 1'b0;
else if(channel_cnt > CHANNEL_NUM)
channel_cnt <= 1'b0;
else if(r_en == 1'b1&&channel_cnt <= CHANNEL_NUM)
channel_cnt <= channel_cnt+1;
else
channel_cnt <= 1'b0;
//串转并输出
always@(negedge in_flag or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
data_parallel <= 120'b0;
else if(r_en == 1'b1)
if(byte_cnt == 1'b0)
case(channel_cnt)
4'b0001:data_parallel[7 :0] <= data_serial[7:0];
4'b0010:data_parallel[19:12] <= data_serial[7:0];
4'b0011:data_parallel[31:24] <= data_serial[7:0];
4'b0100:data_parallel[43:36] <= data_serial[7:0];
4'b0101:data_parallel[55:48] <= data_serial[7:0];
4'b0110:data_parallel[67:60] <= data_serial[7:0];
4'b0111:data_parallel[79:72] <= data_serial[7:0];
4'b1000:data_parallel[91:84] <= data_serial[7:0];
4'b1001:data_parallel[103:96] <= data_serial[7:0];
4'b1010:data_parallel[115:108] <= data_serial[7:0];
default:data_parallel <= data_parallel;
endcase
else
case(channel_cnt)
4'b0001:data_parallel[11:7 +1] <= data_serial[3:0];
4'b0010:data_parallel[23:19 +1] <= data_serial[3:0];
4'b0011:data_parallel[35:31 +1] <= data_serial[3:0];
4'b0100:data_parallel[47:43 +1] <= data_serial[3:0];
4'b0101:data_parallel[58:55 +1] <= data_serial[3:0];
4'b0110:data_parallel[71:67 +1] <= data_serial[3:0];
4'b0111:data_parallel[83:79 +1] <= data_serial[3:0];
4'b1000:data_parallel[95:91 +1] <= data_serial[3:0];
4'b1001:data_parallel[107:103+1] <= data_serial[3:0];
4'b1010:data_parallel[119:115+1] <= data_serial[3:0];
default:data_parallel <= data_parallel;
endcase
else
data_parallel <= data_parallel;
//out_flag转换成功标志位
always@(posedge channel_cnt or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
out_flag <= 1'b0;
else if(channel_cnt == CHANNEL_NUM)
out_flag <= 1'b1;
else
out_flag <= 1'b0;
endmodule
波形图:
decode 模块检测到两个连续的 FF 后 r_en 使能开始记录数据,数据的高低字节用 byte_cnt 加以区分,每记录两个字节使 channel_cnt 加一,超出 CHANNEL_NUM 结束记录, data_parallel 输出120为并行数据。
仿真代码:
`timescale 1us / 1ns
module tb_decoder();
//********************************************************************//
//****************** Parameter and Internal Signal *******************//
//********************************************************************//
//wire define
wire [119:0] data_parallel ;
wire out_flag ;
// wire [3:0] channel_cnt ;
// wire byte_cnt ;
// wire r_en ;
reg [7:0] data_serial;
reg in_flag;
reg sys_rst_n;
//********************************************************************//
//***************************** Main Code ****************************//
//********************************************************************//
//初始化系统时钟、全局复位和输入信号
initial begin
in_flag = 1'b0;
sys_rst_n = 1'b0;
#100
sys_rst_n = 1'b1;
end
//调用任务rx_byte
initial begin
#200
rx_data();
end
//创建任务rx_byte,本次任务调用rx_bit任务,发送8次数据,分别为0~7
task rx_data(); //因为不需要外部传递参数,所以括号中没有输入
integer j;
for(j=0; j<255; j=j+1) //调用8次rx_bit任务,每次发送的值从0变化255
rx_serial();
endtask
//创建任务rx_bit,每次发送的数据有10位,data的值分别为0到7由j的值传递进来
task rx_serial();
integer i;
for(i=0; i<22; i=i+1) begin
case(i)
0: data_serial <= 8'hFF ;
1: data_serial <= 8'hFF ;
2: data_serial <= 8'd1 ;
3: data_serial <= 8'd0 ;
4: data_serial <= 8'd2 ;
5: data_serial <= 8'd0 ;
6: data_serial <= 8'd3 ;
7: data_serial <= 8'd0 ;
8: data_serial <= 8'd4 ;
9: data_serial <= 8'd0 ;
10: data_serial <= 8'd5 ;
11: data_serial <= 8'd0 ;
12: data_serial <= 8'd6 ;
13: data_serial <= 8'd0 ;
14: data_serial <= 8'd7 ;
15: data_serial <= 8'd0 ;
16: data_serial <= 8'd8 ;
17: data_serial <= 8'b0 ;
18: data_serial <= 8'd9 ;
19: data_serial <= 8'd0 ;
20: data_serial <= 8'd10 ;
21: data_serial <= 8'd0 ;
endcase
in_flag <= 1'b1;
#0.001;
in_flag <= 1'b0;
#10;
end
endtask
//********************************************************************//
//*************************** Instantiation **************************//
//********************************************************************//
//------------------------ rs232_inst ------------------------
decoder
#(
.CHANNEL_NUM (4'd10) //传感器通道数
)
decoder_inst
(
.sys_rst_n (sys_rst_n ),
.data_serial (data_serial ),
.in_flag (in_flag ),
.data_parallel (data_parallel),
.out_flag (out_flag )
// .channel_cnt (channel_cnt ),
// .byte_cnt (byte_cnt ),
// .r_en (r_en )
);
endmodule
<3> 顶层模块
代码解析:
`timescale 1ns / 1ps
module proc_fpga
(
input wire clk_in1_p ,
input wire clk_in1_n ,
input wire sys_rst_n ,
//发送数据线
output wire pc_tx , //数据发送线
// input wire [7:0] tx_data , //发送的一字节数据
// input wire tx_flag , //发送数据就位标志
//接收数据线
input wire pc_rx , //数据接收线
// output wire [7:0] rx_data , //接受的一字节数据
// output wire rx_flag , //一字节数据接收完成标志
input wire s1_rx ,
input wire s2_rx ,
output wire [15:0] result
);
wire clk_100M;
wire locked;
wire [7:0] sensor1_data ;
wire sensor1_flag ;
wire s2_rx ;
wire [7:0] sensor2_data ;
wire sensor2_flag ;
//wire s3_rx ,
//wire [7:0] sensor3_data ,
//wire sensor3_flag
wire [119:0] data1_parallel ;
wire out1_flag ;
wire [119:0] data2_parallel ;
wire out2_flag ;
//回环测试线
wire [7:0] pc_data ;
wire pc_flag ;
wire [7:0] result_low;
wire [11:0] b1 ;
wire [11:0] b2 ;
wire [11:0] b3 ;
wire [11:0] b4 ;
wire [11:0] b5 ;
wire [11:0] b6 ;
wire [11:0] b7 ;
wire [11:0] b8 ;
wire [11:0] b9 ;
wire [11:0] b10 ;
wire [11:0] b11 ;
wire [11:0] b12 ;
wire [11:0] b13 ;
wire [11:0] b14 ;
wire [11:0] b15 ;
wire [11:0] b16 ;
assign data1_parallel[11:0] = b1 ;
assign data1_parallel[23:12] = b2 ;
assign data1_parallel[35:24] = b3 ;
assign data1_parallel[47:36] = b4 ;
assign data1_parallel[59:48] = b5 ;
assign data1_parallel[71:60] = b6 ;
assign data1_parallel[83:72] = b7 ;
assign data1_parallel[95:84] = b8 ;
assign data1_parallel[107:96] = b9 ;
assign data1_parallel[119:108] = b10 ;
assign data2_parallel[11:0] = b11 ;
assign data2_parallel[23:12] = b12 ;
assign data2_parallel[35:24] = b13 ;
assign data2_parallel[47:36] = b14 ;
assign data2_parallel[59:48] = b15 ;
assign data2_parallel[71:60] = b16 ;
//pll时钟产生模块
clk_pll clk_pll_inst
(
// Clock out ports
.clk_100M(clk_100M), // output clk_100M
// Status and control signals
.reset(~sys_rst_n), // input reset
.locked(locked), // output locked
// Clock in ports
.clk_in1_p(clk_in1_p), // input clk_in1_p
.clk_in1_n(clk_in1_n) // input clk_in1_n
);
//usart通信模块
rs232 rs232_pc_inst
(
.sys_clk(clk_100M),
.sys_rst_n(sys_rst_n),
.rx_data (pc_data ), //output [7:0] rx_data
.rx_flag (pc_flag ), //output rx_flag
.tx_data (pc_data ),
.tx_flag (pc_flag ),
.rx(pc_rx),
.tx(pc_tx)
);
//传感器数据接收
uart_rx uart_rx_sensor1_inst
(
.sys_clk(clk_100M),
.sys_rst_n(sys_rst_n),
.po_data (sensor1_data ), //output [7:0] rx_data
.po_flag (sensor1_flag ), //output rx_flag
// .po_data (pc_data ), //回环测试
// .po_flag (pc_flag ), //回环测试
.rx(s1_rx)
);
uart_rx uart_rx_sensor2_inst
(
.sys_clk(clk_100M),
.sys_rst_n(sys_rst_n),
.po_data (sensor2_data ), //output [7:0] rx_data
.po_flag (sensor2_flag ), //output rx_flag`
.rx(s2_rx)
);
// uart_rx uart_rx_sensor3_inst
// (
// .sys_clk(clk_100M),
// .sys_rst_n(sys_rst_n),
// .po_data (sensor3_data ), //output [7:0] rx_data
// .po_flag (sensor3_flag ), //output rx_flag
// .rx(s3_rx)
// );
decoder decoder1_inst
(
.sys_rst_n (sys_rst_n) ,
.data_serial (sensor1_data) ,
.in_flag (sensor1_flag) ,
.data_parallel (data1_parallel) ,
.out_flag (out1_flag)
);
decoder decoder2_inst
(
.sys_rst_n (sys_rst_n) ,
.data_serial (sensor2_data) ,
.in_flag (sensor2_flag) ,
.data_parallel (data2_parallel) ,
.out_flag (out2_flag)
);
signal_proc_inst signal_proc_inst_inst
(
.ap_clk (clk_100M) ,
.ap_rst (sys_rst_n) ,
.a1 (b1 ) ,
.a2 (b2 ) ,
.a3 (b3 ) ,
.a4 (b4 ) ,
.a5 (b5 ) ,
.a6 (b6 ) ,
.a7 (b7 ) ,
.a8 (b8 ) ,
.a9 (b9 ) ,
.a10 (b10) ,
.a11 (b11) ,
.a12 (b12) ,
.a13 (b13) ,
.a14 (b14) ,
.a15 (b15) ,
.a16 (b16) ,
.c1 (result[0]) ,
.c2 (result[1]) ,
.c3 (result[2]) ,
.c4 (result[3]) ,
.c5 (result[4]) ,
.c6 (result[5]) ,
.c7 (result[6]) ,
.c8 (result[7]) ,
.c9 (result[8]) ,
.c10 (result[9]) ,
.c11 (result[10]) ,
.c12 (result[11]) ,
.c13 (result[12]) ,
.c14 (result[13]) ,
.c15 (result[14]) ,
.c16 (result[15])
);
endmodule
仿真代码:
`timescale 1ns / 1ps
module tb_proc_fpga();
//********************************************************************//
//****************** Parameter and Internal Signal *******************//
//********************************************************************//
//wire define
wire tx ;
reg rx ;
wire [7:0] rx_data;
wire rx_flag;//reg define
wire [7:0] tx_data;
wire tx_flag;
reg clk_in1_p;
reg clk_in1_n;
reg sys_rst_n;
always #5 clk_in1_p = ~clk_in1_p;
always #5 clk_in1_n = ~clk_in1_n;
assign tx_data=rx_data;
assign tx_flag=rx_flag;
parameter UART_BPS = 20’d115200 , //比特率
CLK_FREQ = 28’d100_000_000 ; //时钟频率
//********************************************************************//
//***************************** Main Code ****************************//
//********************************************************************//
//初始化系统时钟、全局复位和输入信号
initial begin
clk_in1_p = 1'b0;
clk_in1_n = 1'b1;
rx <= 1'b1;
sys_rst_n = 1'b0;
#100
sys_rst_n = 1'b1;
end
//调用任务rx_byte
initial begin
#200
rx_byte();
end
//创建任务rx_byte,本次任务调用rx_bit任务,发送8次数据,分别为0~7
task rx_byte(); //因为不需要外部传递参数,所以括号中没有输入
integer j;
for(j=0; j<255; j=j+1) //调用8次rx_bit任务,每次发送的值从0变化255
rx_bit(j);
endtask
//创建任务rx_bit,每次发送的数据有10位,data的值分别为0到7由j的值传递进来
task rx_bit(
input [7:0] data
);
integer i;
for(i=0; i<10; i=i+1) begin
case(i)
0: rx <= 1'b0;
1: rx <= data[0];
2: rx <= data[1];
3: rx <= data[2];
4: rx <= data[3];
5: rx <= data[4];
6: rx <= data[5];
7: rx <= data[6];
8: rx <= data[7];
9: rx <= 1'b1;
endcase
#(1000000000/UART_BPS); //每发送1位数据延时
end
endtask
//********************************************************************//
//*************************** Instantiation **************************//
//********************************************************************//
//------------------------ rs232_inst ------------------------
proc_fpga proc_fpga_inst
(
.clk_in1_p (clk_in1_p ),
.clk_in1_n (clk_in1_n ),
.sys_rst_n (sys_rst_n ),
// .rx_data (rx_data), //output [7:0] rx_data
// .rx_flag (rx_flag), //output rx_flag
// .tx_data (tx_data),
// .tx_flag (tx_flag),
.s1_rx (rx ),
.pc_tx (tx )
);
endmodule
3.signal_proc 信号处理模块
HLS工程代码解析:
#include <ap_cint.h>
#include <math.h>
void signal_proc(uint12 a1,uint12 a2,uint12 a3,uint12 a4,uint12 a5,uint12 a6,uint12 a7,uint12 a8,uint12 a9,uint12 a10,uint12 a11,uint12 a12,uint12 a13,uint12 a14,uint12 a15,uint12 a16,uint1 *c1,uint1 *c2,uint1 *c3,uint1 *c4,uint1 *c5,uint1 *c6,uint1 *c7,uint1 *c8,uint1 *c9,uint1 *c10,uint1 c11,uint1 c12,uint1 c13,uint1 c14,uint1 c15,uint1 c16)
{
#pragma HLS INTERFACE ap_none port=a1
#pragma HLS INTERFACE ap_none port=a2
#pragma HLS INTERFACE ap_none port=a3
#pragma HLS INTERFACE ap_none port=a4
#pragma HLS INTERFACE ap_none port=a5
#pragma HLS INTERFACE ap_none port=a6
#pragma HLS INTERFACE ap_none port=a7
#pragma HLS INTERFACE ap_none port=a8
#pragma HLS INTERFACE ap_none port=a9
#pragma HLS INTERFACE ap_none port=a10
#pragma HLS INTERFACE ap_none port=a11
#pragma HLS INTERFACE ap_none port=a12
#pragma HLS INTERFACE ap_none port=a13
#pragma HLS INTERFACE ap_none port=a14
#pragma HLS INTERFACE ap_none port=a15
#pragma HLS INTERFACE ap_none port=a16
#pragma HLS INTERFACE ap_none port=c1
#pragma HLS INTERFACE ap_none port=c2
#pragma HLS INTERFACE ap_none port=c3
#pragma HLS INTERFACE ap_none port=c4
#pragma HLS INTERFACE ap_none port=c5
#pragma HLS INTERFACE ap_none port=c6
#pragma HLS INTERFACE ap_none port=c7
#pragma HLS INTERFACE ap_none port=c8
#pragma HLS INTERFACE ap_none port=c9
#pragma HLS INTERFACE ap_none port=c10
#pragma HLS INTERFACE ap_none port=c11
#pragma HLS INTERFACE ap_none port=c12
#pragma HLS INTERFACE ap_none port=c13
#pragma HLS INTERFACE ap_none port=c14
#pragma HLS INTERFACE ap_none port=c15
#pragma HLS INTERFACE ap_none port=c16
#pragma HLS INTERFACE ap_ctrl_none port=return
uint5 i;
uint12 b1,b2,b3,b4,b5,b6,b7,b8,b9,b10,b11,b12,b13,b14,b15,b16;
uint2 time=0;
uint16 xzuo[16]={1,2,3,4,1,2,3,4,1,2,3,4,1,2,3,4};
uint16 yzuo[16]={1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4};
double A[256];
for(i=0;i<=15;i++)
for(int j=0;j<=15;j++)
{
A[i16+j]=sqrt((xzuo[i]-xzuo[j])(xzuo[i]-xzuo[j])+(yzuo[i]-yzuo[j])(yzuo[i]-yzuo[j]));
A[i16+j]=(1.0)/(A[i16+j]A[i16+j]A[i16+j]);
}
for(i=0;i<=15;i++)
{
A[17i]=0;
}
while(1)
{
if(time==0)
{
b1=a1;
b2=a2;
b3=a3;
b4=a4;
b5=a5;
b6=a6;
b7=a7;
b8=a8;
b9=a9;
b10=a10;
b11=a11;
b12=a12;
b13=a13;
b14=a14;
b15=a15;
b16=a16;
time++;
}
else
{
uint5 i,j;
double yuzhi=0.01;
uint12 graphsig[16];
uint12 graphsigq[16];
double Bian,jiubian,xinbian;
/* 此处假设该图信号的邻接矩阵不变,所以前面的只算一次 */
graphsig[0] = a1;
graphsig[1] = a2;
graphsig[2] = a3;
graphsig[3] = a4;
graphsig[4] = a5;
graphsig[5] = a6;
graphsig[6] = a7;
graphsig[7] = a8;
graphsig[8] = a9;
graphsig[9] = a10;
graphsig[10] = a11;
graphsig[11] = a12;
graphsig[12] = a13;
graphsig[13] = a14;
graphsig[14] = a15;
graphsig[15] = a16;
/* 现在时刻图信号 */
graphsigq[0] = b1;
graphsigq[1] = b2;
graphsigq[2] = b3;
graphsigq[3] = b4;
graphsigq[4] = b5;
graphsigq[5] = b6;
graphsigq[6] = b7;
graphsigq[7] = b8;
graphsigq[8] = b9;
graphsigq[9] = b10;
graphsigq[10] = b11;
graphsigq[11] = b12;
graphsigq[12] = b13;
graphsigq[13] = b14;
graphsigq[14] = b15;
graphsigq[15] = b16;
double dianbianhe[16];
for(i=0;i<=15;i++)
{
Bian=0;
for(j=0;j<=15;j++)
{
jiubian=((graphsigq[i]-graphsigq[j])*(graphsigq[i]-graphsigq[j]));
xinbian=((graphsig[i]-graphsig[j])*(graphsig[i]-graphsig[j]));
Bian=Bian+(xinbian-jiubian)*(xinbian-jiubian)*A[i*16+j];
}
dianbianhe[i]=Bian;
}
for(i=0;i<=15;i++)
{
if(dianbianhe[i]>=yuzhi)
{
if(i==0) *c1=1;
else if(i==1) *c2=1;
else if(i==2) *c3=1;
else if(i==3) *c4=1;
else if(i==4) *c5=1;
else if(i==5) *c6=1;
else if(i==6) *c7=1;
else if(i==7) *c8=1;
else if(i==8) *c9=1;
else if(i==9) *c10=1;
else if(i==10) *c11=1;
else if(i==11) *c12=1;
else if(i==12) *c13=1;
else if(i==13) *c14=1;
else if(i==14) *c15=1;
else if(i==15) *c16=1;
}
}
b1=a1;
b2=a2;
b3=a3;
b4=a4;
b5=a5;
b6=a6;
b7=a7;
b8=a8;
b9=a9;
b10=a10;
b11=a11;
b12=a12;
b13=a13;
b14=a14;
b15=a15;
b16=a16;
}
}
}
综合后 IP 核 :
四.注意事项
<1>实例化时注意各个模块的时序,检查代码使用的时钟频率及各参数是否正确;实例化时连接线的运用,不能重复对一变量赋值!;注意实例调用时名称统一。
<2>编写好仿真文件进行仿真后再下载。
<3>报错:[DRC MDRV-1] Multiple Driver Nets
[Vivado综合报multi-driven
nets的错误的解决方法](https://blog.csdn.net/wordwarwordwar/article/details/80428358?ops_request_misc=&request_id=&biz_id=102&utm_term=multiple%20driver%20nets&utm_medium=distribute.pc_search_result.none-
task-blog-2allsobaiduweb~default-0-80428358.nonecase&spm=1018.2226.3001.4187
“Vivado综合报multi-driven nets的错误的解决方法”)
[Vivado编译过程中出现[DRC MDRV-1] Multiple Driver
Nets](https://blog.csdn.net/jk_101/article/details/131824877?ops_request_misc=&request_id=&biz_id=102&utm_term=multiple%20driver%20nets&utm_medium=distribute.pc_search_result.none-
task-
blog-2allsobaiduweb~default-1-131824877.nonecase&spm=1018.2226.3001.4187
“Vivado编译过程中出现[DRC MDRV-1] Multiple Driver Nets”)
<4>未使用的输入输出不要定义,定义后生成比特流前必须绑定引脚
<5>按照官方推荐的配套工具软件,比如Vivado 2023.1对应Vitis HLS
2023.1,如果使用不配套版本,HLS导出的IP核Vivado可能无法完全识别,报错“missing
Source”(全部展开IP核显示有缺少模块说明,如下图:)
本文转自 https://blog.csdn.net/qq_32971095/article/details/133853116,如有侵权,请联系删除。