SPI基础代码模版
user输入: valid信号 , 要输出的值
输出 :一个周期读valid , 读到的值
module spi_drive#(
parameter P_DATA_WIDTH = 8 ,
P_READ_DATA_WIDTH = 8 ,
P_CPOL = 0 ,
P_CPHL = 0
)(
input i_clk ,
input i_rst ,
output o_spi_clk ,
output o_spi_cs ,
output o_spi_mosi ,
input i_spi_miso ,
input [P_DATA_WIDTH - 1 :0] i_user_data ,
input i_user_valid ,
output o_user_ready ,
output [P_READ_DATA_WIDTH - 1:0] o_user_read_data ,
output o_user_read_valid
);
reg ro_spi_clk ;
reg ro_spi_cs ;
reg ro_spi_mosi ;
reg ro_user_ready ;
reg [P_DATA_WIDTH - 1:0] r_user_data ;
reg r_run ;
reg [15:0] r_cnt ;
reg r_spi_cnt ;
reg [P_READ_DATA_WIDTH - 1:0] ro_user_read_data ;
reg ro_user_read_valid ;
reg r_run_1d ;
/***************wire******************/
wire w_user_active ;
wire w_run_negedge ;
/***************assign****************/
assign o_spi_clk = ro_spi_clk ;
assign o_spi_cs = ro_spi_cs ;
assign o_spi_mosi = ro_spi_mosi ;
assign o_user_ready = ro_user_ready ;
assign o_user_read_data = ro_user_read_data ;
assign o_user_read_valid = ro_user_read_valid ;
assign w_run_negedge = !r_run & r_run_1d ;
/***************always****************/
assign w_user_active = i_user_valid & o_user_ready;
always@(posedge i_clk,posedge i_rst)
begin
if(i_rst)
ro_user_ready <='d1;
else if(w_user_active)
ro_user_ready <= 'd0;
else if(w_run_negedge)
ro_user_ready <= 'd1;
else
ro_user_ready <= ro_user_ready;
end
always@(posedge i_clk,posedge i_rst)
begin
if(i_rst)
r_user_data <= 'd0;
else if(w_user_active)
r_user_data <= i_user_data;
else if(r_spi_cnt)
r_user_data <= r_user_data << 1;
else
r_user_data <= r_user_data;
end
always@(posedge i_clk,posedge i_rst)
begin
if(i_rst)
r_run <= 'd0;
else if(r_spi_cnt && r_cnt == 7)
r_run <= 'd0;
else if(w_user_active)
r_run <= 'd1;
else
r_run <= r_run;
end
always@(posedge i_clk,posedge i_rst)
begin
if(i_rst)
r_run_1d <= 'd0;
else
r_run_1d <= r_run;
end
always@(posedge i_clk,posedge i_rst)
begin
if(i_rst)
r_cnt <= 'd0;
else if(r_spi_cnt && r_cnt == 7)
r_cnt <= 'd0;
else if(r_spi_cnt)
r_cnt <= r_cnt + 1;
else
r_cnt <= r_cnt;
end
always@(posedge i_clk,posedge i_rst)
begin
if(i_rst)
r_spi_cnt <= 'd0;
else if(r_run)
r_spi_cnt <= r_spi_cnt + 1;
else
r_spi_cnt <= 'd0;
end
always@(posedge i_clk,posedge i_rst)
begin
if(i_rst)
ro_spi_clk <= P_CPOL;
else if(r_run)
ro_spi_clk <= ~ro_spi_clk;
else
ro_spi_clk <= P_CPOL;
end
always@(posedge i_clk,posedge i_rst)
begin
if(i_rst)
ro_spi_cs <= 'd1;
else if(w_user_active)
ro_spi_cs <= 'd0;
else if(!r_run)
ro_spi_cs <= 'd1;
else
ro_spi_cs <= ro_spi_cs;
end
always@(posedge i_clk,posedge i_rst)
begin
if(i_rst)
ro_spi_mosi <= 'd0;
else if(w_user_active)
ro_spi_mosi <= i_user_data[P_DATA_WIDTH - 1];
else if(r_spi_cnt)
ro_spi_mosi <= r_user_data[P_DATA_WIDTH - 2];
else
ro_spi_mosi <= ro_spi_mosi;
end
always@(posedge ro_spi_clk,posedge i_rst)
begin
if(i_rst)
ro_user_read_data <= 'd0;
else
ro_user_read_data <= {ro_user_read_data[P_DATA_WIDTH - 2 : 0],i_spi_miso};
end
always@(posedge i_clk,posedge i_rst)
begin
if(i_rst)
ro_user_read_valid <= 'd0;
else if(r_spi_cnt && r_cnt == 7)
ro_user_read_valid <= 'd1;
else
ro_user_read_valid <= 'd0;
end
endmodule
1. SPI协议与芯片交互接口
实际上就是加入了(芯片命令cmd + 寄存器地址) 的数据。读写操作的位数可以由spi控制器来控制,用于完成各种spi协议芯片的读写任务。
读数据
写数据
module spi_drive#(
parameter P_DATA_WIDTH = 8 ,
P_OP_LEN = 32,
P_READ_DATA_WIDTH = 8 ,
P_CPOL = 0 ,
P_CPHL = 0
)(
input i_clk ,//系统时钟
input i_rst ,//复位
//spi驱动
output o_spi_clk ,//spi的clk
output o_spi_cs ,//spi的片选
output o_spi_mosi ,//spi的主机输出
input i_spi_miso ,//spi的从机输入
//操作通道
input [P_OP_LEN - 1 :0] i_user_op_data ,//操作数据(命令8bit+地址24bit)
input [1 :0] i_user_op_type ,//操作类型(读、写、指令)
input [15:0] i_user_op_len ,//操作数据的长 32 或 8
input [15:0] i_user_clk_len ,//时钟周期
//握手信号
input i_user_op_valid ,//用户的有效信号
output o_user_op_ready ,//用户的准备信号
//与上层交互通道
input [P_DATA_WIDTH - 1 :0] i_user_write_data ,//写的数据
output o_user_write_req ,//写数据请求
//输出结果通道
output [P_READ_DATA_WIDTH - 1:0] o_user_read_data ,//读到的数据
output o_user_read_valid //读数据有效
);
//3个状态: 命令/读/写
/***************parameter*************/
localparam P_OP_TYPE_INS = 0,
P_OP_READ = 1,
P_OP_WRITE = 2;
/***************reg*******************/
reg ro_spi_clk ;
reg ro_spi_cs ;
reg ro_spi_mosi ;
reg ro_user_ready ;
reg [P_OP_LEN - 1:0] r_user_op_data ;
reg [1 :0] r_user_op_type ;
reg [15:0] r_user_op_len ;
reg [15:0] r_user_clk_len ;
reg [P_DATA_WIDTH - 1:0] r_user_data ;
reg r_run ;
reg [15:0] r_cnt ;
reg r_spi_cnt ;
reg [P_READ_DATA_WIDTH - 1:0] ro_user_read_data ;
reg ro_user_read_valid ;
reg r_run_1d ;
reg ro_user_write_req ;
reg ro_user_write_req_1d;
reg [15:0] r_write_cnt ;
reg [P_DATA_WIDTH - 1 :0] r_user_write_data ;
reg [15:0] r_read_cnt ;
/***************wire******************/
wire w_user_active ;
wire w_run_negedge ;
/***************component*************/
/***************assign****************/
assign o_spi_clk = ro_spi_clk ;
assign o_spi_cs = ro_spi_cs ;
assign o_spi_mosi = ro_spi_mosi ;
assign o_user_op_ready = ro_user_ready ;
assign o_user_read_data = ro_user_read_data ;
assign o_user_read_valid = ro_user_read_valid ;
assign w_run_negedge = !r_run & r_run_1d ;
assign o_user_write_req = ro_user_write_req ;
/***************always****************/
assign w_user_active = i_user_op_valid & o_user_op_ready;
//控制准备信号
always@(posedge i_clk,posedge i_rst)
begin
if(i_rst)
ro_user_ready <='d1;
else if(w_user_active)
ro_user_ready <= 'd0;
else if(w_run_negedge)
ro_user_ready <= 'd1;
else
ro_user_ready <= ro_user_ready;
end
//操作总线,锁存USER的数据指令
always@(posedge i_clk,posedge i_rst)
begin
if(i_rst) begin
r_user_op_type <= 'd0;
r_user_op_len <= 'd0;
r_user_clk_len <= 'd0;
end else if(w_user_active) begin
r_user_op_type <= i_user_op_type;
r_user_op_len <= i_user_op_len ;
r_user_clk_len <= i_user_clk_len;
end else begin
r_user_op_type <= r_user_op_type;
r_user_op_len <= r_user_op_len ;
r_user_clk_len <= r_user_clk_len;
end
end
//激活后, 锁存操作数据
//下降沿, spi数据并转串
always@(posedge i_clk,posedge i_rst)
begin
if(i_rst)
r_user_op_data <= 'd0;
else if(w_user_active)
r_user_op_data <= i_user_op_data;//指令8bit + 24bit地址
else if(r_spi_cnt)//spi输出时,并转
r_user_op_data <= r_user_op_data << 1;
else
r_user_op_data <= r_user_op_data;
end
//run总线运行标志
//下降沿+spi的clk周期到达指定值 ,停止
//激活后,运行
always@(posedge i_clk,posedge i_rst)
begin
if(i_rst)
r_run <= 'd0;
else if(r_spi_cnt && r_cnt == r_user_clk_len - 1)
r_run <= 'd0;
else if(w_user_active)
r_run <= 'd1;
else
r_run <= r_run;
end
// run 打拍 获得下降沿
always@(posedge i_clk,posedge i_rst)
begin
if(i_rst)
r_run_1d <= 'd0;
else
r_run_1d <= r_run;
end
//spi时钟周期计数
always@(posedge i_clk,posedge i_rst)
begin
if(i_rst)
r_cnt <= 'd0;
else if(r_spi_cnt && r_cnt == r_user_clk_len - 1)
r_cnt <= 'd0;
else if(r_spi_cnt)
r_cnt <= r_cnt + 1;
else
r_cnt <= r_cnt;
end
//spi时钟计数,用于判断上升/下降沿
always@(posedge i_clk,posedge i_rst)
begin
if(i_rst)
r_spi_cnt <= 'd0;
else if(r_run)
r_spi_cnt <= r_spi_cnt + 1;
else
r_spi_cnt <= 'd0;
end
//spi时钟信号,run就开始翻转
always@(posedge i_clk,posedge i_rst)
begin
if(i_rst)
ro_spi_clk <= P_CPOL;
else if(r_run)
ro_spi_clk <= ~ro_spi_clk;
else
ro_spi_clk <= P_CPOL;
end
//spi片选信号 ,激活就片选
always@(posedge i_clk,posedge i_rst)
begin
if(i_rst)
ro_spi_cs <= 'd1;
else if(w_user_active)
ro_spi_cs <= 'd0;
else if(!r_run)
ro_spi_cs <= 'd1;
else
ro_spi_cs <= ro_spi_cs;
end
//spi输出引脚
//1. 输出操作数据
//2. 输出要写出去的数据
always@(posedge i_clk,posedge i_rst)
begin
if(i_rst)
ro_spi_mosi <= 'd0;
else if(w_user_active)//输出操作数据 最高位 指令+地址
ro_spi_mosi <= i_user_op_data[P_OP_LEN - 1];//operation
else if(r_spi_cnt && r_cnt < r_user_op_len - 1)//依次输出操作数据次高位
ro_spi_mosi <= r_user_op_data[P_OP_LEN - 2];
else if(r_user_op_type == P_OP_WRITE && r_spi_cnt)//串行输出写数据
ro_spi_mosi <= r_user_write_data[7];
else
ro_spi_mosi <= ro_spi_mosi;
end
//
//2.(上升沿 + 周期计数器到P_OP_LEN -2 ||写数据计数==15 ) && 写状态
// 因为r_cnt是基于spi_clk(系统时钟/2)来计数的,!r_spi_cnt是作为i_clk时钟位置的判断
always@(posedge i_clk,posedge i_rst)
begin
if(i_rst)
ro_user_write_req <= 'd0;
else if(r_cnt >= r_user_clk_len - 5)
ro_user_write_req <= 'd0;
else if(((!r_spi_cnt && r_cnt == P_OP_LEN-2) || r_write_cnt == 15) && r_user_op_type == P_OP_WRITE )
ro_user_write_req <= 'd1;
else
ro_user_write_req <= 'd0;
end
// 获得延时1个周期的写请求信号
always@(posedge i_clk,posedge i_rst)
begin
if(i_rst)
ro_user_write_req_1d <= 'd0;
else
ro_user_write_req_1d <= ro_user_write_req;
end
// 1.用延时一个周期的写请求信号(此时外部数据已经更新),来锁存输入的要写的数据
// 2.spi_clk的下降沿 位移数据
always@(posedge i_clk,posedge i_rst)
begin
if(i_rst)
r_user_write_data <= 'd0;
else if(ro_user_write_req_1d)
r_user_write_data <= i_user_write_data;
else if(r_spi_cnt)
r_user_write_data <= r_user_write_data << 1;
else
r_user_write_data <= r_user_write_data;
end
//写请求后 r_write_cnt 写计数 0 ~ 15 用于下次产生写请求
always@(posedge i_clk,posedge i_rst)
begin
if(i_rst)
r_write_cnt <= 'd0;
else if(r_write_cnt == 15 || ro_spi_cs)
r_write_cnt <= 'd0;
else if(ro_user_write_req || r_write_cnt)
r_write_cnt <= r_write_cnt + 1;
else
r_write_cnt <= r_write_cnt;
end
/*--------------------------读---------------------------------*/
//完成命令+地址的指令后,读数据
always@(posedge ro_spi_clk,posedge i_rst)
begin
if(i_rst)
ro_user_read_data <= 'd0;
else if(r_cnt >= r_user_op_len )
ro_user_read_data <= {ro_user_read_data[P_READ_DATA_WIDTH - 2 : 0],i_spi_miso};
else
ro_user_read_data <= ro_user_read_data;
end
// 完成了命令+地址的指令后,读计数 0 ~ 8
always@(posedge i_clk,posedge i_rst)
begin
if(i_rst)
r_read_cnt <= 'd0;
else if(r_read_cnt == P_READ_DATA_WIDTH || ro_spi_cs)
r_read_cnt <= 'd0;
else if(r_spi_cnt && r_cnt >= r_user_op_len - 0 && r_user_op_type == P_OP_READ)
r_read_cnt <= r_read_cnt + 1;
else
r_read_cnt <= r_read_cnt;
end
//读数据有效信号
always@(posedge i_clk,posedge i_rst)
begin
if(i_rst)
ro_user_read_valid <= 'd0;
else if(r_spi_cnt && r_read_cnt == P_READ_DATA_WIDTH - 1 && r_user_op_type == P_OP_READ)
ro_user_read_valid <= 'd1;
else
ro_user_read_valid <= 'd0;
end
endmodule
2. SPI协议的控制器(状态机)
连续读出存在FIFO中的数据
module flash_ctrl#(
parameter P_DATA_WIDTH = 8 ,//数据位宽
P_OP_LEN = 32,//指令长度
P_READ_DATA_WIDTH = 8 ,//读数据位宽
P_CPOL = 0 ,//空闲时时钟状态
P_CPHL = 0 //采集数据时钟沿
)(
input i_clk ,//用户时钟
input i_rst ,//用户复位
/*--------用户接口--------*/
input [1 :0] i_operation_type ,//操作类型
input [23:0] i_operation_addr ,//操作地址
input [8 :0] i_operation_num ,//限制用户每次最多写256字节
input i_operation_valid ,//操作握手有效
output o_operation_ready ,//操作握手准备
input [P_DATA_WIDTH - 1 :0] i_write_data ,//写数据
input i_write_sop ,//写数据-开始信号
input i_write_eop ,//写数据-结束信号
input i_write_valid ,//写数据-有效信号
output [P_DATA_WIDTH - 1 :0] o_read_data ,//读数据
output o_read_sop ,//读数据-开始信号
output o_read_eop ,//读数据-结束信号
output o_read_valid ,//读数据-有效信号
/*--------驱动接口--------*/
output [P_OP_LEN - 1 :0] o_user_op_data ,//操作数据(指令8bit+地址24bit)
output [1 :0] o_user_op_type ,//操作类型(读、写、指令)
output [15:0] o_user_op_len ,//操作数据的长度32、8
output [15:0] o_user_clk_len ,//时钟周期
output o_user_op_valid ,//用户的有效信号
input i_user_op_ready ,//用户的准备信号
output [P_DATA_WIDTH - 1 :0] o_user_write_data ,//写数据
input i_user_write_req ,//写数据请求
input [P_READ_DATA_WIDTH - 1:0] i_user_read_data ,//读数据
input i_user_read_valid //读数据有效
);
/***************function**************/
/***************parameter*************/
//用户接口操作类型
localparam P_TYPE_CLEAR = 0 ,
P_TYPE_WRITE = 1 ,
P_TYPE_READ = 2 ;
//SPI总线驱动器操作类型
localparam P_OP_TYPE_INS = 0,
P_OP_READ = 1,
P_OP_WRITE = 2;
//状态机状态
localparam P_IDLE = 0 ,
P_RUN = 1 ,
P_W_EN = 2 ,
P_W_INS = 3 ,
P_W_DATA = 4 ,
P_R_INS = 5 ,
P_R_DATA = 6 ,
P_CLEAR = 7 ,
P_BUSY = 8 ,
P_BUSY_CHECK = 9 ,
P_BUSY_WAIT = 10 ;
/***************port******************/
/***************mechine***************/
//状态机
reg [7 :0] r_st_current ;
reg [7 :0] r_st_next ;
reg [7 :0] r_st_cnt ;
/***************reg*******************/
reg [1 :0] ri_operation_type ;
reg [23:0] ri_operation_addr ;
reg [8 :0] ri_operation_num ;
reg [P_DATA_WIDTH - 1 :0] ri_write_data ;
reg ri_write_sop ;
reg ri_write_eop ;
reg ri_write_valid ;
reg r_user_ready_1d ;
reg [P_OP_LEN - 1 :0] ro_user_op_data ;
reg [1 :0] ro_user_op_type ;
reg [15:0] ro_user_op_len ;
reg [15:0] ro_user_clk_len ;
reg ro_user_op_valid ;
reg [P_DATA_WIDTH - 1 :0] ri_user_read_data ;
reg ri_user_read_valid ;
reg ro_operation_ready ;
reg [7 :0] ro_read_data ;
reg ro_read_sop ;
reg ro_read_eop ;
reg ro_read_valid ;
reg r_fifo_read_rden ;
reg r_fifo_read_rden_1d ;
reg r_fifo_read_pos ;
reg r_fifo_read_emp_1d ;
reg r_fifo_read_wren ;
/***************wire******************/
wire w_operation_active ;
wire w_user_ready_pos ;
wire w_spi_drive_act ;
wire w_fifo_read_empty ;
wire [7 :0] w_read_data ;
/***************component*************/
//输入:用户写入想要 写进外设的数据
//输出:spi请求数据的时候,输出要写的数据
FLASH_CTRL_FIFO_DATA FLASH_CTRL_FIFO_DATA_U0 (
.clk (i_clk ),
.srst (i_rst ),
.din (ri_write_data ),
.wr_en (ri_write_valid ),
.rd_en (i_user_write_req ),
.dout (o_user_write_data ),
.full (),
.empty ()
);
//输入:spi读到的数据,写进去
//输出:用户要读取数据的时候,输出
FLASH_CTRL_FIFO_DATA FLASH_CTRL_FIFO_DATA_READ_U0 (
.clk (i_clk ),
.srst (i_rst ),
.din (ri_user_read_data ),
.wr_en (r_fifo_read_wren ),
.rd_en (r_fifo_read_rden ),
.dout (w_read_data ),
.full (),
.empty (w_fifo_read_empty )
);
/***************assign****************/
assign w_operation_active = i_operation_valid & o_operation_ready ;
assign w_user_ready_pos = r_user_ready_1d & i_user_op_ready ;
assign o_user_op_data = ro_user_op_data ;
assign o_user_op_type = ro_user_op_type ;
assign o_user_op_len = ro_user_op_len ;
assign o_user_clk_len = ro_user_clk_len ;
assign o_user_op_valid = ro_user_op_valid ;
assign o_operation_ready = ro_operation_ready ;
assign w_spi_drive_act = o_user_op_valid & i_user_op_ready ;
// assign o_read_data = ro_read_data ;
assign o_read_sop = ro_read_sop ;
assign o_read_eop = ro_read_eop ;
assign o_read_valid = ro_read_valid ;
assign o_read_data = ro_read_data ;
/***************always****************/
//状态机跳转
always@(posedge i_clk,posedge i_rst)
begin
if(i_rst)
r_st_current <= P_IDLE;
else
r_st_current <= r_st_next;
end
//跳转条件
always@(*)
begin
case(r_st_current)
P_IDLE : r_st_next = w_operation_active ? P_RUN : P_IDLE ; //空闲状态,用户激活时跳转
P_RUN : r_st_next = ri_operation_type == P_TYPE_READ ? P_R_INS : P_W_EN ; //开始运行状态机,读/写
P_W_EN : r_st_next = w_spi_drive_act ?
ri_operation_type == P_TYPE_WRITE ? P_W_INS : P_CLEAR //判断是写数据还是擦除
: P_W_EN ;//写使能状态
P_W_INS : r_st_next = w_spi_drive_act ? P_W_DATA : P_W_INS ; //写数据指令状态
P_W_DATA : r_st_next = i_user_op_ready ? P_BUSY : P_W_DATA ; //写数据
P_R_INS : r_st_next = w_spi_drive_act ? P_R_DATA : P_R_INS ; //读数据指令状态
P_R_DATA : r_st_next = i_user_op_ready ? P_BUSY : P_R_DATA ; //读数据
P_CLEAR : r_st_next = w_spi_drive_act ? P_BUSY : P_CLEAR ;
P_BUSY : r_st_next = w_spi_drive_act ? P_BUSY_CHECK : P_BUSY ; //读状态寄存器
P_BUSY_CHECK : r_st_next = ri_user_read_valid ?
i_user_read_data[0] ? P_BUSY_WAIT : P_IDLE
: P_BUSY_CHECK ; //根据返回的状态值,判断是否繁忙
P_BUSY_WAIT : r_st_next = r_st_cnt == 255 ? P_BUSY : P_BUSY_WAIT ; //等待255个周期,重启读忙
default : r_st_next = P_W_EN;
endcase
end
always@(posedge i_clk,posedge i_rst)
begin
if(i_rst)
r_st_cnt <= 'd0;
else if(r_st_current != r_st_next)
r_st_cnt <= 'd0;
else
r_st_cnt <= r_st_cnt + 1;
end
/*--------驱动逻辑--------*/
//第三段状态机
always@(posedge i_clk,posedge i_rst)
begin
if(i_rst) begin
ro_user_op_data <= 'd0;
ro_user_op_type <= 'd0;
ro_user_op_len <= 'd0;
ro_user_clk_len <= 'd0;
ro_user_op_valid <= 'd0;
end else if(r_st_current == P_W_EN) begin //发送写使能指令
ro_user_op_data <= {8'h06,8'h00,8'h00,8'h00};
ro_user_op_type <= P_OP_TYPE_INS;
ro_user_op_len <= 8;
ro_user_clk_len <= 8;
ro_user_op_valid <= 'd1;
end else if(r_st_current == P_W_INS) begin //发送写数据指令
ro_user_op_data <= {8'h02,ri_operation_addr};
ro_user_op_type <= P_OP_WRITE;
ro_user_op_len <= 32;
ro_user_clk_len <= 32 + 8 * ri_operation_num;
ro_user_op_valid <= 'd1;
end else if(r_st_current == P_R_INS) begin //发送读数据指令
ro_user_op_data <= {8'h03,ri_operation_addr};
ro_user_op_type <= P_OP_READ;
ro_user_op_len <= 32;
ro_user_clk_len <= 32 + 8 * ri_operation_num;
ro_user_op_valid <= 'd1;
end else if(r_st_current == P_CLEAR) begin //发送擦除指令
ro_user_op_data <= {8'h20,ri_operation_addr};
ro_user_op_type <= P_OP_TYPE_INS;
ro_user_op_len <= 32;
ro_user_clk_len <= 32;
ro_user_op_valid <= 'd1;
end else if(r_st_current == P_BUSY) begin //发送读状态-BUSY
ro_user_op_data <= {8'h05,24'd0};
ro_user_op_type <= P_OP_READ;
ro_user_op_len <= 8;
ro_user_clk_len <= 16;
ro_user_op_valid <= 'd1;
end else begin
ro_user_op_data <= ro_user_op_data;
ro_user_op_type <= ro_user_op_type;
ro_user_op_len <= ro_user_op_len ;
ro_user_clk_len <= ro_user_clk_len;
ro_user_op_valid <= 'd0;
end
end
always@(posedge i_clk,posedge i_rst)
begin
if(i_rst)
r_user_ready_1d <= 'd0;
else
r_user_ready_1d <= i_user_op_ready;
end
// 锁存读到的数据和有效信号
always@(posedge i_clk,posedge i_rst)
begin
if(i_rst) begin
ri_user_read_data <= 'd0;
ri_user_read_valid <= 'd0;
end else begin
ri_user_read_data <= i_user_read_data ;
ri_user_read_valid <= i_user_read_valid ;
end
end
/*--------用户逻辑--------*/
//握手激活,开始操作
always@(posedge i_clk,posedge i_rst)
begin
if(i_rst) begin
ri_operation_type <= 'd0;
ri_operation_addr <= 'd0;
ri_operation_num <= 'd0;
end else if(w_operation_active) begin
ri_operation_type <= i_operation_type;
ri_operation_addr <= i_operation_addr;
ri_operation_num <= i_operation_num ;
end else begin
ri_operation_type <= ri_operation_type;
ri_operation_addr <= ri_operation_addr;
ri_operation_num <= ri_operation_num ;
end
end
//激活拉低准备信号
always@(posedge i_clk,posedge i_rst)
begin
if(i_rst)
ro_operation_ready <= 'd1;
else if(r_st_next == P_IDLE)
ro_operation_ready <= 'd1;
else if(w_operation_active)
ro_operation_ready <= 'd0;
else
ro_operation_ready <= ro_operation_ready;
end
//*------------------用户写入数据存入FIFO ------------------------*/
always@(posedge i_clk,posedge i_rst)
begin
if(i_rst) begin
ri_write_data <= 'd0;
ri_write_sop <= 'd0;
ri_write_eop <= 'd0;
ri_write_valid <= 'd0;
end else begin
ri_write_data <= i_write_data ;
ri_write_sop <= i_write_sop ;
ri_write_eop <= i_write_eop ;
ri_write_valid <= i_write_valid;
end
end
/*-----------------------从FIFO中读数据---------------------------------*/
//从FIFO中读数据使能开启
always@(posedge i_clk,posedge i_rst)
begin
if(i_rst)
r_fifo_read_rden <= 'd0;
else if(w_fifo_read_empty)
r_fifo_read_rden <= 'd0;
else if(r_st_current == P_R_DATA && r_st_next != P_R_DATA)
r_fifo_read_rden <= 'd1;
else
r_fifo_read_rden <= r_fifo_read_rden;
end
always@(posedge i_clk,posedge i_rst)
begin
if(i_rst)
r_fifo_read_rden_1d <= 'd0;
else
r_fifo_read_rden_1d <= r_fifo_read_rden;
end
always@(posedge i_clk,posedge i_rst)
begin
if(i_rst)
r_fifo_read_pos <= 'd0;
else
r_fifo_read_pos <= !r_fifo_read_rden_1d && r_fifo_read_rden;
end
always@(posedge i_clk,posedge i_rst)
begin
if(i_rst)
r_fifo_read_emp_1d <= 'd0;
else
r_fifo_read_emp_1d <= w_fifo_read_empty;
end
//开始fifo数据输出
always@(posedge i_clk,posedge i_rst)
begin
if(i_rst)
ro_read_sop <= 'd0;
else if(r_fifo_read_pos)
ro_read_sop <= 'd1;
else
ro_read_sop <= 'd0;
end
//结束fifo数据输出
always@(posedge i_clk,posedge i_rst)
begin
if(i_rst)
ro_read_eop <= 'd0;
else if(w_fifo_read_empty && !r_fifo_read_emp_1d && ro_read_valid)
ro_read_eop <= 'd1;
else
ro_read_eop <= 'd0;
end
//fifo读有效信号指示
always@(posedge i_clk,posedge i_rst)
begin
if(i_rst)
ro_read_valid <= 'd0;
else if(ro_read_eop)
ro_read_valid <= 'd0;
else if(r_fifo_read_pos)
ro_read_valid <= 'd1;
else
ro_read_valid <= ro_read_valid;
end
//从FIFO中读出的数据
always@(posedge i_clk,posedge i_rst)
begin
if(i_rst)
ro_read_data <= 'd0;
else
ro_read_data <= w_read_data;
end
//---------------------------将读到的数据写入FIFO------------------------------*/
always@(posedge i_clk,posedge i_rst)
begin
if(i_rst)
r_fifo_read_wren <= 'd0;
else if(r_st_current == P_R_DATA)
r_fifo_read_wren <= i_user_read_valid;
else
r_fifo_read_wren <= 'd0;
end
endmodule