HLS:跑馬燈實驗


跑馬燈實驗的第一部分記錄:

1. vivado 2018.2的HLS在跑C/RTL co-simulation的時候,一直報錯,不論是用modelsim 還是vivado自帶的similator。使用vivado 2015.4的HLS沒有問題。

2. modelsim 我用的是10.1c版本,vivado 2018.2對modelsim支持至少是10.5以上。

3. 在vivado hls跑co-simulation未結束的情況下,打開modelsim會報錯。等協同仿真跑完,再用modelsim打開波形文件。

4. Vivado 2015.4的HLS做的IP核,在VIvado 2018.2中是可以使用的。

打開Vivado HLS,新建一個工程。

  工程位置和名稱自定義,一直點下一步,中間添加到文件暫時不用添加,直到出現下面一步。在part selection中選好芯片型號,時鍾周期 Clock Period 按照默認 10ns,Uncertaintly 和 Solution Name 均按照默認設置,然后點擊 finish。 

  一個建立好的工程如下圖所示。

   在工程左側添加如下空文件。

 

 代碼:

main.c

#include "shift_led.h"
#include <stdio.h>

using namespace std;

int main()
{
    led_t led_o;
    led_t led_i = 0xFE;//1111_1110
    const int SHIFT_TIME = 8;
    int i;
    for(i = 0;i < SHIFT_TIME;i++)
    {
        shift_led(&led_o,led_i);
        led_i = led_o;
        char string[25];
        itoa((unsigned int)led_o&0xFF,string,2);//&oxFF是為了取led_o的8位,轉化為二進制數出
        if(i == 6)
            fprintf(stdout,"shift_out= 0%s\n",string);//數據對齊,高位補零
        else
            fprintf(stdout,"shift_out= %s\n",string);
    }
}
#ifndef _SHIFT_LED_H_
#define _SHIFT_LED_H_

#include "ap_int.h"

#define MAX_CNT 100000000/2
#define SHIFT_FLAG  MAX_CNT-2

typedef ap_fixed<4,4> led_t; 
typedef ap_fixed<32,32> cnt32_t;

void shift_led(led_t *led_o,led_t led_i);

#endif

shift_led.cpp

#include "shift_led.h"

void shift_led(led_t *led_o,led_t led_i)
{
    #pragma HLS INTERFACE ap_ovld port=led_o
    #pragma HLS INTERFACE ap_ovld port=led_o
    #pragma HLS INTERFACE ap_vld port=led_i

    led_t tmp_led;
    cnt32_t i;
    tmp_led = led_i;
    for(i = 0;i < MAX_CNT;i++)
    {
        if(i==SHIFT_FLAG)
        {
            tmp_led = ((tmp_led>>7)&0x01) + ((tmp_led<<1)&0xFE);
            *led_o = tmp_led;
        }
    }
}

 代碼綜合步驟:

步驟一:點擊 Project -> Project Settings, 在 Synthesis 界面下選擇綜合的頂層函數名。 單擊 Browse 指定工程的頂層文件, 最后單擊 OK 完成修改。

步驟二:因為當前工程中只存在一個 Solution(解決方案) , 我們右鍵選擇 Solution –> Run C Synthesis–>Active Solutions 或者直接點擊 綠色三角進行綜合, 等待一段時間, 在經過優化的情況下綜合報告如圖所示(未經優化就是沒有加任何#pragma的), 我們可以看到 FF 和 LUT 分別使用了 37 和 140。 

步驟三:單擊solution->Open Analysis Perspective打開分析報告

  在 shift_led.h 文件中我們包含一個設置 int 自定義位寬的頭文件"ap_int.h", 我們使用ap_fixed()函數自定義 int 型的 bit 數, 其函數原型為:
ap_int_sim.h中class ap_fixed: public ap_fixed_base<_AP_W, _AP_I, true, _AP_Q, _AP_O, _AP_N> 。

  ap_fixed<M,N>,第一個 M 代表數據總位寬, N 代表數據整數部分的位寬, 那么小數部分的位寬即 M – N; 頭文件中的第6和7行代碼體現了ap_fixed的用法!
步驟四:優化端口

  現在把所有的#pragma都刪除掉,可以看到右側的Derective是沒有指令的,只顯示了一些端口信息。

右鍵led_o,插入directive。

  因為 led_o 是接口, 所以 Directive 我們選擇為 INTERFACE,Destination 選擇為 Source File。Source File 是針對所有的 Solution 采用同一個優化手段, 而 Directive File 是對當前的 Solution 有效, mode(optional)我們選為 ap_ovld,即輸出使能。 對 led_i 進行同樣的約束, 並選擇輸入使能,ap_vld。 我們再次綜合,就可得到前面步驟二的經過優化后的報告了。
仿真實現步驟:

步驟一:單擊 Project 下的 Run C Simulation  

步驟二:單擊 Solution 下的 Run C/RTL cosimulation 運行協同仿真。

步驟三:使用Modelsim打開sim->verilog->wave.wlf文件,添加interface信號。

打包HLS代碼成IP核步驟:

步驟一:單擊 Solution 菜單下的 Export RTL 或直接單擊 那個“田”的按鈕導出 RTL 級。

  這個壓縮包就是我們在后面Vivado中建立工程要用的。

  建立Vivado工程,添加頂層文件和約束文件。

module shift_led
  #(
    parameter  DATA_WIDTH  = 4
    )
   (
    input                        i_clk,
    input                        i_rst_n,
    output  reg [DATA_WIDTH-1:0] led
    );

reg             [1:0]  cnt      ;
reg  [DATA_WIDTH-1:0]  led_i_V  ;
wire                   ap_start ;
wire                   led_i_vld;
wire [DATA_WIDTH-1:0]  led_o_V  ;

always@(posedge i_clk or negedge i_rst_n)begin
    if(i_rst_n == 1'b0)
        cnt <= 2'd0;
    else if(cnt[1]==1'b0)
        cnt <= cnt + 1'b1;
end
        
always@(posedge i_clk or negedge i_rst_n)begin
    if(i_rst_n == 1'b0)
        led_i_V <= 2'd0;
    else if(cnt[0]==1'b1)
        led_i_V <= 4'h1;
    else if(led_o_vld == 1'b1)
        led_i_V <= led_o_V;
end

always@(posedge i_clk or negedge i_rst_n)begin
    if(i_rst_n == 1'b0)
        led <= 1'b0;
    else if(led_o_vld == 1'b1)
        led <= led_o_V;
end
        
assign ap_start  = cnt[1];
assign led_i_vld = cnt[1];

shift_led_0 u_shift_led_0(
                          .led_o_V_ap_vld  (led_o_vld),// output wire led_o_vld 
                          .led_i_V_ap_vld  (led_i_vld),// input wire led_i_vld  
                          .ap_clk          (i_clk    ),// input wire ap_clk          
                          .ap_rst          (~i_rst_n ),// input wire ap_rst          
                          .ap_start        (ap_start ),// input wire ap_start        
                          .ap_done         (         ),// output wire ap_done        
                          .ap_idle         (         ),// output wire ap_idle        
                          .ap_ready        (         ),// output wire ap_ready       
                          .led_i_V         (led_i_V  ),// output wire [7 : 0] led_o_V
                          .led_o_V         (led_o_V  ) // input wire [7 : 0] led_i_V 
                          );

endmodule

開發板現象:

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM