Skip to content

fpga项目: st7796 spi接口

minichao9901 edited this page Dec 8, 2023 · 1 revision

1)st7796 40pin fpc接口介绍

image image


  • 我们选择spi 4w接口模式,因为im[2:0]要设置为3'b111
  • 用的是我自己做的FPGA扩展板。将扩展板的fpc接口列在excel表里,再将模组的excel表列在excel表里一一对应,然后用excel的公式自动生成引脚约束文件,这样免去了手工抄写的繁琐和易错。

image

2)先写一个简单的spi接口,测试一下spi接口的简单写操作

  • 这个测试比较简单,就发了2个命令:11和29。正常情况下,st7796屏幕会打开显示,进入雪花屏状态。实际测试确认如此。
  • spi.v的写法,采用了clk的上升沿和下降沿实现的。在下降沿准备数据,在上升沿拉时钟。
  • spi时钟与输入时钟同频率,因此不得不用下降沿。spi时钟用组合逻辑产生(可能有毛刺,不过由于fpga门延时非常大,到输出毛刺都被过滤掉了)。
  • 代码层次化结构如下,包含3个.v文件
    image
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer: 
// 
// Create Date: 2023/12/06 09:23:08
// Design Name: 
// Module Name: spi
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//////////////////////////////////////////////////////////////////////////////////

module spi(
    input clk,
    input rst_n,
    
    input pi_start_pulse,
    input [7:0] pi_cmd,
//    input [15:0] pi_data0,        
//    input [19:0] pi_nbytes,    
    
    output reg csx,
    output reg dcx,
    output sck,
    output reg mosi
    );

reg [3:0] timer0;
reg [3:0] timer1;
reg start_pulse_d;
reg work_en;


//timer0
always @(posedge clk or negedge rst_n)
if(rst_n==0)
    timer0<=0;
else if(pi_start_pulse || timer0==8)
    timer0<=0;
else if(csx==0)
    timer0<=timer0+1;

//timer1
always @(negedge clk or negedge rst_n)
if(rst_n==0) begin
    timer1<=0;
    start_pulse_d<=0;
end
else begin
    timer1<=timer0;
    start_pulse_d<=pi_start_pulse;
end

//csx
always @(negedge clk or negedge rst_n)
if(rst_n==0)
    csx<=1;
else if(start_pulse_d)
    csx<=0;
else if(timer1==8)
    csx<=1;

//dcx
always @(negedge clk or negedge rst_n)
if(rst_n==0)
    dcx<=0;
else if(start_pulse_d)
    dcx<=0;
else if(timer1==8)
    dcx<=1;
    
//mosi
always @(negedge clk or negedge rst_n)
if(rst_n==0)
    mosi<=0;
else if(csx==0 && timer1<=7)
    mosi<=pi_cmd[7-timer1];
else if(csx==0 && timer1==7)
    mosi<=0;    

assign sck=(timer1>=1)? clk:0;
    
endmodule
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer: 
// 
// Create Date: 2023/12/06 09:48:51
// Design Name: 
// Module Name: timer_gen_seqs
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//////////////////////////////////////////////////////////////////////////////////
module gen_timer_seqs(
    input clk,
    input rst_n,
    input [9:0] event_max_value,
    
    output [9:0] event_o
);

parameter FCLK=27_000_000;
parameter DLY_10MS=FCLK/100; 

reg [25:0] timer;
always @(posedge clk or negedge rst_n)
if(rst_n==0)
    timer<=0;
else
    timer<=timer+1;

reg timer_flag;
always @(posedge clk or negedge rst_n)
if(rst_n==0)
    timer_flag<=0;
else if(timer%DLY_10MS==0)
    timer_flag<=1;
else
    timer_flag<=0;
    
reg [9:0] event_t;
always @(posedge clk or negedge rst_n)
if(rst_n==0)
    event_t<=0;
else if(event_t==event_max_value)
    event_t<=0;
else if(timer_flag)
    event_t<=event_t+1;

assign event_o=timer_flag? event_t: 10'd0;  //generate counter-value pulse

endmodule
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer: 
// 
// Create Date: 2023/12/06 09:38:49
// Design Name: 
// Module Name: tb_spi
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//////////////////////////////////////////////////////////////////////////////////


module spi_st7796(
    input clk,
    input rst,

    output csx,
    output dcx,
    output sck,
    output mosi,
    output rst_o,
    output [2:0] im
    );


assign rst_n=~rst;
assign rst_o=rst_n;
assign im=3'b111;


reg pi_start_pulse;
reg [7:0] pi_cmd;
wire [9:0] event_o;

always @(posedge clk or negedge rst_n)
if(rst_n==0) begin
    pi_start_pulse<=0;
    pi_cmd<=8'h00;
end
else case(event_o)
    2:  begin
    pi_start_pulse<=1;
    pi_cmd<=8'h11;   
end
    3:  begin
    pi_start_pulse<=1;
    pi_cmd<=8'h29;   
end
    default:
    pi_start_pulse<=0;
endcase 
 
spi u_spi(
    .clk(clk),
    .rst_n(rst_n),
    
    .pi_start_pulse(pi_start_pulse),
    .pi_cmd(pi_cmd),
    
    .csx(csx),
    .dcx(dcx),
    .sck(sck),
    .mosi(mosi)
    ); 

gen_timer_seqs 
//#( .FCLK(27_00)
u_gen_timer_seqs(
    .clk(clk),
    .rst_n(rst_n),
    .event_max_value(4),
    
    .event_o(event_o)
);

endmodule

3)引脚约束文件

//IO_LOC "clk" 10;  //30MHz
IO_LOC "clk" 11;  //5MHz
IO_LOC "rst" 88;

IO_LOC "im[2]" 73;
IO_LOC "im[1]" 74;
IO_LOC "im[0]" 75;


IO_LOC "rst_o" 79;
//IO_LOC "miso" 17;
IO_LOC "mosi" 20;

IO_LOC "sck" 72;
IO_LOC "dcx" 18;
IO_LOC "csx" 71;
Clone this wiki locally