qspi优化:qspi2 - minichao9901/TangNano-20k-Zynq-7020 GitHub Wiki

D1 驱动代码

`timescale 1ns / 1ps

module qspi2
#(
    parameter DATA_SIZE=9600  /* 400*3=1200 bytes */
)
(
    input clk,
    input rst_n,
    
    (*mark_debug="true"*)input xfer_start,
    (*mark_debug="true"*)output reg xfer_final,
    (*mark_debug="true"*)output xfer_rdy,           
    
    (*mark_debug="true"*)input [7:0] cmd,
    (*mark_debug="true"*)input [23:0] addr,
    (*mark_debug="true"*)input [0: DATA_SIZE-1] din, 
    (*mark_debug="true"*)input [10:0]  vadid_length,  /* Max suppport DATA_SIZE=2047*8=16376 */   
    (*mark_debug="true"*)input [1:0] data_mode,  /*00: cmd, 01: cmd+addr, 10: cmd+addr+1wire data, 11: cmd+addr+4wire data*/ 
    (*mark_debug="true"*)input  cs_mode,  /*IDLE state, 0: cs=0, 1:cs=1, to support multi data_bursts while keep cs=0*/     
    
    (*mark_debug="true"*)output reg csx,
    (*mark_debug="true"*)output reg sck,
    (*mark_debug="true"*)output reg [3:0] dout
    );
    
parameter IDLE=2'b00;
parameter SEND_CMD=2'b01;
parameter SEND_DATA=2'b10;
parameter SEND_WAIT=2'b11;

reg [1:0] state;
reg [6:0] lsm_cnt;
reg [10:0] xfer_valid_cnt;
reg xfer_end;

wire [10:0] valid_length_min;
assign valid_length_min=(vadid_length<=DATA_SIZE/8)? vadid_length:(DATA_SIZE/8);

always @(posedge clk or negedge rst_n)
if(rst_n==0)
    state<=IDLE;
else case(state)
    IDLE: if(xfer_start) 
            state<=SEND_CMD;
    SEND_CMD: if(xfer_end && xfer_final)
                state<=IDLE;
              else if(xfer_end && ~xfer_final)
                state<=SEND_DATA;
    SEND_DATA: if(xfer_end && xfer_final && cs_mode)
                state<=IDLE;
               else if(xfer_end && xfer_final && ~cs_mode)
                state<=SEND_WAIT;
    SEND_WAIT: if(xfer_start)
                state<=SEND_DATA;
    default: state<=IDLE;
endcase
    
always @(posedge clk or negedge rst_n)
if(rst_n==0)
    xfer_valid_cnt<=11'd0;
else if((state==IDLE|| state==SEND_WAIT) && xfer_start)
    xfer_valid_cnt<=valid_length_min;
else if(state==SEND_DATA) begin
    if((data_mode==2'b10) && lsm_cnt==16-1       /* 1wire */
        || (data_mode==2'b11) && lsm_cnt==4-1)   /* 4wire */
        xfer_valid_cnt<=xfer_valid_cnt-1;
end
    
always @(posedge clk or negedge rst_n)
if(rst_n==0)
    lsm_cnt<=0;
else if(state==IDLE || state==SEND_WAIT)
    lsm_cnt<=0;  
else if(state==SEND_CMD) begin
    if(xfer_end)
        lsm_cnt<=0;
    else
        lsm_cnt<=lsm_cnt+1;
end
else if(state==SEND_DATA) begin
    if((data_mode==2'b10) && lsm_cnt==16-1       /* 1wire */
        || (data_mode==2'b11) && lsm_cnt==4-1)   /* 4wire */
        lsm_cnt<=0;
    else
        lsm_cnt<=lsm_cnt+1;
end

reg [0:7] din_tmp;
always @(*) begin
if(state==SEND_DATA && xfer_valid_cnt>=1)
    din_tmp=din[(valid_length_min-xfer_valid_cnt)*8 +:8];
else
    din_tmp=8'h00;
end
 
always @(posedge clk or negedge rst_n)
if(rst_n==0) begin
    csx<=1;
    sck<=0;
    dout<=4'h0;
end
else case(state)
    IDLE: begin csx<=1; sck=0; end       //begin and final state
    SEND_WAIT: begin csx<=0; sck=0; end  //intermediate state    
    SEND_CMD: begin
        dout[3:1]<=3'b000;            
         if(data_mode==2'b00)
             case(lsm_cnt)
                0:  begin csx<=0;end
                1:  begin dout[0]<=cmd[7];end
                2:  begin sck<=1;end     
                3:  begin dout[0]<=cmd[6]; sck<=0; end
                4:  begin sck<=1;end      
                5:  begin dout[0]<=cmd[5]; sck<=0; end
                6:  begin sck<=1;end     
                7:  begin dout[0]<=cmd[4]; sck<=0; end
                8:  begin sck<=1;end    
                9:  begin dout[0]<=cmd[3]; sck<=0; end
                10: begin sck<=1;end     
                11: begin dout[0]<=cmd[2]; sck<=0; end
                12: begin sck<=1;end      
                13: begin dout[0]<=cmd[1]; sck<=0; end
                14: begin sck<=1;end     
                15: begin dout[0]<=cmd[0]; sck<=0; end
                16: begin sck<=1;end                                                                               
            endcase 
        else if(data_mode!=2'b00)
             case(lsm_cnt)
                0:  begin csx<=0;end
                1:  begin dout[0]<=cmd[7];end
                2:  begin sck<=1;end     
                3:  begin dout[0]<=cmd[6]; sck<=0; end
                4:  begin sck<=1;end      
                5:  begin dout[0]<=cmd[5]; sck<=0; end
                6:  begin sck<=1;end     
                7:  begin dout[0]<=cmd[4]; sck<=0; end
                8:  begin sck<=1;end    
                9:  begin dout[0]<=cmd[3]; sck<=0; end
                10: begin sck<=1;end     
                11: begin dout[0]<=cmd[2]; sck<=0; end
                12: begin sck<=1;end      
                13: begin dout[0]<=cmd[1]; sck<=0; end
                14: begin sck<=1;end     
                15: begin dout[0]<=cmd[0]; sck<=0; end
                16: begin sck<=1;end   
                                  
                17: begin dout[0]<=addr[23]; sck<=0; end
                18: begin sck<=1;end      
                19: begin dout[0]<=addr[22]; sck<=0; end
                20: begin sck<=1;end     
                21: begin dout[0]<=addr[21]; sck<=0; end
                22: begin sck<=1;end    
                23: begin dout[0]<=addr[20]; sck<=0; end
                24: begin sck<=1;end     
                25: begin dout[0]<=addr[19]; sck<=0; end
                26: begin sck<=1;end      
                27: begin dout[0]<=addr[18]; sck<=0; end
                28: begin sck<=1;end     
                29: begin dout[0]<=addr[17]; sck<=0; end    
                30: begin sck<=1;end     
                31: begin dout[0]<=addr[16]; sck<=0; end
                32: begin sck<=1;end      
                33: begin dout[0]<=addr[15]; sck<=0; end
                34: begin sck<=1;end     
                35: begin dout[0]<=addr[14]; sck<=0; end
                36: begin sck<=1;end    
                37: begin dout[0]<=addr[13]; sck<=0; end
                38: begin sck<=1;end     
                39: begin dout[0]<=addr[12]; sck<=0; end
                40: begin sck<=1;end      
                41: begin dout[0]<=addr[11]; sck<=0; end
                42: begin sck<=1;end     
                43: begin dout[0]<=addr[10]; sck<=0; end    
                44: begin sck<=1;end   
                
                45: begin dout[0]<=addr[9]; sck<=0; end
                46: begin sck<=1;end      
                47: begin dout[0]<=addr[8]; sck<=0; end
                48: begin sck<=1;end     
                49: begin dout[0]<=addr[7]; sck<=0; end
                50: begin sck<=1;end    
                51: begin dout[0]<=addr[6]; sck<=0; end
                52: begin sck<=1;end     
                53: begin dout[0]<=addr[5]; sck<=0; end
                54: begin sck<=1;end      
                55: begin dout[0]<=addr[4]; sck<=0; end
                56: begin sck<=1;end     
                57: begin dout[0]<=addr[3]; sck<=0; end    
                58: begin sck<=1;end     
                59: begin dout[0]<=addr[2]; sck<=0; end
                60: begin sck<=1;end      
                61: begin dout[0]<=addr[1]; sck<=0; end
                62: begin sck<=1;end     
                63: begin dout[0]<=addr[0]; sck<=0; end
                64: begin sck<=1;end                                                                                                                    
            endcase  
     end
     
     SEND_DATA: begin
            if(data_mode==2'b10) begin
                 dout[3:1]<=3'b000;             
                 case(lsm_cnt)
                    0:  begin dout[0]<=din_tmp[0]; sck<=0; end
                    1:  begin sck<=1;end     
                    2:  begin dout[0]<=din_tmp[1]; sck<=0; end
                    3:  begin sck<=1;end      
                    4:  begin dout[0]<=din_tmp[2]; sck<=0; end
                    5:  begin sck<=1;end     
                    6:  begin dout[0]<=din_tmp[3]; sck<=0; end
                    7:  begin sck<=1;end    
                    8:  begin dout[0]<=din_tmp[4]; sck<=0; end
                    9:  begin sck<=1;end     
                    10: begin dout[0]<=din_tmp[5]; sck<=0; end
                    11: begin sck<=1;end      
                    12: begin dout[0]<=din_tmp[6]; sck<=0; end
                    13: begin sck<=1;end     
                    14: begin dout[0]<=din_tmp[7]; sck<=0; end
                    15: begin sck<=1;end  
                endcase  
           end  
           else if(data_mode==2'b11)
                 case(lsm_cnt)
                    0:  begin dout[3:0]<=din_tmp[0:3]; sck<=0; end
                    1:  begin sck<=1;end     
                    2:  begin dout[3:0]<=din_tmp[4:7]; sck<=0; end
                    3:  begin sck<=1;end       
                endcase                                                      
     end   
        
endcase

//xfer_end要单独产生,因为它只占一个aclk脉宽,与其它信号不一样
always @(posedge clk or negedge rst_n)
if(rst_n==0)
    xfer_end<=0;
else if(state==SEND_CMD && (data_mode==2'b00) && lsm_cnt==17)
    xfer_end<=1;
else if(state==SEND_CMD && (data_mode!=2'b00) && lsm_cnt==65)
    xfer_end<=1; 
else if(state==SEND_DATA &&  (data_mode==2'b10) && lsm_cnt==16-1 && xfer_valid_cnt==1)
    xfer_end<=1;
else if(state==SEND_DATA &&  (data_mode==2'b11) && lsm_cnt==4-1 && xfer_valid_cnt==1)
    xfer_end<=1;  
else
    xfer_end<=0; 
    
always @(posedge clk or negedge rst_n)
if(rst_n==0)
    xfer_final<=0;
else if(state==SEND_CMD && (data_mode==2'b00) && lsm_cnt==17)   //cmd only 
    xfer_final<=1;
else if(state==SEND_CMD && (data_mode==2'b01) && lsm_cnt==65)   //cmd+addr
    xfer_final<=1;    
else if(state==SEND_DATA &&  (data_mode==2'b10) && lsm_cnt==16-1 && xfer_valid_cnt==1)  //data use 1wire
    xfer_final<=1;
else if(state==SEND_DATA &&  (data_mode==2'b11) && lsm_cnt==4-1 && xfer_valid_cnt==1)   //data use 4wire
    xfer_final<=1;    
else
    xfer_final<=0; 
   
assign xfer_rdy=(state==IDLE || state==SEND_WAIT)? 1:0;         
    
endmodule

D2 st77903初始化代码

`timescale 1ns / 1ps

module qspi_init(
    input clk,
    input rst_n,
    output csx,
    output sck,
    output [3:0] dout,
    output reg rst_o
    );

    parameter CNT1_MAX=50_000_0;
    parameter CNT2_MAX=34;
    parameter CNT3_MAX=50_000_0;     
    reg [19:0] cnt1;    /* generate rst_o and xfer_start */
    reg [9:0]  cnt2;    /* counter init-seq numbers */
    reg [19:0] cnt3;    /* counter init-seq interval */
    
    always @(posedge clk or negedge rst_n)
    if(rst_n==0)
        cnt1<=0;
    else if(add_cnt1) begin
        if(end_cnt1)
            cnt1<=0;
        else
            cnt1<=cnt1+1; 
    end 
    
    always @(posedge clk or negedge rst_n)
    if(rst_n==0)
        cnt2<=0;
    else if(add_cnt2) begin
        if(end_cnt2)
            cnt2<=0;
        else
            cnt2<=cnt2+1; 
    end 
    
     always @(posedge clk or negedge rst_n)
    if(rst_n==0)
        cnt3<=0;
    else if(add_cnt3) begin
        if(end_cnt3)
            cnt3<=0;
        else
            cnt3<=cnt3+1; 
    end    
    
//     always @(posedge clk or negedge rst_n)
//    if(rst_n==0)
//        cnt4<=0;
//    else if(add_cnt4) begin
//        if(end_cnt4)
//            cnt4<=0;
//        else
//            cnt4<=cnt4+1; 
//    end         
    
    assign add_cnt1=cnt1_en; 
    assign end_cnt1=add_cnt1 && (cnt1==CNT1_MAX-1);    
    
    assign add_cnt2=(end_cnt3) && cnt2_en;  
    assign end_cnt2=add_cnt2 && (cnt2==CNT2_MAX-1);    
    
    assign add_cnt3=cnt3_en;
    assign end_cnt3=add_cnt3 && (cnt3==CNT3_MAX-1);     
    
//    assign add_cnt4=cnt4_en;
//    assign end_cnt4=add_cnt4 && (cnt4==CNT4_MAX-1);       
    
    reg cnt1_en;
    reg cnt2_en;
    reg cnt3_en;
//    reg cnt4_en;
    always @(posedge clk or negedge rst_n)
    if(rst_n==0)  
        cnt1_en<=1;
    else if(end_cnt1)
        cnt1_en<=0;  
        
    always @(posedge clk or negedge rst_n)
    if(rst_n==0)  
        cnt2_en<=1;
    else if(end_cnt2)
        cnt2_en<=0;   
        
//   always @(*)
//        cnt3_en=~cnt4_en;
        
    always @(posedge clk or negedge rst_n)
    if(rst_n==0)  
        cnt3_en<=0;      
    else if(end_cnt1)
        cnt3_en<=1;
    else if(end_cnt2)
        cnt3_en<=0;             
        
    always @(posedge clk or negedge rst_n)
    if(rst_n==0)
        rst_o<=0;
    else if(add_cnt1 && (cnt1==CNT1_MAX/2-1))
        rst_o<=1;                            
    
    reg [0: 128*CNT2_MAX-1] rom={
        {8'd2,8'hf0, 8'hc3,{13{8'h00}}},
        {8'd2,8'hf0, 8'h96,{13{8'h00}}},
        {8'd2,8'hf0, 8'ha5,{13{8'h00}}},
        {8'd2,8'he9, 8'h20,{13{8'h00}}},
        {8'd5,8'he7,  8'h80, 8'h77, 8'h1f, 8'hcc,{10{8'h00}}},
        {8'd5,8'hc1,  8'h77, 8'h07, 8'hcf, 8'h16,{10{8'h00}}},//Normal:VGHS/VGLS/VSP/VSN电压
        {8'd5,8'hc2,  8'h77, 8'h07, 8'hcf, 8'h16,{10{8'h00}}},//Idle: VGHS/VGLS/VSP/VSN电压
        {8'd5,8'hc3,  8'h22, 8'h02, 8'h22, 8'h04,{10{8'h00}}},//Normal: VGH/VGL/VSP/VSN Clk
        {8'd5,8'hc4,  8'h22, 8'h02, 8'h22, 8'h04,{10{8'h00}}},//Idle: VGH/VGL/VSP/VSN Clk
        {8'd2,8'hc5,  8'hed,{13{8'h00}}}, //VCOM
        {8'd15,8'he0, 8'h87, 8'h09, 8'h0c, 8'h06, 8'h05, 8'h03, 8'h29, 8'h32, 8'h49, 8'h0f, 8'h1b, 8'h17, 8'h2a, 8'h2f},
        {8'd15,8'he1, 8'h87, 8'h09, 8'h0c, 8'h06, 8'h05, 8'h03, 8'h29, 8'h32, 8'h49, 8'h0f, 8'h1b, 8'h17, 8'h2a, 8'h2f},
        {8'd15,8'he5, 8'hbe, 8'hf5, 8'hb1, 8'h22, 8'h22, 8'h25, 8'h10, 8'h22, 8'h22, 8'h22, 8'h22, 8'h22, 8'h22, 8'h22},
        {8'd15,8'he6, 8'hbe, 8'hf5, 8'hb1, 8'h22, 8'h22, 8'h25, 8'h10, 8'h22, 8'h22, 8'h22, 8'h22, 8'h22, 8'h22, 8'h22},
        {8'd3,8'hec, 8'h40, 8'h03,{12{8'h00}}},
        {8'd2,8'h36,  8'h0c,{13{8'h00}}},
        {8'd2,8'h3a,  8'h07,{13{8'h00}}},
        {8'd2,8'hb2,  8'h00,{13{8'h00}}},//GIP pattern
        {8'd2,8'hb3,  8'h01,{13{8'h00}}},//video mode dot-inversion
        {8'd2,8'hb4,  8'h01,{13{8'h00}}},
        {8'd5,8'hb5,  8'h00, 8'h08, 8'h00, 8'h08,{10{8'h00}}}, //vfp
        {8'd3,8'hb6,  8'hc7, 8'h31,{12{8'h00}}},
        {8'd10,8'ha5,  8'h00, 8'h00, 8'h00, 8'h00, 8'h00, 8'h15, 8'h2a, 8'h8a, 8'h02,{5{8'h00}}},
        {8'd10,8'ha6,  8'h00, 8'h00, 8'h00, 8'h00, 8'h00, 8'h15, 8'h2a, 8'h8a, 8'h02,{5{8'h00}}},
        {8'd8,8'hba,  8'h0a, 8'h5a, 8'h23, 8'h10, 8'h25, 8'h02, 8'h00,{7{8'h00}}},
        {8'd9,8'hbb,  8'h00, 8'h30, 8'h00, 8'h2c, 8'h82, 8'h87, 8'h18, 8'h00,{6{8'h00}}},
        {8'd9,8'hbc,  8'h00, 8'h30, 8'h00, 8'h2c, 8'h82, 8'h87, 8'h18, 8'h00,{6{8'h00}}},
        {8'd12,8'hbd, 8'ha1, 8'hb2, 8'h2b, 8'h1a, 8'h56, 8'h43, 8'h34, 8'h65, 8'hff, 8'hff, 8'h0f,{3{8'h00}}},
        {8'd2,8'h35,  8'h00,{13{8'h00}}},
        {8'd1,8'h21,{14{8'h00}}},
        {8'd1,8'h11,{14{8'h00}}},
        {8'd1,8'h29,{14{8'h00}}},
        {8'd2,8'hb0,  8'ha5,{13{8'h00}}},
        {8'd10,8'hcc,  8'h40, 8'h00, 8'h3f, 8'h00, 8'h14, 8'h14, 8'h20, 8'h20, 8'h03,{5{8'h00}}}
    };

    
    reg xfer_start;
    wire xfer_final;
    wire [3:0] dout;

    reg [0:127] cmd_line;   
    reg [7:0] cmd;
    reg [23:0] addr;
    reg [0:127] din; 
    reg [10:0]  vadid_length;  /* Max suppport DATA_SIZE=2047*8=16376 */   
    reg [1:0] data_mode;  /*00: cmd, 01: cmd+addr, 10: cmd+addr+1wire data, 11: cmd+addr+4wire data*/ 
    reg  cs_mode;  /*IDLE state, 0: cs=0, 1:cs=1, to support multi data_bursts while keep cs=0*/  
    
    always @(posedge clk or negedge rst_n)
    if(rst_n==0)
        xfer_start<=0;
    else if((end_cnt1 || end_cnt3) && cnt2<CNT2_MAX-1)
        xfer_start<=1;
    else
        xfer_start<=0;    
   

    always @(*)
        if(cnt2<CNT2_MAX)
            cmd_line=rom[128*cnt2 +:128];
        else
            cmd_line=0;
     
     always @(*) begin
        vadid_length=cmd_line[0:7]-1;
        cmd=8'hde;
        addr={8'h00, cmd_line[8:15], 8'h00};
        din={cmd_line[16:127], 16'h0};
        data_mode=(vadid_length==0)? 2'b01: 2'b11;
        cs_mode=1;
     end
        
qspi2  #(.DATA_SIZE(128)) qspi2_inst(
   // Input Ports - Single Bit
   .clk                (clk),             
   .cs_mode            (cs_mode),         
   .rst_n              (rst_n),           
   .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
);
                       
          
endmodule

D3 st77903刷图代码

`timescale 1ns / 1ps

module qspi_fillcolor(
    input clk,
    input rst_n,
    
    input start_pulse,
    output csx,
    output sck,
    output [3:0] dout,
    output vs,
    output hs
    );
    
    parameter LCD_BPP=24;
    parameter LCD_X_SIZE=400;
    parameter LCD_Y_SIZE=400;
    parameter LCD_PBYTE=(LCD_BPP+0)/8;
    parameter LCD_HBYTE=(LCD_X_SIZE * LCD_PBYTE);
    parameter LCD_VSW=1;
    parameter LCD_HFP=8;
    parameter LCD_HBP=8;   
    

    parameter CNT1_MAX=4880;  //line_cycles(精确值是4871)
    parameter CNT2_MAX=LCD_VSW+LCD_HBP+LCD_Y_SIZE+LCD_HFP; 
    parameter CNT3_MAX=LCD_HBYTE;
    reg [19:0]  cnt1;
    reg [10:0]  cnt2;  /*总行数计数器*/
    
    always @(posedge clk or negedge rst_n)
    if(rst_n==0)
        cnt1<=0;
    else if(add_cnt1) begin
        if(end_cnt1)
            cnt1<=0;
        else
            cnt1<=cnt1+1; 
    end 
    
    always @(posedge clk or negedge rst_n)
    if(rst_n==0)
        cnt2<=0;
    else if(add_cnt2) begin
        if(end_cnt2)
            cnt2<=0;
        else
            cnt2<=cnt2+1; 
    end         
    
    assign add_cnt1=cnt1_en;                                //有条件的计数,因此有计数使能, 一行的定时计数器
    assign end_cnt1=add_cnt1 && (cnt1==CNT1_MAX-1);    
    
    assign add_cnt2=end_cnt1;   
    assign end_cnt2=add_cnt2 && (cnt2==CNT2_MAX-1);      
       
    
    reg cnt1_en;
    always @(posedge clk or negedge rst_n)
    if(rst_n==0)  
        cnt1_en<=0;
    else if(start_pulse)
        cnt1_en<=1;
    
    reg xfer_start;
    always @(posedge clk or negedge rst_n)
    if(rst_n==0) 
        xfer_start<=0;
//    else if(start_pulse || xfer_rdy &&end_cnt1)
    else if(add_cnt1 && (cnt1==0))
        xfer_start<=1;
    else
        xfer_start<=0;

    wire [7:0] cmd;
    reg [23:0] addr;
    reg [0:9600-1] din; 
    reg [10:0]  vadid_length;  /* Max suppport DATA_SIZE=2047*8=16376 */   
    reg [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*/       
    
    assign cmd=8'hde;
    assign cs_mode=1;
    
    always @(posedge clk or negedge rst_n)
    if(rst_n==0) begin
        addr<=24'h0;
        data_mode<=2'b01;
        vadid_length<=0;   
    end  
    else if(cnt2>=0 && cnt2<LCD_VSW) begin
        addr<={8'h00, 8'h61, 8'h00};
        data_mode<=2'b01;
        vadid_length<=0;
    end
    else if(cnt2>=LCD_VSW && cnt2<LCD_VSW+LCD_HBP) begin 
        addr<={8'h00, 8'h60, 8'h00};    
        data_mode<=2'b01;
        vadid_length<=0;        
    end
    else if(cnt2>=LCD_VSW+LCD_HBP && cnt2<LCD_VSW+LCD_HBP+LCD_Y_SIZE) begin 
        addr<={8'h00, 8'h60, 8'h00};    
        data_mode<=2'b11;
        vadid_length<=400*3;        
    end 
    else if(cnt2>=LCD_VSW+LCD_HBP+LCD_Y_SIZE && cnt2<LCD_VSW+LCD_HBP+LCD_Y_SIZE+LCD_HFP) begin 
        addr<={8'h00, 8'h60, 8'h00};    
        data_mode<=2'b01;
        vadid_length<=0;        
    end       
    
    //在这里定义图像    
    always @(posedge clk or negedge rst_n)
    if(rst_n==0) begin
         din<={400{24'h000000}};
    end
    else if(cnt2>=LCD_VSW+LCD_HBP && cnt2< LCD_VSW+LCD_HBP+LCD_Y_SIZE/3) begin
         din<={400{24'hff0000}};  //r
    end
    else if(cnt2>= LCD_VSW+LCD_HBP+LCD_Y_SIZE/3 && cnt2<LCD_VSW+LCD_HBP+LCD_Y_SIZE*2/3) begin
         din<={400{24'h00ff00}};  //g    
    end
    else if(cnt2>= LCD_VSW+LCD_HBP+LCD_Y_SIZE*2/3 && cnt2<LCD_VSW+LCD_HBP+LCD_Y_SIZE*3/3) begin
         din<={400{24'h0000ff}};  //b               
    end
    else
         din<={400{24'h000000}}; 
         
   assign vs=add_cnt2 && (cnt2==0);
   assign hs=add_cnt1 && (cnt1==0);  
           

qspi2  #(.DATA_SIZE(9600)) qspi2_inst(
   // Input Ports - Single Bit
   .clk                (clk),             
   .cs_mode            (cs_mode),         
   .rst_n              (rst_n),           
   .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
);
            
endmodule

D4 top总拼代码

`timescale 1ns / 1ps

module qspi_init_and_fillcolor(
    input clk,
    input rst_n,
    
    input bist_mode_en,
    
    output csx,
    output sck,
    output [3:0] dout,
    output rst_o,
    
    output vs,
    output hs
    );
    
    parameter CNT1_MAX=50_000_000; 
    reg [31:0] cnt1;
    
    always @(posedge clk or negedge rst_n)
    if(rst_n==0)
        cnt1<=0;
    else if(add_cnt1) begin
        if(end_cnt1)
            cnt1<=0;
        else
            cnt1<=cnt1+1; 
    end  
 
    assign add_cnt1=cnt1_en;         //有条件的计数,因此有计数使能
    assign end_cnt1=add_cnt1 && (cnt1==CNT1_MAX-1);    
       
    reg cnt1_en;
    always @(posedge clk or negedge rst_n)
    if(rst_n==0)  
        cnt1_en<=1;
    else if(end_cnt1)
        cnt1_en<=0;  
    
    assign start_pulse=end_cnt1; 
    
    wire [3:0] dout1;
    wire [3:0] dout2;
    
    assign csx=(cnt1_en)? csx1: csx2;
    assign sck=(cnt1_en)? sck1: sck2;  
    assign dout=(cnt1_en)? dout1:dout2;        

//qspi_init qspi_init_inst(    
qspi_init qspi_init_inst(
    .clk(clk),
    .rst_n(rst_n),

    .bist_mode_en(bist_mode_en),
    .csx(csx1),
    .sck(sck1),
    .dout(dout1),
    .rst_o(rst_o)    
    );    
//    defparam qspi_init_inst.CNT1_MAX=1000;
//    defparam qspi_init_inst.CNT4_MAX=100;
    
qspi_fillcolor qspi_fillcolor_inst(
    .clk(clk),
    .rst_n(rst_n),
    
    .start_pulse(start_pulse),
    .csx(csx2),
    .sck(sck2),
    .dout(dout2),
    .vs(vs),
    .hs(hs) 
    );    
//    defparam qspi_fillcolor_inst.LCD_X_SIZE=40;
//    defparam qspi_fillcolor_inst.LCD_Y_SIZE=40;        
endmodule

D5 测试代码

`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer: 
// 
// Create Date: 2024/03/31 12:44:53
// Design Name: 
// Module Name: tb
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//////////////////////////////////////////////////////////////////////////////////


//module tb;
//    reg clk, rst_n;
//    initial clk=0;
//    always #10 clk=~clk;
//    initial begin
//        rst_n=0;
//        #1000;
//        rst_n=1;
//    end 

//    reg xfer_start;
//    reg [7:0] cmd;
//    reg [23:0] addr;
//    reg [191:0] din; 
//    reg [6:0]  current_vadid_length;
//    reg [17:0] total_length;
//    reg [1:0] data_mode;
//    wire [3:0] dout;    
    
//    initial begin
//        xfer_start=0;
//        cmd=8'h00;
//        addr=24'hf0000f;
//        din=8'h00;
//        current_vadid_length=0;
//        total_length=0;
//        data_mode=2'b00;
        
//        wait(rst_n==1);
//        #1000;
        
//        //send command only
//        current_vadid_length=0;
//        total_length=0;
//        data_mode=2'b00;     
//        cmd=8'hf0;          
//        @(posedge clk) #1 xfer_start=1;
//        @(posedge clk) #1 xfer_start=0; 
//        wait(xfer_final==1);
//        #100;
  
//        //send command+addr
//        current_vadid_length=3;
//        total_length=3;
//        data_mode=2'b01; 
//        cmd=8'hf0; 
//        @(posedge clk) #1 xfer_start=1;
//        @(posedge clk) #1 xfer_start=0;          
//        wait(xfer_final==1);
//        #100;
        
//        //send command+addr+data, 1wire mode             
//        current_vadid_length=3;
//        total_length=3;
//        data_mode=2'b10; 
//        cmd=8'hf0; 
//        din={24'hf0f0f0,168'b0}; 
//        @(posedge clk) #1 xfer_start=1;
//        @(posedge clk) #1 xfer_start=0;          
//        wait(xfer_final==1);
//        #100;
  
//         //send command+addr+data, 4wire mode          
//        current_vadid_length=24;
//        total_length=40;
//        data_mode=2'b10; 
//        cmd=8'h23; 
//        din={12{16'h1234}}; 
//        @(posedge clk) #1 xfer_start=1;
//        @(posedge clk) #1 xfer_start=0;          
//        wait(xfer_end==1); 
//        #100;
        
//        current_vadid_length=16;
//        din={12{16'h5678}}; 
//        @(posedge clk) #1 xfer_start=1;
//        @(posedge clk) #1 xfer_start=0;          
//        wait(xfer_final==1);  
//        #1;                            
    
//    end
    
//    qspi qspi_inst(
//        .clk(clk),
//        .rst_n(rst_n),
        
//        .xfer_start(xfer_start),
//        .xfer_end(xfer_end),
//        .xfer_final(xfer_final),
//        .xfer_rdy(xfer_rdy),        
        
//        .cmd(cmd),
//        .addr(addr),
//        .din(din),
//        .current_vadid_length(current_vadid_length),
//        .total_length(total_length),
//        .data_mode(data_mode),
        
//        .csx(csx),
//        .sck(sck),
//        .dout(dout)
//        );


//endmodule


module tb;
    reg clk, rst_n;
    initial clk=0;
    always #10 clk=~clk;
    initial begin
        rst_n=0;
        #1000;
        rst_n=1;
    end 

    reg xfer_start;
    reg [7:0] cmd;
    reg [23:0] addr;
    reg [9600-1:0] din; 
    reg [10:0]  vadid_length;
    reg [1:0] data_mode;
    reg cs_mode;
    wire [3:0] dout;    
    
    initial begin
        xfer_start=0;
        cmd=8'h00;
        addr=24'h000000;
        din=8'h00;
        vadid_length=0;
        data_mode=2'b00;
        cs_mode=1;
        
        wait(rst_n==1);
        #1000;
        
        //send command only
        data_mode=2'b00;     
        cmd=8'hf0;          
        @(posedge clk) #1 xfer_start=1;
        @(posedge clk) #1 xfer_start=0; 
        wait(xfer_final==1);
        #100;
  
        //send command+addr
        data_mode=2'b01; 
        cmd=8'hf0; 
        addr=24'hf0f0f0;        
        @(posedge clk) #1 xfer_start=1;
        @(posedge clk) #1 xfer_start=0;          
        wait(xfer_final==1);
        #100;
        
        //send command+addr+data, 1wire mode             
        vadid_length=3;
        data_mode=2'b10; 
        cmd=8'hf0; 
        addr=24'hf0f0f0;             
        din={24'hf0f0f0,9576'b0}; 
        @(posedge clk) #1 xfer_start=1;
        @(posedge clk) #1 xfer_start=0;          
        wait(xfer_final==1);
        #100;
  
         //send command+addr+data, 4wire mode          
        vadid_length=700;
        data_mode=2'b11; 
        cs_mode=0;        
        cmd=8'h23; 
        addr=24'hf0f0f0;         
        din={600{16'h1234}}; 
        @(posedge clk) #1 xfer_start=1;
        @(posedge clk) #1 xfer_start=0;          
        wait(xfer_final==1); 
        #100;  
        
         //send command+addr+data, 4wire mode          
        vadid_length=700;
        data_mode=2'b11; 
        cs_mode=1;        
        cmd=8'h23; 
        addr=24'hf0f0f0;         
        din={600{16'h4321}}; 
        @(posedge clk) #1 xfer_start=1;
        @(posedge clk) #1 xfer_start=0;          
        wait(xfer_final==1); 
        #100;                              
    
    end
    
    qspi2 qspi_inst(
        .clk(clk),
        .rst_n(rst_n),
        
        .xfer_start(xfer_start),
        .xfer_final(xfer_final),
        .xfer_rdy(xfer_rdy),        
        
        .cmd(cmd),
        .addr(addr),
        .din(din),
        .vadid_length(vadid_length),
        .data_mode(data_mode),
        .cs_mode(cs_mode),
        
        .csx(csx),
        .sck(sck),
        .dout(dout)
        );


endmodule


module tb2;
    reg clk, rst_n;
    initial clk=0;
    always #10 clk=~clk;
    initial begin
        rst_n=0;
        #1000;
        rst_n=1;
    end 
    
qspi_init qspi_init_inst(
    .clk(clk),
    .rst_n(rst_n)
    );    
    defparam qspi_init_inst.CNT1_MAX=1000;
    defparam qspi_init_inst.CNT3_MAX=200;    
endmodule


module tb3;
    reg clk, rst_n;
    initial clk=0;
    always #10 clk=~clk;
    initial begin
        rst_n=0;
        #1000;
        rst_n=1;
    end 
    
    bit start_pulse;
    initial begin
        start_pulse=0;
        #5000;
        @(posedge clk) #1 start_pulse=1;
        @(posedge clk) #1 start_pulse=0;        
    end
    
qspi_fillcolor qspi_fillcolor_inst(
    .clk(clk),
    .rst_n(rst_n),
    .start_pulse(start_pulse)
    );    
    defparam qspi_fillcolor_inst.LCD_X_SIZE=40;
    defparam qspi_fillcolor_inst.LCD_Y_SIZE=40;    
endmodule


module tb4;
    reg clk, rst_n;
    initial clk=0;
    always #10 clk=~clk;
    initial begin
        rst_n=0;
        #1000;
        rst_n=1;
    end 
    
qspi_init_and_fillcolor qspi_init_and_fillcolor_inst(
    .clk(clk),
    .rst_n(rst_n)
    );    
    defparam qspi_init_and_fillcolor_inst.CNT1_MAX=50_000;
    defparam qspi_init_and_fillcolor_inst.qspi_init_inst.CNT1_MAX=1000;
    defparam qspi_init_and_fillcolor_inst.qspi_init_inst.CNT4_MAX=100;
    defparam qspi_init_and_fillcolor_inst.qspi_fillcolor_inst.LCD_X_SIZE=400;
    defparam qspi_init_and_fillcolor_inst.qspi_fillcolor_inst.LCD_Y_SIZE=40; 
endmodule