fpga项目: st7796 spi接口 - minichao9901/TangNano-20k-Zynq-7020 GitHub Wiki
1)st7796 40pin fpc接口介绍
- 我们选择spi 4w接口模式,因为im[2:0]要设置为3'b111
- 用的是我自己做的FPGA扩展板。将扩展板的fpc接口列在excel表里,再将模组的excel表列在excel表里一一对应,然后用excel的公式自动生成引脚约束文件,这样免去了手工抄写的繁琐和易错。
2)先写一个简单的spi接口,测试一下spi接口的简单写操作
- 这个测试比较简单,就发了2个命令:11和29。正常情况下,st7796屏幕会打开显示,进入雪花屏状态。实际测试确认如此。
- spi.v的写法,采用了clk的上升沿和下降沿实现的。在下降沿准备数据,在上升沿拉时钟。
- spi时钟与输入时钟同频率,因此不得不用下降沿。spi时钟用组合逻辑产生(可能有毛刺,不过由于fpga门延时非常大,到输出毛刺都被过滤掉了)。
- 代码层次化结构如下,包含3个.v文件
`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;