qspi_stream_ip的verilog代码 - minichao9901/TangNano-20k-Zynq-7020 GitHub Wiki


`timescale 1 ns / 1 ps

	module qspi_stream_ip_v1_0_S00_AXIS #
	(
		// Users to add parameters here

		// User parameters ends
		// Do not modify the parameters beyond this line

		// AXI4Stream sink: Data Width
		parameter integer C_S_AXIS_TDATA_WIDTH	= 512
	)
	(
		// Users to add ports here
		input qspi_clk,
		input qspi_clk_rstn,
        output csx,
        output sck,
        output [3:0] dout,

		// 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
	);
	// 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  = 128;
	// 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
	reg fifo_rden;
    reg xfer_start;

	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) && ~full);

	always@(posedge S_AXIS_ACLK)
	begin
	  if(!S_AXIS_ARESETN)
	    begin
	      writes_done <= 1'b0;
	    end  
	  else
	    if (~full)
	      begin
	        if (fifo_wren)
	          begin
	            // write pointer is incremented after every write to the FIFO
	            // when FIFO write signal is enabled.
	            writes_done <= 1'b0;
	          end
	          if (~full|| 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;

	// Add user logic here
    wire full;
    wire empty;
    wire  [0:511] fifo_dout;
    wire [6:0] 	rd_data_count;
    wire [6:0] wr_data_count;
	
    fifo_generator_0 your_instance_name (
      .wr_clk(S_AXIS_ACLK),                // input wire wr_clk
      .rd_clk(qspi_clk),                // input wire rd_clk
      .din(S_AXIS_TDATA),                      // input wire [511 : 0] din
      .wr_en(fifo_wren),                  // input wire wr_en
      .rd_en(fifo_rden),                  // input wire rd_en
      .dout(fifo_dout),                    // output wire [511 : 0] dout
      .full(full),                    // output wire full
      .almost_full(almost_full),      // output wire almost_full
      .empty(empty),                  // output wire empty
      .almost_empty(almost_empty),    // output wire almost_empty
      .rd_data_count(rd_data_count),  // output wire [6 : 0] rd_data_count
      .wr_data_count(wr_data_count)  // output wire [6 : 0] wr_data_count
    );
    
    reg empty_d;
    always @(posedge qspi_clk or negedge qspi_clk_rstn)
    if(qspi_clk_rstn==0)
        empty_d<=0;
    else
        empty_d<=empty;
    
    assign first_rd_en=(~empty) & empty_d & xfer_rdy;            //第一次读,由empty信号下降沿自动启动   


    always @(posedge qspi_clk or negedge qspi_clk_rstn)
    if(qspi_clk_rstn==0) begin
        fifo_rden <= 0;
        xfer_start<=0;
    end
    else begin    
        fifo_rden <= (first_rd_en|xfer_final) & (~empty);  //fifo不为空的时候才可以读    
        xfer_start<= fifo_rden;
    end

    wire [7:0] cmd;
    wire [23:0] addr;
    reg [0:480-1] din; 
    wire [10:0]  vadid_length;  /* Max suppport DATA_SIZE=2047*8=16376 */   
    wire [1:0] data_mode;  /*00: cmd, 01: cmd+addr, 10: cmd+addr+1wire data, 11: cmd+addr+4wire data*/ 
    wire  cs_mode;  /*IDLE state, 0: cs=0, 1:cs=1, to support multi data_bursts while keep cs=0*/
    wire byte_mode; /* (0:for init) 0->1->2->3,  (1: for rgb565 color) 2->3->0->1 */ 
    
    qspi2  #(.DATA_SIZE(480)) qspi2_inst(
       // Input Ports - Single Bit
       .clk                (qspi_clk),                  
       .rst_n              (qspi_clk_rstn),   
       .cs_mode            (cs_mode),              
       .xfer_start         (xfer_start),      
       // Input Ports - Busses
       .addr         (addr),      
       .cmd           (cmd),        
       .data_mode     (data_mode),  
       .din        (din),     
       .vadid_length (vadid_length),
       // Output Ports - Single Bit
       .csx                (csx),             
       .sck                (sck),             
       .xfer_final         (xfer_final),      
       .xfer_rdy           (xfer_rdy),        
       // Output Ports - Busses
       .dout          (dout)       
       // InOut Ports - Single Bit
       // InOut Ports - Busses
    );
        

    reg  [0:511] fifo_dout_rev; 
    integer i;    
    always @(*)
    begin
        for (i = 0; i < 16; i = i + 1) begin
            fifo_dout_rev[32*i +: 32] = fifo_dout[(480-32*i) +: 32]; 
        end         
    end

    always @( *) begin
        if(byte_mode==0)
            for(i=1; i<16; i=i+1) begin
                din[(32*(i-1)+0)  +:8]= fifo_dout_rev[32*i+24 +:8];
                din[(32*(i-1)+8)  +:8]= fifo_dout_rev[32*i+16 +:8];
                din[(32*(i-1)+16) +:8]= fifo_dout_rev[32*i+8 +:8];
                din[(32*(i-1)+24) +:8]= fifo_dout_rev[32*i+0 +:8];
            end   
        else
            for(i=1; i<16; i=i+1) begin
                din[(32*(i-1)+0)  +:8]= fifo_dout_rev[32*i+16 +:8];
                din[(32*(i-1)+8)  +:8]= fifo_dout_rev[32*i+24 +:8];
                din[(32*(i-1)+16) +:8]= fifo_dout_rev[32*i+0 +:8];
                din[(32*(i-1)+24) +:8]= fifo_dout_rev[32*i+8 +:8];
            end              
    end
    
    wire [31:0] reg0;
    assign reg0=fifo_dout_rev[0:31];
//    assign din=fifo_dout_rev[32:511];                                
                      
    assign cmd=reg0[7:0];
    assign addr={8'h00, reg0[15:8], 8'h00};
    assign {byte_mode,cs_mode,data_mode}=reg0[19:16];
    assign vadid_length=reg0[30:20]; 
    

   //仅供波形分析使用
//    reg [31:0] regx1 [0:15];    
//    always @(*)
//    begin
//        for (i = 0; i < 16; i = i + 1) begin
//            regx1[i]=fifo_dout[32*i+:32];   
//        end         
//    end 
    
//    reg [31:0] regx2 [0:15];    
//    always @(*)
//    begin
//        for (i = 0; i < 16; i = i + 1) begin
//            regx2[i]=fifo_dout_rev[32*i+:32];   
//        end         
//    end 

//    reg [31:0] regx3 [0:14];    
//    always @(*)
//    begin
//        for (i = 0; i < 15; i = i + 1) begin
//            regx3[i]=din[32*i+:32];   
//        end         
//    end               


	// User logic ends

	endmodule