The use of ICAP primitives in FPGA -- the implementation of Multiboot function

Use of ICAP primitives

First, gossip

I haven't blogged for a while, because I went home from school. Now is the prevalence of pneumonia, not to add trouble to the community, their own adjustment procedures at home to see the paper. However, the verification of the icap primitives written today on the board failed, because the learning is that the icap primitives are used on the S6 chip, but because I didn't bring the development board of S6 home, I used 7 series of icape2 primitives to do the experiment here. Although the verification on the board failed, it is still not commonly used. Finally, in this unstable day, I hope that Wuhan refueling, China refueling, together to pass the difficulty!!!

Introduction of ICAP primitives

ICAP primitive is a primitive on S6 chip. It is necessary to explain the concept of primitive here. We can think of the primitive as an IP core, but the IP core is a graphical interface, and the primitive is equivalent to generating. v files generated by the IP core. The use of primitive does not need to add corresponding files. For ISE software, the location of primitive call is as follows:

The call location of the corresponding ICAP primitive is as follows:


Among them, the content of icap primitive is as follows:

// ICAP_SPARTAN6 : In order to incorporate this function into the design,
//    Verilog    : the following instance declaration needs to be placed
//   instance    : in the body of the design code.  The instance name
//  declaration  : (ICAP_SPARTAN6_inst) and/or the port declarations within the
//     code      : parenthesis may be changed to properly reference and
//               : connect this function to the design.  All inputs
//               : and outputs must be connected.

//  <-----Cut code below this line---->

   // ICAP_SPARTAN6: Internal Configuration Access Port
   //                Spartan-6
   // Xilinx HDL Language Template, version 14.7

   ICAP_SPARTAN6 #(
      .DEVICE_ID(0'h4000093),     // Specifies the pre-programmed Device ID value
      .SIM_CFG_FILE_NAME("NONE")  // Specifies the Raw Bitstream (RBT) file to be parsed by the simulation
                                  // model
   )
   ICAP_SPARTAN6_inst (
      .BUSY(BUSY),   // 1-bit output: Busy/Ready output
      .O(O),         // 16-bit output: Configuartion data output bus
      .CE(CE),       // 1-bit input: Active-Low ICAP Enable input
      .CLK(CLK),     // 1-bit input: Clock input
      .I(I),         // 16-bit input: Configuration data input bus
      .WRITE(WRITE)  // 1-bit input: Read/Write control input
   );

   // End of ICAP_SPARTAN6_inst instantiation

Here is an introduction to the use of several signals scored in the primitive:
1. Device ID: the device ID of different chips is different. When using this primitive, it is necessary to find the ID of the chip to be used, and the specific data manual UG380 to be found;
2. Sim? CFG? File? Name: for simulation, it is OK by default.
3. BUSY: BUSY signal corresponding to primitive
4. O: output of configuration data
5. CE: enable signal of primitive, effective at low level
6. CLK: clock signal of primitive
7. I: input signal of primitive configuration data
8. WRITE: enable signal of read-WRITE primitive, effective at low level

Here, you need to fill in the corresponding ID number in the device? ID
Then according to the above requirements, the primitive has to input the corresponding instructions from I before the FPGA can start from the specified storage address.

Input the above data into the ICAP primitive, FPGA can read the code from the storage address specified by the memory device. Note that the data in I and the data in the table above should be inverted by bytes. This part can also be found in the manual, as follows:

Here we need to focus on the meaning of Opcode, as shown in the following figure:

The physical meaning of the Opcode is to read the command code with flash, and the corresponding mg light is generally 0x03. The meaning of the rest of the configuration data can be seen from the diagram. With the above information, we can operate the ICAP primitive of S6 series.

Introduction of ICAPE2 primitive

Since there is no development board with S6 at home, we will then introduce the use of ICAP primitives in the A7 development board. Through S6, we know the above information as follows:
For vivado software, the location of primitive call is as follows:

The corresponding call location of ICAP primitive is as follows:
Among them, the content of icap primitive is as follows:

//   ICAPE2    : In order to incorporate this function into the design,
//   Verilog   : the following instance declaration needs to be placed
//  instance   : in the body of the design code.  The instance name
// declaration : (ICAPE2_inst) and/or the port declarations within the
//    code     : parenthesis may be changed to properly reference and
//             : connect this function to the design.  All inputs
//             : and outputs must be connected.

//  <-----Cut code below this line---->

   // ICAPE2: Internal Configuration Access Port
   //         Artix-7
   // Xilinx HDL Language Template, version 2019.1

   ICAPE2 #(
      .DEVICE_ID(0'h3651093),     // Specifies the pre-programmed Device ID value to be used for simulation
                                  // purposes.
      .ICAP_WIDTH("X32"),         // Specifies the input and output data width.
      .SIM_CFG_FILE_NAME("NONE")  // Specifies the Raw Bitstream (RBT) file to be parsed by the simulation
                                  // model.
   )
   ICAPE2_inst (
      .O(O),         // 32-bit output: Configuration data output bus
      .CLK(CLK),     // 1-bit input: Clock Input
      .CSIB(CSIB),   // 1-bit input: Active-Low ICAP Enable
      .I(I),         // 32-bit input: Configuration data input bus
      .RDWRB(RDWRB)  // 1-bit input: Read/Write Select input
   );

   // End of ICAPE2_inst instantiation
				
				



Code of ICAPE2 primitive

Code for project 1:
Code of top module

`timescale 1ns / 1ps
// *********************************************************************************
// Project Name : OSXXXX
// Author       : zhangningning
// Email        : nnzhang1996@foxmail.com
// Website      : 
// Module Name  : top.v
// Create Time  : 2020-01-29 13:45:19
// Editor       : sublime text3, tab size (4)
// CopyRight(c) : All Rights Reserved
//
// *********************************************************************************
// Modification History:
// Date             By              Version                 Change Description
// -----------------------------------------------------------------------
// XXXX       zhangningning          1.0                        Original
//  
// *********************************************************************************


module top(
    input                   sclk            ,
    input                   rst_n           ,
    input                   key_i           ,
    output  wire    [ 3:0]  led                           
);
 
//========================================================================================\
//**************Define Parameter and  Internal Signals**********************************
//========================================================================================/
wire                        key_flag        ;
 
//========================================================================================\
//**************     Main      Code        **********************************
//========================================================================================/

led led_inst(
    .sclk                   (sclk                   ),
    .rst_n                  (rst_n                  ),
    .led                    (led                    )
);

key key_inst(
    .sclk                   (sclk                   ),
    .rst_n                  (rst_n                  ),
    .key                    (~key_i                 ),
    .key_o                  (key_flag               )      
);

icap_start icap_start_inst(
    .sclk                   (sclk                   ),
    .rst_n                  (rst_n                  ),
    .icap_flag              (key_flag               ),
    .icap_done              (                       )
);

endmodule

Code of icap_start module:

`timescale 1ns / 1ps
// *********************************************************************************
// Project Name : OSXXXX
// Author       : zhangningning
// Email        : nnzhang1996@foxmail.com
// Website      : 
// Module Name  : icap_start.v
// Create Time  : 2020-01-29 13:02:26
// Editor       : sublime text3, tab size (4)
// CopyRight(c) : All Rights Reserved
//
// *********************************************************************************
// Modification History:
// Date             By              Version                 Change Description
// -----------------------------------------------------------------------
// XXXX       zhangningning          1.0                        Original
//  
// *********************************************************************************

module icap_start(
    input                   sclk            ,
    input                   rst_n           ,
    input                   icap_flag       ,
    output  reg             icap_done 
);
 
//========================================================================================\
//**************Define Parameter and  Internal Signals**********************************
//========================================================================================/
wire                        csib            ;
reg                 [31:0]  con_data [ 7:0] ;
wire                [31:0]  con_data_r      ;
reg                 [ 2:0]  cnt             ;
reg                         busy_flag       ;
reg                         rdwrb           ;
 
//========================================================================================\
//**************     Main      Code        **********************************
//========================================================================================/
initial begin
    con_data[0]             =       32'hFFFF_FFFF;
    con_data[1]             =       32'hAA99_5566;
    con_data[2]             =       32'h2000_0000;
    con_data[3]             =       32'h3002_0001;
    con_data[4]             =       32'h00a0_0000;
    con_data[5]             =       32'h3000_8001;
    con_data[6]             =       32'h0000_000F;
    con_data[7]             =       32'h2000_0000;
end
assign      csib            =       ~busy_flag;
assign      con_data_r      =       {con_data[cnt][24],con_data[cnt][25],con_data[cnt][26],con_data[cnt][27],con_data[cnt][28],con_data[cnt][29],
                                     con_data[cnt][30],con_data[cnt][31],con_data[cnt][16],con_data[cnt][17],con_data[cnt][18],con_data[cnt][19],
                                     con_data[cnt][20],con_data[cnt][21],con_data[cnt][22],con_data[cnt][23],con_data[cnt][08],con_data[cnt][09],
                                     con_data[cnt][10],con_data[cnt][11],con_data[cnt][12],con_data[cnt][13],con_data[cnt][14],con_data[cnt][15],
                                     con_data[cnt][00],con_data[cnt][01],con_data[cnt][02],con_data[cnt][03],con_data[cnt][04],con_data[cnt][05],
                                     con_data[cnt][06],con_data[cnt][07]};

always @(posedge sclk or negedge rst_n)
    if(rst_n == 1'b0)
        busy_flag           <=      1'b0;
    else if(icap_flag == 1'b1 && busy_flag == 1'b0)
        busy_flag           <=      1'b1; 
    else if(cnt == 3'd7 && rdwrb == 1'b0)
        busy_flag           <=      1'b0;
    else
        busy_flag           <=      busy_flag;

always @(posedge sclk or negedge rst_n)
    if(rst_n == 1'b0)
        cnt                 <=      3'd0;
    else if(busy_flag == 1'b1 && rdwrb == 1'b0)
        cnt                 <=      cnt + 1'b1;
    else if(cnt == 3'd7 && rdwrb == 1'b0)
        cnt                 <=      3'd0;
    else
        cnt                 <=      cnt;

always @(posedge sclk or negedge rst_n)
    if(rst_n == 1'b0)
        icap_done           <=      1'b0;        
    else if(cnt == 3'd7 && rdwrb == 1'b0)
        icap_done           <=      1'b1;
    else
        icap_done           <=      1'b0;
          
always @(posedge sclk or negedge rst_n)
    if(rst_n == 1'b0)
        rdwrb               <=      1'b1; 
    else if(cnt == 3'd7 && rdwrb == 1'b0)
        rdwrb               <=      1'b1;       
    else if(busy_flag == 1'b1)
        rdwrb               <=      1'b0;
    else
        rdwrb               <=      rdwrb;

ICAPE2 #(
    .DEVICE_ID          (32'h3631093        ),     // Specifies the pre-programmed Device ID value to be used for simulation
                                                    // purposes.
    .ICAP_WIDTH         ("X32"              ),         // Specifies the input and output data width.
    .SIM_CFG_FILE_NAME  ("NONE"             )  // Specifies the Raw Bitstream (RBT) file to be parsed by the simulation
)ICAPE2_inst(
    .O                  (                   ),         // 32-bit output: Configuration data output bus
    .CLK                (sclk               ),     // 1-bit input: Clock Input
    .CSIB               (csib               ),   // 1-bit input: Active-Low ICAP Enable
    .I                  (con_data_r         ),         // 32-bit input: Configuration data input bus
    .RDWRB              (rdwrb              )  // 1-bit input: Read/Write Select input
);
 
//========================================================================================\
//*******************************     Debug    **********************************
//========================================================================================/
ila_0 ila_0_inst (
    .clk                (sclk               ), // input wire clk
    .probe0             (icap_flag          ), // input wire [0:0]  probe0  
    .probe1             (icap_done          ), // input wire [0:0]  probe1 
    .probe2             (csib               ), // input wire [0:0]  probe2 
    .probe3             (rdwrb              ), // input wire [0:0]  probe3 
    .probe4             (con_data_r         ) // input wire [31:0]  probe4
);



endmodule

led module code:

`timescale 1ns / 1ps
// *********************************************************************************
// Project Name : OSXXXX
// Author       : zhangningning
// Email        : nnzhang1996@foxmail.com
// Website      : 
// Module Name  : led.v
// Create Time  : 2020-01-30 11:47:29
// Editor       : sublime text3, tab size (4)
// CopyRight(c) : All Rights Reserved
//
// *********************************************************************************
// Modification History:
// Date             By              Version                 Change Description
// -----------------------------------------------------------------------
// XXXX       zhangningning          1.0                        Original
//  
// *********************************************************************************


module led(
    input                   sclk            ,
    input                   rst_n           ,
    output  reg     [ 3:0]  led             
);
 
//========================================================================================\
//**************Define Parameter and  Internal Signals**********************************
//========================================================================================/
    
 
//========================================================================================\
//**************     Main      Code        **********************************
//========================================================================================/
always @(posedge sclk or negedge rst_n)
    if(rst_n == 1'b0)
        led         <=      4'b0000;
    else 
        led         <=      4'b1010;

endmodule

Code of key module:

`timescale 1ns / 1ps
// *********************************************************************************
// Project Name : OSXXXX
// Author       : zhangningning
// Email        : nnzhang1996@foxmail.com
// Website      : 
// Module Name  : key.v
// Create Time  : 2020-01-05 13:49:36
// Editor       : sublime text3, tab size (4)
// CopyRight(c) : All Rights Reserved
//
// *********************************************************************************
// Modification History:
// Date             By              Version                 Change Description
// -----------------------------------------------------------------------
// XXXX       zhangningning          1.0                        Original
//  
// *********************************************************************************

module key(
    input                       sclk            ,
    input                       rst_n           ,
    input                       key             ,
    output  reg                 key_o       
);
 
//========================================================================================\
//**************Define Parameter and  Internal Signals**********************************
//========================================================================================/
parameter       IDLE        =       4'b0001     ;    
parameter       S1          =       4'b0010     ;
parameter       S2          =       4'b0100     ;
parameter       S3          =       4'b1000     ;

reg                 [ 3:0]      state           ;
reg                 [ 9:0]      cnt             ;
reg                             key_r1          ;
reg                             key_r2          ;
reg                             key_r3          ;
reg                             nege_flag       ;
reg                             pose_flag       ;
 
//========================================================================================\
//**************     Main      Code        **********************************
//========================================================================================/
always @(posedge sclk)
    key_r1          <=      key;

always @(posedge sclk)
    key_r2          <=      key_r1;

always @(posedge sclk)
    key_r3          <=      key_r2;

always @(posedge sclk or negedge rst_n)
    if(rst_n == 1'b0)
        nege_flag       <=      1'b0;
    else if(key_r3 == 1'b1 && key_r2 == 1'b0)
        nege_flag       <=      1'b1;
    else
        nege_flag       <=      1'b0;

always @(posedge sclk or negedge rst_n)
    if(rst_n == 1'b0)
        pose_flag       <=      1'b0;
    else if(key_r3 == 1'b0 && key_r2 == 1'b1) 
        pose_flag       <=      1'b1;
    else
        pose_flag       <=      1'b0;

always @(posedge sclk or negedge rst_n)
    if(rst_n == 1'b0)
        state           <=      IDLE;
    else case(state)
        IDLE    :   if(nege_flag == 1'b1)
                        state           <=      S1;
                    else
                        state           <=      IDLE;                        
        S1      :   if(cnt == 10'd999)
                        state           <=      S2;
                    else if(pose_flag == 1'b1)
                        state           <=      IDLE;
                    else
                        state           <=      S1;                        
        S2      :   if(pose_flag == 1'b1)
                        state           <=      S3;
                    else
                        state           <=      S2;                        
        S3      :   if(cnt == 10'd999)
                        state           <=      IDLE;
                    else if(nege_flag == 1'b1)
                        state           <=      S2;
                    else
                        state           <=      S3;
                        
        default :   state           <=      IDLE;
    endcase

always @(posedge sclk or negedge rst_n)
    if(rst_n == 1'b0)
        cnt             <=      10'd0;
    else if(state != S1 && state != S3)
        cnt             <=      10'd0;
    else
        cnt             <=      cnt + 1'b1;

always @(posedge sclk or negedge rst_n)
    if(rst_n == 1'b0)
        key_o           <=      1'b0;
    else if(state == S1 && cnt == 10'd999) 
        key_o           <=      1'b1;
    else
        key_o           <=      1'b0;

endmodule


Code for project 2:

`timescale 1ns / 1ps
// *********************************************************************************
// Project Name : OSXXXX
// Author       : zhangningning
// Email        : nnzhang1996@foxmail.com
// Website      : 
// Module Name  : led.v
// Create Time  : 2020-01-30 11:47:29
// Editor       : sublime text3, tab size (4)
// CopyRight(c) : All Rights Reserved
//
// *********************************************************************************
// Modification History:
// Date             By              Version                 Change Description
// -----------------------------------------------------------------------
// XXXX       zhangningning          1.0                        Original
//  
// *********************************************************************************


module led(
    input                   sclk            ,
    input                   rst_n           ,
    output  reg     [ 3:0]  led             
);
 
//========================================================================================\
//**************Define Parameter and  Internal Signals**********************************
//========================================================================================/
    
 
//========================================================================================\
//**************     Main      Code        **********************************
//========================================================================================/
always @(posedge sclk or negedge rst_n)
    if(rst_n == 1'b0)
        led         <=      4'b0000;
    else 
        led         <=      4'b1010;

endmodule

Verification

The above procedure is that I directly extended to ICAPE2 primitives according to the use of ICAP primitives. There was a little problem in the result of board loading, but there is no problem in writing ICAP primitives according to this method. It should be that I am not familiar with the use of ICAPE2. I will read the technical manual carefully and make corresponding corrections when I return to school.

Concluding remarks

Creation is not easy. Students who think the article is helpful can collect some praise and support. (projects are also in the group) students who have any opinions on the article or need to communicate further can join the following group:

Published 15 original articles, won praise 6, visited 4526
Private letter follow

Tags: sublime Verilog REST

Posted on Thu, 30 Jan 2020 04:29:49 -0500 by frih