初级会员
积分 103
金钱 103
注册时间 2021-1-30
在线时间 68 小时
10 金钱
本帖最后由 LJY344500 于 2021-3-13 16:43 编辑
我看别的板子上spi flash的全擦除实验试着自己改一下,编译都没有问题,接到电脑上后串口助手不会显示数据,求大佬指点一下哪里出问题了 ,我把文件上传了,救救孩子
顶层模块:
module spi
(
input wire sys_clk , //系统时钟,频率50MHz
input wire sys_rst_n , //复位信号,低电平有效
input wire pi_key , //按键输入信号
output wire txd //输出
);
//********************************************************************//
//****************** Parameter and Internal Signal *******************//
//********************************************************************//
//parameter define
parameter CNT_MAX = 20'd999_999; //计数器计数最大值
parameter UART_BPS = 14'd9600 , //比特率
CLK_FREQ = 26'd50_000_000 ; //时钟频率
//wire define
wire po_key ;
wire [7:0] mosi_w ;
wire sck_w ;
wire cs_n_w ;
//********************************************************************//
//*************************** Instantiation **************************//
//********************************************************************//
//------------- key_filter_inst -------------
key_filter
#(
.CNT_MAX (CNT_MAX ) //计数器计数最大值
)
key_filter_inst
(
.sys_clk (sys_clk ), //系统时钟,频率50MHz
.sys_rst_n (sys_rst_n ), //复位信号,低电平有效
.key_in (pi_key ), //按键输入信号
.key_flag (po_key ) //消抖后信号
);
//------------- flash_be_ctrl_inst -------------
master master_inst
(
.sys_clk (sys_clk ), //系统时钟,频率50MHz
.sys_rst_n (sys_rst_n ), //复位信号,低电平有效
.key (po_key ), //按键输入信号
.sck (sck_w ), //片选信号
.cs_n (cs_n_w ), //串行时钟
.mosi (mosi_w ) //主输出从输入数据
);
slave
#(
.UART_BPS (UART_BPS ), //串口波特率
.CLK_FREQ (CLK_FREQ ) //时钟频率
)
slave_inst
(
.cs_n_in (cs_n_w ) , //片选信号
.sck_in (sck_w ) , //串行时钟
.mosi_in (mosi_w ) , //主输出从输入数据
.txd (txd ) //输出
);
endmodule
按键消抖模块:
module key_filter
#(
parameter CNT_MAX = 20'd999_999 //计数器计数最大值
)
(
input wire sys_clk , //系统时钟50Mhz
input wire sys_rst_n , //全局复位
input wire key_in , //按键输入信号
output reg key_flag //key_flag为1时表示消抖后检测到按键被按下
//key_flag为0时表示没有检测到按键被按下
);
//********************************************************************//
//****************** Parameter and Internal Signal *******************//
//********************************************************************//
//reg define
reg [19:0] cnt_20ms ; //计数器
//********************************************************************//
//***************************** Main Code ****************************//
//********************************************************************//
//cnt_20ms:如果时钟的上升沿检测到外部按键输入的值为低电平时,计数器开始计数
always@(posedge sys_clk or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
cnt_20ms <= 20'b0;
else if(key_in == 1'b1)
cnt_20ms <= 20'b0;
else if(cnt_20ms == CNT_MAX && key_in == 1'b0)
cnt_20ms <= cnt_20ms;
else
cnt_20ms <= cnt_20ms + 1'b1;
//key_flag:当计数满20ms后产生按键有效标志位
//且key_flag在999_999时拉高,维持一个时钟的高电平
always@(posedge sys_clk or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
key_flag <= 1'b0;
else if(cnt_20ms == CNT_MAX - 1'b1)
key_flag <= 1'b1;
else
key_flag <= 1'b0;
endmodule
主机发送:
module master
(
input wire sys_clk , //系统时钟,频率50MHz
input wire sys_rst_n , //复位信号,低电平有效
input wire key , //按键输入信号
output reg cs_n , //片选信号
output reg sck , //串行时钟
output reg mosi //主输出从输入数据
);
//********************************************************************//
//****************** Parameter and Internal Signal *******************//
//********************************************************************//
//parameter define
parameter IDLE = 2'b01 , //初始状态
WR_EN = 4'b10 ; //写状态
parameter WR_EN_INST = 8'b0000_0110; //写使能指令
//reg define
reg [1:0] cnt_byte; //字节计数器,0-2计数
reg [1:0] state ; //状态机状态,2个状态
reg [4:0] cnt_clk ; //系统时钟计数器,0-31循环计数
reg [1:0] cnt_sck ; //串行时钟计数器,0-3计数
reg [2:0] cnt_bit ; //比特计数器
//********************************************************************//
//***************************** Main Code ****************************//
//********************************************************************//
//cnt_clk:系统时钟计数器,用以记录单个字节,不用修改
always@(posedge sys_clk or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
cnt_clk <= 5'd0;
else if(state != IDLE)
cnt_clk <= cnt_clk + 1'b1;
//cnt_byte:记录输出字节个数和等待时间,ok
always@(posedge sys_clk or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
cnt_byte <= 3'd0;
else if((cnt_clk == 5'd31) && (cnt_byte == 2'd2))
cnt_byte <= 3'd0;
else if(cnt_clk == 31)
cnt_byte <= cnt_byte + 1'b1;
//cnt_sck:串行时钟计数器,用以生成串行时钟,ok
always@(posedge sys_clk or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
cnt_sck <= 2'd0;
else if((state == WR_EN) && (cnt_byte == 1'b1)) //处于写状态并且字节计数器等于1,开始计数
cnt_sck <= cnt_sck + 1'b1;
//cs_n:片选信号,ok
always@(posedge sys_clk or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
cs_n <= 1'b1;
else if(key == 1'b1)
cs_n <= 1'b0;
else if((cnt_byte == 3'd2) && (cnt_clk == 5'd31) && (state == WR_EN))
cs_n <= 1'b1;
//sck:输出串行时钟
always@(posedge sys_clk or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
sck <= 1'b0;
else if(cnt_sck == 2'd0)
sck <= 1'b0;
else if(cnt_sck == 2'd2)
sck <= 1'b1;
//cnt_bit:高低位对调,控制mosi输出
always@(posedge sys_clk or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
cnt_bit <= 3'd0;
else if(cnt_sck == 2'd2)
cnt_bit <= cnt_bit + 1'b1;
//state:两段式状态机第一段,状态跳转,ok
always@(posedge sys_clk or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
state <= IDLE;
else
case(state)
IDLE: if(key == 1'b1)
state <= WR_EN;
WR_EN: if((cnt_byte == 2'd2) && (cnt_clk == 5'd31))
state <= IDLE;
default: state <= IDLE;
endcase
//mosi:两段式状态机第二段,逻辑输出
always@(posedge sys_clk or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
mosi <= 1'b0;
else if((state == WR_EN) && (cnt_byte == 2'd2))
mosi <= 1'b0;
else if((state == WR_EN) && (cnt_byte == 2'd1) && (cnt_sck == 5'd0))
mosi <= WR_EN_INST[7 - cnt_bit]; //写使能指令
endmodule
从机模块:
module slave
#(
parameter UART_BPS = 'd9600, //串口波特率
parameter CLK_FREQ = 'd50_000_000 //时钟频率
)
(
input cs_n_in , //片选信号
input sck_in , //串行时钟
input wire [7:0] mosi_in , //主输出从输入数据
output reg txd //输出
);
reg[3:0] Data_State = 4'd0;
parameter D7_State = 4'd0;
parameter D6_State = 4'd1;
parameter D5_State = 4'd2;
parameter D4_State = 4'd3;
parameter D3_State = 4'd4;
parameter D2_State = 4'd5;
parameter D1_State = 4'd6;
parameter D0_State = 4'd7;
always@(posedge sck_in)
if(cs_n_in == 1'b1)
txd <= 1'b1; //空闲状态时为高电平
else if(cs_n_in == 1'b0)
case(Data_State)
D7_State:begin txd <= mosi_in[0]; Data_State<= D6_State;end
D6_State:begin txd <= mosi_in[1]; Data_State<= D5_State;end
D5_State:begin txd <= mosi_in[2]; Data_State<= D4_State;end
D4_State:begin txd <= mosi_in[3]; Data_State<= D3_State;end
D3_State:begin txd <= mosi_in[4]; Data_State<= D2_State;end
D2_State:begin txd <= mosi_in[5]; Data_State<= D1_State;end
D1_State:begin txd <= mosi_in[6]; Data_State<= D0_State;end
D0_State:begin txd <= mosi_in[7]; Data_State<= D7_State;end
default : txd <= 1'b1;
endcase
endmodule
我来回答