【ZYNQ-7000开发之十一】VGA RLT代码封装成AXI Stream

来源:互联网 发布:js拉链是哪个国家的 编辑:程序博客网 时间:2024/05/21 15:01

本编文章将对VGA的RTL代码,封装成AXI Stream,并且在vivado 里用TPG进行测试

本篇文章的VGA RTL代码在【ZYNQ-7000开发之一】基础上修改,封装好的VGA Stream可以方便我们实现视频图像处理

TGP 等的规范说明可以到官网下载最新版本

本文所使用的开发板是Miz702(兼容zedboard)
PC 开发环境版本:Vivado 2015.2 Xilinx SDK 2015.2
其它:VGA显示器

AXI Stream原理

首先这里列出axi stream的信号,红框里的是要用到的
这里写图片描述
核心的信号是,TVALID,TREADY,TLAST,TUSER

TVALID和TREADY握手信号

这里写图片描述
在TVALID和TREADY同时有效的时候,数据才有效。对于TPG来说,大部分时间TVALID是有效的,TREADY由我们自己控制。
TUSER(SOF,Start Of Frame),代表每一帧的开始。TLAST(EOL,End Of Line),代表每一行的结束。
这里给出TPG的时序图,比较简洁,要理解之后才好把RTL封装成AXI Stream
这里写图片描述
这里写图片描述

封装AXI Stream

打开vivado,建立一个工程(选择zed)

选择Tools->Create and Package IP

这里写图片描述

点击NEXT,选择Create AXI4,如图所示

这里写图片描述

输入好name和路径后,点击NEXT

这里写图片描述

按照如下配置

这里写图片描述

点击NEXT,选择Edit IP,然后点击Finish

这时会弹出一个新的IP 编辑界面,这个可以看到VIVADO已经自动生成了一些必要的AXI Stream相关的代码,我们在这个基础上修改很方便

把VGA_AXI_Stream_v1_0.v文件里的代码,修改如下

`timescale 1 ns / 1 ps    module myip_v1_0 #    (        // Users to add parameters here        // User parameters ends        // Do not modify the parameters beyond this line        // Parameters of Axi Slave Bus Interface S00_AXIS_VGA        parameter integer C_S00_AXIS_VGA_TDATA_WIDTH    = 32    )    (        // Users to add ports here        input   wire            clk_25mhz,        output  wire            hsync,        output  wire            vsync,        output  wire   [11:0]   rgb,        output  reg             led,        // User ports ends        // Do not modify the ports beyond this line        // Ports of Axi Slave Bus Interface S00_AXIS_VGA        input wire  s00_axis_vga_aclk,        input wire  s00_axis_vga_aresetn,        output wire  s00_axis_vga_tready,        input wire [C_S00_AXIS_VGA_TDATA_WIDTH-1 : 0] s00_axis_vga_tdata,        input wire [(C_S00_AXIS_VGA_TDATA_WIDTH/8)-1 : 0] s00_axis_vga_tstrb,        input wire  s00_axis_vga_tlast,        input wire  s00_axis_vga_tvalid,        input wire  s00_axis_vga_tuser    );// Instantiation of Axi Bus Interface S00_AXIS_VGA    myip_v1_0_S00_AXIS_VGA # (         .C_S_AXIS_TDATA_WIDTH(C_S00_AXIS_VGA_TDATA_WIDTH)    ) myip_v1_0_S00_AXIS_VGA_inst (        .S_AXIS_ACLK(s00_axis_vga_aclk),        .S_AXIS_ARESETN(s00_axis_vga_aresetn),        .S_AXIS_TREADY(s00_axis_vga_tready),        .S_AXIS_TDATA(s00_axis_vga_tdata),        .S_AXIS_TSTRB(s00_axis_vga_tstrb),        .S_AXIS_TLAST(s00_axis_vga_tlast),        .S_AXIS_TVALID(s00_axis_vga_tvalid),        .S_AXIS_TUSER(s00_axis_vga_tuser),        .clk            (clk_25mhz),        .rst_n          (s00_axis_vga_aresetn),        .video_en       (video_en),        .hsync          (hsync),        .vsync          (vsync),        .pixel_x        (pixel_x),        .pixel_y        (pixel_y)    );    // Add user logic here    wire    [9:0]   pixel_x;    wire    [9:0]   pixel_y;    wire            clk_25mhz;    reg     [11:0]  rgb_reg;    //显示静态图像640*480    reg        [23:0] cnt;    always @(posedge clk_25mhz or negedge s00_axis_vga_aresetn)        if(!s00_axis_vga_aresetn)            begin                cnt <= 0;                led <= 0;            end         else            begin                cnt <= cnt + 1'b1;                if(cnt == 24'd12500000)                    begin                         cnt <= 24'b0;                        led <= ~led;                    end             end     always @ (posedge clk_25mhz or negedge s00_axis_vga_aresetn)        if(!s00_axis_vga_aresetn)            begin                rgb_reg <= 12'b0;            end         else if(s00_axis_vga_tvalid == 1'b1 && s00_axis_vga_tready == 1'b1)            begin                //显示图像                         rgb_reg[3:0] <= s00_axis_vga_tdata[7:4];                rgb_reg[7:4] <= s00_axis_vga_tdata[15:12];                rgb_reg[11:8] <= s00_axis_vga_tdata[23:20];                end           /*             always @ (posedge clk_25mhz or negedge s00_axis_vga_aresetn)        if(!s00_axis_vga_aresetn)            begin                address_sig <= 19'b0;            end         else            begin                                if(pixel_x>=0 && pixel_x<= 639 && pixel_y>=0 && pixel_y<=479)                    address_sig = (pixel_x + 640*pixel_y);            end    */    //////////////////////////////////////////////////////////////            assign rgb = (video_en == 1'b1) ? rgb_reg:12'b0;              // User logic ends    endmodule

把VGA_AXI_Stream_v1_0_S00_AXI_VgA.v文件里的代码,修改如下

// Users to add ports here        input   wire            clk,        input   wire            rst_n,        output  wire            video_en,        output  reg             hsync,        output  reg             vsync,        output  wire    [9:0]   pixel_x,        output  wire    [9:0]   pixel_y,          // User ports ends        // Do not modify the ports beyond this line        // AXI4Stream sink: Clock        input wire  S_AXIS_ACLK,        // AXI4Stream sink: Reset        input wire  S_AXIS_ARESETN,        // Ready to accept data in        output wire  S_AXIS_TREADY,        // Data in        input wire [C_S_AXIS_TDATA_WIDTH-1 : 0] S_AXIS_TDATA,        // Byte qualifier        input wire [(C_S_AXIS_TDATA_WIDTH/8)-1 : 0] S_AXIS_TSTRB,        // Indicates boundary of last packet        input wire  S_AXIS_TLAST,        // Data is in valid        input wire  S_AXIS_TVALID,        input wire S_AXIS_TUSER    );    // function called clogb2 that returns an integer which has the     // value of the ceiling of the log base 2.    function integer clogb2 (input integer bit_depth);      begin        for(clogb2=0; bit_depth>0; clogb2=clogb2+1)          bit_depth = bit_depth >> 1;      end    endfunction    // Total number of input data.    localparam NUMBER_OF_INPUT_WORDS  = 8;    // bit_num gives the minimum number of bits needed to address 'NUMBER_OF_INPUT_WORDS' size of FIFO.    localparam bit_num  = clogb2(NUMBER_OF_INPUT_WORDS-1);    // Define the states of state machine    // The control state machine oversees the writing of input streaming data to the FIFO,    // and outputs the streaming data from the FIFO    parameter [1:0] IDLE = 1'b0,        // This is the initial/idle state                     WRITE_FIFO  = 1'b1; // In this state FIFO is written with the                                        // input stream data S_AXIS_TDATA     wire    axis_tready;    // State variable    reg mst_exec_state;      // FIFO implementation signals    genvar byte_index;         // FIFO write enable    wire fifo_wren;    // FIFO full flag    reg fifo_full_flag;    // FIFO write pointer    reg [bit_num-1:0] write_pointer;    // sink has accepted all the streaming data and stored in FIFO      reg writes_done;    // I/O Connections assignments    assign S_AXIS_TREADY    = axis_tready;    // Control state machine implementation    always @(posedge S_AXIS_ACLK)     begin        if (!S_AXIS_ARESETN)       // Synchronous reset (active low)        begin          mst_exec_state <= IDLE;        end        else        case (mst_exec_state)          IDLE:             // The sink starts accepting tdata when             // there tvalid is asserted to mark the            // presence of valid streaming data               if (S_AXIS_TVALID)                begin                  mst_exec_state <= WRITE_FIFO;                end              else                begin                  mst_exec_state <= IDLE;                end          WRITE_FIFO:             // When the sink has accepted all the streaming input data,            // the interface swiches functionality to a streaming master            if (writes_done)              begin                mst_exec_state <= IDLE;              end            else              begin                // The sink accepts and stores tdata                 // into FIFO                mst_exec_state <= WRITE_FIFO;              end        endcase    end    // AXI Streaming Sink     //     // The example design sink is always ready to accept the S_AXIS_TDATA  until    // the FIFO is not filled with NUMBER_OF_INPUT_WORDS number of input words.    //assign axis_tready = ((mst_exec_state == WRITE_FIFO) && (write_pointer <= NUMBER_OF_INPUT_WORDS-1)    assign axis_tready =( (pixel_x>=0 && pixel_x<= 639 && pixel_y>=0 && pixel_y<=479) );    always@(posedge S_AXIS_ACLK)    begin      if(!S_AXIS_ARESETN)        begin          write_pointer <= 0;          writes_done <= 1'b0;        end        else        if (write_pointer <= NUMBER_OF_INPUT_WORDS-1)          begin            if (fifo_wren)              begin                // write pointer is incremented after every write to the FIFO                // when FIFO write signal is enabled.                write_pointer <= write_pointer + 1;                writes_done <= 1'b0;              end              if ((write_pointer == NUMBER_OF_INPUT_WORDS-1)|| S_AXIS_TLAST)                begin                  // reads_done is asserted when NUMBER_OF_INPUT_WORDS numbers of streaming data                   // has been written to the FIFO which is also marked by S_AXIS_TLAST(kept for optional usage).                  writes_done <= 1'b1;                end          end      end    // FIFO write enable generation    assign fifo_wren = S_AXIS_TVALID && axis_tready;    // FIFO Implementation    generate       for(byte_index=0; byte_index<= (C_S_AXIS_TDATA_WIDTH/8-1); byte_index=byte_index+1)      begin:FIFO_GEN        reg  [(C_S_AXIS_TDATA_WIDTH/4)-1:0] stream_data_fifo [0 : NUMBER_OF_INPUT_WORDS-1];        // Streaming input data is stored in FIFO        always @( posedge S_AXIS_ACLK )        begin          if (fifo_wren)// && S_AXIS_TSTRB[byte_index])            begin              stream_data_fifo[write_pointer] <= S_AXIS_TDATA[(byte_index*8+7) -: 8];            end          end        end           endgenerate    // Add user logic here   reg     [9:0] pixel_cnt;   reg     [9:0] line_cnt;   reg             v_video_en;   reg             h_video_en;   always @(posedge clk or negedge rst_n)       if(!rst_n)           begin               pixel_cnt <= 10'b0;           end       else           begin               pixel_cnt <= pixel_cnt + 1'b1;                     if(pixel_cnt == 10'd799 || S_AXIS_TUSER == 1'b1)                     begin                            pixel_cnt <= 10'b0;                     end           end    always @(posedge clk or negedge rst_n)       if(!rst_n)           begin                h_video_en <= 1'b1;                       hsync <= 1'b1;           end       else           begin               case (pixel_cnt)                    10'd0:                       begin                           h_video_en <= 1'b1;                       end                   10'd639:                       begin                           h_video_en <= 1'b0;                       end                    10'd655:                       begin                           hsync <= 1'b0;                       end                    10'd751:                       begin                           hsync <= 1'b1;                       end                            endcase           end    always @(posedge clk or negedge rst_n)       if(!rst_n)           begin               line_cnt <= 10'b0;           end       else             begin               if(pixel_cnt <= S_AXIS_TLAST)    //pixel_cnt == 10'd799                   begin                       line_cnt <= line_cnt + 1'b1;                   end                  if(line_cnt == 10'd524)                 begin                       line_cnt <= 10'b0;                 end                    if(S_AXIS_TUSER == 1'b1)                 begin                     line_cnt <= 10'b0;                                             end           end   always @(posedge clk or negedge rst_n)       if(!rst_n)           begin               v_video_en <= 1'b1;               vsync <= 1'b1;           end       else           begin               case(line_cnt)                   10'd0:                       begin                           v_video_en <= 1'b1;                       end                    10'd479:                       begin                           v_video_en <= 1'b0;                       end                    10'd489:                       begin                           vsync <= 1'b0;                       end                    10'd491:                       begin                           vsync <= 1'b1;                       end                endcase           end                  assign pixel_x = pixel_cnt;   assign pixel_y = line_cnt;   assign video_en = ((h_video_en == 1'b1) &&  (v_video_en == 1'b1));     // User logic ends    endmodule

保存后,按照如图所示操作

这里写图片描述
这里写图片描述
其它的类似,最后在Review and Package,里选择repackage

建立硬件工程

首先要把IP的路径添加进来

在vivado里新建一个Block Design,按照如图所示建立硬件工程,FCLK_CLK0设置成25MHz

这里写图片描述

TPG这样配置

这里写图片描述

约束文件如下

set_property PACKAGE_PIN T22 [get_ports led]set_property IOSTANDARD LVCMOS33 [get_ports led]set_property PACKAGE_PIN AA19 [get_ports hsync]set_property IOSTANDARD LVCMOS33 [get_ports hsync]set_property PACKAGE_PIN Y19 [get_ports vsync]set_property IOSTANDARD LVCMOS33 [get_ports vsync]set_property PACKAGE_PIN Y21 [get_ports {rgb[0]}]set_property IOSTANDARD LVCMOS33 [get_ports {rgb[0]}]set_property PACKAGE_PIN Y20 [get_ports {rgb[1]}]set_property IOSTANDARD LVCMOS33 [get_ports {rgb[1]}]set_property PACKAGE_PIN AB20 [get_ports {rgb[2]}]set_property IOSTANDARD LVCMOS33 [get_ports {rgb[2]}]set_property PACKAGE_PIN AB19 [get_ports {rgb[3]}]set_property IOSTANDARD LVCMOS33 [get_ports {rgb[3]}]set_property PACKAGE_PIN AB22 [get_ports {rgb[4]}]set_property IOSTANDARD LVCMOS33 [get_ports {rgb[4]}]set_property PACKAGE_PIN AA22 [get_ports {rgb[5]}]set_property IOSTANDARD LVCMOS33 [get_ports {rgb[5]}]set_property PACKAGE_PIN AB21 [get_ports {rgb[6]}]set_property IOSTANDARD LVCMOS33 [get_ports {rgb[6]}]set_property PACKAGE_PIN AA21 [get_ports {rgb[7]}]set_property IOSTANDARD LVCMOS33 [get_ports {rgb[7]}]set_property PACKAGE_PIN V20 [get_ports {rgb[8]}]set_property IOSTANDARD LVCMOS33 [get_ports {rgb[8]}]set_property PACKAGE_PIN U20 [get_ports {rgb[9]}]set_property IOSTANDARD LVCMOS33 [get_ports {rgb[9]}]set_property PACKAGE_PIN V19 [get_ports {rgb[10]}]set_property IOSTANDARD LVCMOS33 [get_ports {rgb[10]}]set_property PACKAGE_PIN V18 [get_ports {rgb[11]}]set_property IOSTANDARD LVCMOS33 [get_ports {rgb[11]}]

编译后,导出硬件,新建一个Hello工程(主要是为PL提供25M时钟)

开发板上电测试,效果如下(color bar效果)

这里写图片描述

0 0
原创粉丝点击