2023年FPGA创新大赛记录

目录

一.基本信息

二.设计记录

1.任务分解

2.模块设计

三.设计实践

1.adc_stm32 信号采集模块

2.proc_fpga FPGA主体模块

<1>uart协议数据接收模块——uart_rx

<2>串行数据解码模块——decoder

<3> 顶层模块

3.signal_proc 信号处理模块

四.注意事项


一.基本信息

参赛厂商:AMD

参赛平台:基于AMD的FPGA/Zynq/Versal器件(无资源限制)

开发方向:基于AMD板卡的综合类赛道

开发平台:正点原子 DFZU2EG MPSoc 开发板

平台资源:

Application Processing UnitQuad-core Arm® Cortex®-A53 MPCore™ up to 1.5GHz
Real-Time Processing UnitDual-core Arm Cortex-R5F MPCore™ up to 600MHz
Graphics Processing UnitArm Mali™-400 MP2 up to 667MHz
Dynamic Memory InterfaceDDR4, LPDDR4, DDR3, DDR3L, LPDDR3
High-Speed PeripheralsPCIe® 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[i*16+j]=sqrt((xzuo[i]-xzuo[j])*(xzuo[i]-xzuo[j])+(yzuo[i]-yzuo[j])*(yzuo[i]-yzuo[j]));
	    	A[i*16+j]=(1.0)/(A[i*16+j]*A[i*16+j]*A[i*16+j]);
		}
    for(i=0;i<=15;i++)
    {
    	A[17*i]=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的错误的解决方法

Vivado编译过程中出现[DRC MDRV-1] Multiple Driver Nets

<4>未使用的输入输出不要定义,定义后生成比特流前必须绑定引脚

<5>按照官方推荐的配套工具软件,比如Vivado 2023.1对应Vitis HLS 2023.1,如果使用不配套版本,HLS导出的IP核Vivado可能无法完全识别,报错“missing Source”(全部展开IP核显示有缺少模块说明,如下图:)

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

switch_swq

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值