STARTUPE3原语的使用

分享我写的一个程序,利用STARTUPE3原语实现读写配置flash,用的是VU3P+S25FL256S flash,有需要的可以参考一下。

`timescale 1ns / 1ps

module top(
    input sys_clk,
    output led
    
    );
    
    reg rst_n;

    wire Read_tx_en;
    wire MISO;
    wire CS;
    wire SCK;
    wire MOSI;
    wire [31:0] Read_Usr_Addr;
    wire [7:0] Read_Usr_Cmd;
    wire [7:0] DATA_OUT;
    wire Write_tx_en;
    wire Write_en;

    wire [31:0] Write_Usr_Addr;
    wire [7:0] Write_Usr_Cmd;
    wire [7:0] Write_Usr_Data;

    wire Erase_en;
    wire [31:0] Erase_Addr;
    wire [7:0] Erase_Cmd;

    wire Read_Cmd_Send_Ok;
    wire Read_Addr_Send_Ok;
    wire Read_Data_Ok;
    wire Write_Cmd_Send_Ok;
    wire Write_Addr_Send_Ok;
    wire Write_Data_Ok;
    wire Write_Enable_Ok;
    wire Erase_Ok;
    //wire sys_clk;
    
//    clk_wiz_0 clk_wiz_0_u
//   (
//        // Clock out ports
//        .clk_out1(sys_clk),     // output clk_out1
//        // Status and control signals
//        .reset(1'b0), // input reset
//        .locked(),       // output locked
//        // Clock in ports
//        .clk_in1(clk_100M)
//    );      // input clk_in1
    
    vio_0 your_instance_name (
        .clk(sys_clk),                // input wire clk
        .probe_in0(),    // input wire [0 : 0] probe_in0
        .probe_in1(),    // input wire [0 : 0] probe_in1
        .probe_in2(),    // input wire [0 : 0] probe_in2
        .probe_out0(Read_tx_en),  // output wire [0 : 0] probe_out0
        .probe_out1(Read_Usr_Addr),  // output wire [31 : 0] probe_out1
        .probe_out2(Read_Usr_Cmd),  // output wire [7 : 0] probe_out2
        .probe_out3(Write_tx_en),  // output wire [0 : 0] probe_out3
        .probe_out4(Write_Usr_Addr),  // output wire [31 : 0] probe_out4
        .probe_out5(Write_Usr_Cmd),  // output wire [7 : 0] probe_out5
        .probe_out6(Write_Usr_Data),  // output wire [7 : 0] probe_out6
        .probe_out7(Erase_en),  // output wire [0 : 0] probe_out7
        .probe_out8(Erase_Addr),  // output wire [31 : 0] probe_out8
        .probe_out9(Erase_Cmd)  // output wire [7 : 0] probe_out9
    );

    
    Read_Write_SignalBytes Read_Write_SignalBytes_u(

        .sys_clk(sys_clk),
        .rst_n(rst_n),
        .Read_tx_en(Read_tx_en),                         //发送使能
        .MISO(MISO),

        .Read_Usr_Addr(Read_Usr_Addr),
        .Read_Usr_Cmd(Read_Usr_Cmd),
   
        .Write_tx_en(Write_tx_en),         //发送完 写使能  紧接着就发送地址和数据
        .Write_en(Write_en),

        .Write_Usr_Addr(Write_Usr_Addr),
        .Write_Usr_Cmd(Write_Usr_Cmd),
        .Write_Usr_Data(Write_Usr_Data),
        
         .Erase_en(Erase_en),

        .Erase_Addr(Erase_Addr),
        .Erase_Cmd(Erase_Cmd),

        .CS(CS),
        .SCK(SCK),
        .MOSI(MOSI),
        .DATA_OUT(DATA_OUT),

        .Read_Cmd_Send_Ok(Read_Cmd_Send_Ok),
        .Read_Addr_Send_Ok(Read_Addr_Send_Ok),
        .Read_Data_Ok(Read_Data_Ok),

        .Write_Cmd_Send_Ok(Write_Cmd_Send_Ok),
        .Write_Addr_Send_Ok(Write_Addr_Send_Ok),
        .Write_Data_Ok(Write_Data_Ok),
        .Write_Enable_Ok(Write_Enable_Ok),
        
         .Erase_Ok(Erase_Ok)

    );
    
    
    STARTUPE3 #(
      .PROG_USR("FALSE"),  
      
      .SIM_CCLK_FREQ(0.0)  // Set the Configuration Clock Frequency (ns) for simulation
   )
   STARTUPE3_inst (
      .CFGCLK(),       // 1-bit output: Configuration main clock output
      .CFGMCLK(),     // 1-bit output: Configuration internal oscillator clock output
      .DI({1'b0,1'b0,MISO,1'b0}),               // 4-bit output: Allow receiving on the D input pin
      .EOS(),             // 1-bit output: Active-High output signal indicating the End Of Startup
      .PREQ(),           // 1-bit output: PROGRAM request to fabric output
      .DO({1'b0,1'b0,1'b0,MOSI}),               // 4-bit input: Allows control of the D pin output
      .DTS(4'b0000),             // 4-bit input: Allows tristate of the D pin
      .FCSBO(CS),         // 1-bit input: Controls the FCS_B pin for flash access
      .FCSBTS(0),       // 1-bit input: Tristate the FCS_B pin
      .GSR(0),             // 1-bit input: Global Set/Reset input (GSR cannot be used for the port)
      .GTS(0),             // 1-bit input: Global 3-state input (GTS cannot be used for the port name)
      .KEYCLEARB(0), // 1-bit input: Clear AES Decrypter Key input from Battery-Backed RAM (BBRAM)
      .PACK(0),           // 1-bit input: PROGRAM acknowledge input
      .USRCCLKO(SCK),   // 1-bit input: User CCLK input
      .USRCCLKTS(0), // 1-bit input: User CCLK 3-state enable input
      .USRDONEO(),   // 1-bit input: User DONE pin output control
      .USRDONETS(0)  // 1-bit input: User DONE 3-state enable output
   );
   
  
    
    reg [27:0] cnt;
    
    assign led = (cnt == 28'd100_000_000) ? ~led : led;
    
    always @(posedge sys_clk) begin
        if (cnt > 28'd100_000_000) begin
            cnt <= 28'd0;
            rst_n <= 1'b1;
        end
        else
            cnt <= cnt + 1'b1;
    end
    
     
    (*MARK_DEBUG = "TRUE"*)reg Read_tx_en_ila;
    (*MARK_DEBUG = "TRUE"*)reg MISO_ila;
    (*MARK_DEBUG = "TRUE"*)reg CS_ila;
    (*MARK_DEBUG = "TRUE"*)reg SCK_ila;
    (*MARK_DEBUG = "TRUE"*)reg MOSI_ila;
    (*MARK_DEBUG = "TRUE"*)reg [31:0] Read_Usr_Addr_ila;
    (*MARK_DEBUG = "TRUE"*)reg [7:0] Read_Usr_Cmd_ila;
    (*MARK_DEBUG = "TRUE"*)reg [7:0] DATA_OUT_ila;
    (*MARK_DEBUG = "TRUE"*)reg Write_tx_en_ila;
    
    (*MARK_DEBUG = "TRUE"*)reg [31:0] Write_Usr_Addr_ila;
    (*MARK_DEBUG = "TRUE"*)reg [7:0] Write_Usr_Cmd_ila;
    (*MARK_DEBUG = "TRUE"*)reg [7:0] Write_Usr_Data_ila;

    (*MARK_DEBUG = "TRUE"*)reg Erase_en_ila;
    (*MARK_DEBUG = "TRUE"*)reg [31:0] Erase_Addr_ila;
    (*MARK_DEBUG = "TRUE"*)reg [7:0] Erase_Cmd_ila;

    (*MARK_DEBUG = "TRUE"*)reg Read_Cmd_Send_Ok_ila;
    (*MARK_DEBUG = "TRUE"*)reg Read_Addr_Send_Ok_ila;
    (*MARK_DEBUG = "TRUE"*)reg Read_Data_Ok_ila;
    (*MARK_DEBUG = "TRUE"*)reg Write_Cmd_Send_Ok_ila;
    (*MARK_DEBUG = "TRUE"*)reg Write_Addr_Send_Ok_ila;
    (*MARK_DEBUG = "TRUE"*)reg Write_Data_Ok_ila;
    (*MARK_DEBUG = "TRUE"*)reg Write_Enable_Ok_ila;
    (*MARK_DEBUG = "TRUE"*)reg Erase_Ok_ila;
    (*MARK_DEBUG = "TRUE"*)reg rst_n_ila;

    always @(posedge sys_clk) begin
         Read_tx_en_ila <= Read_tx_en;
         MISO_ila <= MISO;
         CS_ila <= CS;
         SCK_ila <= SCK;
         MOSI_ila <= MOSI;
         Read_Usr_Addr_ila <= Read_Usr_Addr;
         Read_Usr_Cmd_ila <= Read_Usr_Cmd;
         DATA_OUT_ila <= DATA_OUT;
         Write_tx_en_ila <= Write_tx_en;
    

         Write_Usr_Addr_ila <= Write_Usr_Addr;
         Write_Usr_Cmd_ila <= Write_Usr_Cmd;
         Write_Usr_Data_ila <= Write_Usr_Data;

         Erase_en_ila <= Erase_en;
         Erase_Addr_ila <= Erase_Addr;
         Erase_Cmd_ila <= Erase_Cmd;

         Read_Cmd_Send_Ok_ila <= Read_Cmd_Send_Ok;
         Read_Addr_Send_Ok_ila <= Read_Addr_Send_Ok;
         Read_Data_Ok_ila <= Read_Data_Ok;
         Write_Cmd_Send_Ok_ila <= Write_Cmd_Send_Ok;
         Write_Addr_Send_Ok_ila <= Write_Addr_Send_Ok;
         Write_Data_Ok_ila <= Write_Data_Ok;
         Write_Enable_Ok_ila <= Write_Enable_Ok;
         Erase_Ok_ila <= Erase_Ok;
         
         rst_n_ila <= rst_n;

    end
    
    
    
    
    
endmodule

`timescale 1ns / 1ps


module Read_Write_SignalBytes(

    input sys_clk,
    input rst_n,
    input Read_tx_en,                         //发送使能
    input MISO,

    input [31:0] Read_Usr_Addr,
    input [7:0]  Read_Usr_Cmd,
    
    input Write_tx_en,
    input Write_en,

    input [31:0] Write_Usr_Addr,
    input [7:0] Write_Usr_Cmd,
    input [7:0] Write_Usr_Data,

    input Erase_en,

    input [31:0] Erase_Addr,
    input [7:0] Erase_Cmd,
    

    output reg CS,
    output reg SCK,
    output reg MOSI,
    output reg [7:0] DATA_OUT,

    output reg Read_Cmd_Send_Ok,
    output reg Read_Addr_Send_Ok,
    output reg Read_Data_Ok,

    output reg Write_Cmd_Send_Ok,
    output reg Write_Addr_Send_Ok,
    output reg Write_Data_Ok,
    output reg Write_Enable_Ok,
    output reg Erase_enable_Ok,

    output reg Erase_Ok

    );
    
    //  写数据发送使能
    reg [5:0] cnt;

    reg Write_tx_en_dly1;
    reg Write_tx_en_dly2;

    wire Write_tx_en_pos;
    reg Write_tx_en_pos_dly;

    always @(posedge sys_clk or negedge rst_n) begin
        if (!rst_n) begin
            Write_tx_en_dly1 <= 1'b0;
            Write_tx_en_dly2 <= 1'b0;
        end
        else begin
            {Write_tx_en_dly2, Write_tx_en_dly1} <= {Write_tx_en_dly1, Write_tx_en};
        end
    end

    assign Write_tx_en_pos = ~Write_tx_en_dly2 & Write_tx_en_dly1;

    always @(posedge sys_clk or negedge rst_n) begin
        if (!rst_n) begin
            Write_tx_en_pos_dly <= 1'b0;
        end
        else begin
            Write_tx_en_pos_dly <= Write_tx_en_pos;
        end
    end

    
    //  写使能 发送使能
    reg [7:0] Enable_Data = 8'h06;
    
    reg [1:0] Write_en_dly;
    wire Write_en_pos;
    reg Write_en_pos_dly;
    
    assign Write_en_pos = ~Write_en_dly[1] & Write_en_dly[0];
    
    always @(posedge sys_clk) begin
        Write_en_dly[1:0] <= {Write_en_dly[0],Write_en};
        Write_en_pos_dly <= Write_en_pos;
    end

    //  读数据发送使能
    reg tx_en_dly1;
    reg tx_en_dly2;

    wire tx_en_pos;
    reg tx_en_pos_dly;

    always @(posedge sys_clk or negedge rst_n) begin
        if (!rst_n) begin
            tx_en_dly1 <= 1'b0;
            tx_en_dly2 <= 1'b0;
        end
        else begin
            {tx_en_dly2, tx_en_dly1} <= {tx_en_dly1, Read_tx_en};
        end
    end

    assign tx_en_pos = ~tx_en_dly2 & tx_en_dly1;

    always @(posedge sys_clk or negedge rst_n) begin
        if (!rst_n) begin
            tx_en_pos_dly <= 1'b0;
        end
        else begin
            tx_en_pos_dly <= tx_en_pos;
        end
    end

    // 擦除使能
    reg [1:0] Erase_en_dly;
    reg Erase_en_pos_dly;
    wire Erase_en_pos;

    assign Erase_en_pos = ~Erase_en_dly[1] & Erase_en_dly[0];

    always @(posedge sys_clk or negedge rst_n) begin
        if (!rst_n) begin
            Erase_en_dly <= 2'd0;
        end
        else begin
            Erase_en_dly[1:0] <= {Erase_en_dly[0], Erase_en};
            Erase_en_pos_dly <= Erase_en_pos;
        end
    end
    

    // 读数据的逻辑
    reg [16:0] Current_State = 17'd0;
    parameter READY = 17'b0_0000_0000_0000_0000;
    parameter READ_CMD = 17'b0_0000_0000_0000_0001;
    parameter READ_ADDR = 17'b0_0000_0000_0000_0010;
    parameter READ_DATA =  17'b0_0000_0000_0000_0100;
    parameter READ_FINISH = 17'b0_0000_0000_0000_1000;
    //  写数据得逻辑
    parameter WRITE_READY = 17'b0_1000_0000_0000_0000;
    parameter WRITE_CMD = 17'b0_0000_0000_0001_0000;
    parameter WRITE_ADDR = 17'b0_0000_0000_0010_0000;
    parameter WRITE_DATA =  17'b0_0000_0000_0100_0000;
    parameter WRITE_FINISH = 17'b0_0000_0000_1000_0000;
    //  写使能的逻辑
    parameter WRITE_ENABLE = 17'b0_0000_0001_0000_0000;
    parameter WRITE_OVER = 17'b0_0000_0010_0000_0000;

    //  擦除sector的逻辑
    parameter ERASE_ENABLE = 17'b0_0000_0100_0000_0000;
    parameter ERASE_OVER = 17'b0_0000_1000_0000_0000;
    parameter ERASE_READY = 17'b1_0000_0000_0000_0000;
    parameter ERASE_CMD = 17'b0_0001_0000_0000_0000;
    parameter ERASE_ADDR = 17'b0_0010_0000_0000_0000;
    parameter ERASE_FINISH = 17'b0_0100_0000_0000_0000;


    always @(posedge sys_clk or negedge rst_n) begin
        if (!rst_n) begin
            CS <= 1'b1;
            MOSI <= 1'b0;
            cnt <= 5'd0;
            Current_State <= READY;
            Read_Cmd_Send_Ok <= 1'b0;
            Read_Addr_Send_Ok <= 1'b0;     //发送完成
            Read_Data_Ok <= 1'b0;
            Write_Cmd_Send_Ok <= 1'b0;
            Write_Addr_Send_Ok <= 1'b0;
            Write_Data_Ok <= 1'b0;
            Write_Enable_Ok <= 1'b0;
            Erase_enable_Ok <= 1'b0;
            Erase_Ok <= 1'b0;
            Enable_Data <= 8'h06;
        end
        else begin
            case (Current_State)
                READY:begin
                    if (tx_en_pos_dly) begin   // 读使能
                        CS <= 1'b0;
                        MOSI <= Read_Usr_Cmd[7];
                        Current_State <= READ_CMD;
                    end
                    else if (Write_en_pos_dly) begin
                        CS <= 1'b0;
                        MOSI <= Enable_Data[7];
                        Current_State <= WRITE_ENABLE;
                    end
                    else if (Write_tx_en_pos_dly) begin         //写数据使能
                        CS <= 1'b0;
                        MOSI <= Enable_Data[7];
                        Current_State <= WRITE_ENABLE;          //写发送写使能
                    end
                    else if (Erase_en_pos_dly) begin            //擦除使能
                        CS <= 1'b0;
                        MOSI <= Enable_Data[7];
                        Current_State <= ERASE_ENABLE;
                    end
                    else begin
                         CS <= 1'b1;
                         Current_State <= READY;
                    end
                end
                //擦除数据的逻辑
                ERASE_ENABLE: begin
                    if (cnt <= 5'd6)begin
                        if (SCK) begin
                            MOSI <= Enable_Data[6-cnt];
                            cnt <= cnt + 1'b1;
                        end
                        else begin
                            cnt <= cnt;
                        end
                    end
                    else begin
                        cnt <= 5'd0;
                        Erase_enable_Ok <= 1'b1;
                        Current_State <= ERASE_OVER;
                    end
                end
                ERASE_OVER: begin
                    CS <= 1'b1;
                    MOSI <= 1'b0;
                    Erase_enable_Ok <= 1'b0;
                    Current_State <= ERASE_READY;
                end
                ERASE_READY:begin
                    CS <= 1'b0;
                    MOSI <= Erase_Cmd[7];
                    Current_State <= ERASE_CMD;
                end
                ERASE_CMD:begin
                    if (cnt <= 5'd6) begin
                        if (SCK) begin
                            MOSI <= Erase_Cmd[6-cnt];
                            cnt <= cnt + 1'b1;
                        end
                        else begin
                            cnt <= cnt;
                        end
                    end
                    else begin
                        cnt <= 5'd0;
                        Current_State <= ERASE_ADDR;
                    end
                end
                ERASE_ADDR:begin
                    if (cnt <= 5'd31) begin
                        if (SCK) begin
                            MOSI <= Erase_Addr[31-cnt];
                            cnt <= cnt + 1'b1;
                        end
                        else begin
                            cnt <= cnt;
                        end
                    end
                    else begin
                        cnt <= 5'd0;
                        Current_State <= ERASE_FINISH;
                        Erase_Ok <= 1'b1;
                    end
                end
                ERASE_FINISH:begin
                    Erase_Ok <= 1'b0;
                    CS <= 1'b1;
                    Current_State <= READY;
                    MOSI <= 1'b0;
                end
                //  读数据的逻辑
                READ_CMD:begin
                    if (cnt <= 5'd6) begin
                        if (SCK) begin
                            MOSI <= Read_Usr_Cmd[6-cnt];
                            cnt <= cnt + 1'b1;
                        end
                        else begin
                            cnt <= cnt;
                        end
                    end
                    else begin
                        cnt <= 5'd0;
                        Current_State <= READ_ADDR;
                        Read_Cmd_Send_Ok <= 1'b1;
                    end
                end
                READ_ADDR:begin
                    Read_Cmd_Send_Ok <= 1'b0;
                    if (cnt <= 5'd31) begin
                        if (SCK) begin
                            MOSI <= Read_Usr_Addr[31-cnt];
                            cnt <= cnt + 1'b1;
                        end
                        else begin
                            cnt <= cnt;
                        end
                    end
                    else begin
                        cnt <= 5'd0;
                        Read_Addr_Send_Ok <= 1'b1;
                        Current_State <= READ_DATA;
                    end
                end
                READ_DATA:begin
                    Read_Addr_Send_Ok <= 1'b0;
                    if (cnt <= 5'd7) begin
                        if (!SCK) begin
                            DATA_OUT[7-cnt] <= MISO;
                            cnt <= cnt + 1'b1;
                        end
                        else begin
                            cnt <= cnt;
                        end
                    end
                    else begin
                        cnt <= 5'd0;
                        Current_State <= READ_FINISH;
                        Read_Data_Ok <= 1'b1;
                    end
                end
                READ_FINISH:begin
                    Read_Data_Ok <= 1'b0;
                    CS <= 1'b1;
                    Current_State <= READY;
                    //SCK <= 1'b0;
                    MOSI <= 1'b0;
                end
                //  写  写使能
                WRITE_ENABLE:begin
                    if (cnt <= 5'd6) begin
                        if (SCK) begin
                            MOSI <= Enable_Data[6-cnt];
                            cnt <= cnt + 1'b1;
                        end
                        else begin
                            cnt <= cnt;
                        end
                    end
                    else begin
                        Write_Enable_Ok <= 1'b1;
                        cnt <= 5'd0;
                        Current_State <= WRITE_OVER;
                    end
                end
                WRITE_OVER:begin
                    CS <= 1'b1;
                    MOSI <= 1'b0;
                    Write_Enable_Ok <= 1'b0;
                    Current_State <= WRITE_READY;
                end
                //  写数据的逻辑
                WRITE_READY:begin
                    CS <= 1'b0;
                    MOSI <= Write_Usr_Cmd[7];
                    Current_State <= WRITE_CMD;
                end
                WRITE_CMD:begin
                    if (cnt <= 5'd6) begin
                        if (SCK) begin
                            MOSI <= Write_Usr_Cmd[6-cnt];
                            cnt <= cnt + 1'b1;
                        end
                        else begin
                            cnt <= cnt;
                        end
                    end
                    else begin
                        cnt <= 5'd0;
                        Current_State <= WRITE_ADDR;
                        Write_Cmd_Send_Ok <= 1'b1;
                    end
                end
                WRITE_ADDR:begin
                    Write_Cmd_Send_Ok <= 1'b0;
                    if (cnt <= 5'd31) begin
                        if (SCK) begin
                            MOSI <= Write_Usr_Addr[31-cnt];
                            cnt <= cnt + 1'b1;
                        end
                        else begin
                            cnt <= cnt;
                        end
                    end
                    else begin
                        cnt <= 5'd0;
                        Write_Addr_Send_Ok <= 1'b1;
                        Current_State <= WRITE_DATA;
                    end
                end
                WRITE_DATA:begin
                    Write_Addr_Send_Ok <= 1'b0;
                    if (cnt <= 5'd7) begin
                        if (SCK) begin
                            MOSI <= Write_Usr_Data[7-cnt];
                            cnt <= cnt + 1'b1;
                        end
                        else begin
                            cnt <= cnt;
                        end
                    end
                    else begin
                        cnt <= 5'd0;
                        Current_State <= WRITE_FINISH;
                        Write_Data_Ok <= 1'b1;
                    end
                end
                WRITE_FINISH:begin
                    Write_Data_Ok <= 1'b0;
                    CS <= 1'b1;
                    Current_State <= READY;
                    //SCK <= 1'b0;
                    MOSI <= 1'b0;
                end
                default:begin
                    CS <= 1'b1;
                    Current_State <= READY;
                    SCK <= 1'b0;
                    MOSI <= 1'b0;
                end
                

            endcase
        end
    end

    always @(posedge sys_clk) begin
        if (!CS) begin
            SCK <= ~SCK;
        end
        else begin
            SCK <= 1'b0;
        end
    end


endmodule
 

你可能感兴趣的:(fpga开发,单片机,嵌入式硬件)