SPI接口设计
- SPI基础代码模版
- 1. SPI协议与芯片交互接口
- 2. SPI协议的控制器(状态机)
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)
beginif(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;
endalways@(posedge i_clk,posedge i_rst)
beginif(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;
endalways@(posedge i_clk,posedge i_rst)
beginif(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;
endalways@(posedge i_clk,posedge i_rst)
beginif(i_rst)r_run_1d <= 'd0;elser_run_1d <= r_run;
end
always@(posedge i_clk,posedge i_rst)
beginif(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;
endalways@(posedge i_clk,posedge i_rst)
beginif(i_rst)r_spi_cnt <= 'd0;else if(r_run)r_spi_cnt <= r_spi_cnt + 1;else r_spi_cnt <= 'd0;
endalways@(posedge i_clk,posedge i_rst)
beginif(i_rst)ro_spi_clk <= P_CPOL;else if(r_run)ro_spi_clk <= ~ro_spi_clk;else ro_spi_clk <= P_CPOL;
endalways@(posedge i_clk,posedge i_rst)
beginif(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;
endalways@(posedge i_clk,posedge i_rst)
beginif(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)
beginif(i_rst)ro_user_read_data <= 'd0;elsero_user_read_data <= {ro_user_read_data[P_DATA_WIDTH - 2 : 0],i_spi_miso};endalways@(posedge i_clk,posedge i_rst)
beginif(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;
endendmodule
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的clkoutput 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 或 8input [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)
beginif(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)
beginif(i_rst) beginr_user_op_type <= 'd0;r_user_op_len <= 'd0;r_user_clk_len <= 'd0;end else if(w_user_active) beginr_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)
beginif(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)
beginif(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)
beginif(i_rst)r_run_1d <= 'd0;elser_run_1d <= r_run;
end//spi时钟周期计数
always@(posedge i_clk,posedge i_rst)
beginif(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)
beginif(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)
beginif(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)
beginif(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)
beginif(i_rst)ro_spi_mosi <= 'd0;else if(w_user_active)//输出操作数据 最高位 指令+地址ro_spi_mosi <= i_user_op_data[P_OP_LEN - 1];//operationelse 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)
beginif(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)
beginif(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)
beginif(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)
beginif(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)
beginif(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)
beginif(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)
beginif(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;
endendmodule
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、8output [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)
beginif(i_rst)r_st_current <= P_IDLE;elser_st_current <= r_st_next;
end//跳转条件
always@(*)
begincase(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)
beginif(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)
beginif(i_rst) beginro_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 //发送读状态-BUSYro_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 beginro_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
endalways@(posedge i_clk,posedge i_rst)
beginif(i_rst)r_user_ready_1d <= 'd0;else r_user_ready_1d <= i_user_op_ready;
end// 锁存读到的数据和有效信号
always@(posedge i_clk,posedge i_rst)
beginif(i_rst) beginri_user_read_data <= 'd0;ri_user_read_valid <= 'd0;end else beginri_user_read_data <= i_user_read_data ;ri_user_read_valid <= i_user_read_valid ;end
end/*--------用户逻辑--------*/
//握手激活,开始操作
always@(posedge i_clk,posedge i_rst)
beginif(i_rst) beginri_operation_type <= 'd0;ri_operation_addr <= 'd0;ri_operation_num <= 'd0;end else if(w_operation_active) beginri_operation_type <= i_operation_type;ri_operation_addr <= i_operation_addr;ri_operation_num <= i_operation_num ;end else beginri_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)
beginif(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)
beginif(i_rst) beginri_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)
beginif(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;
endalways@(posedge i_clk,posedge i_rst)
beginif(i_rst) r_fifo_read_rden_1d <= 'd0;else r_fifo_read_rden_1d <= r_fifo_read_rden;
endalways@(posedge i_clk,posedge i_rst)
beginif(i_rst)r_fifo_read_pos <= 'd0;else r_fifo_read_pos <= !r_fifo_read_rden_1d && r_fifo_read_rden;
endalways@(posedge i_clk,posedge i_rst)
beginif(i_rst)r_fifo_read_emp_1d <= 'd0;elser_fifo_read_emp_1d <= w_fifo_read_empty;
end//开始fifo数据输出
always@(posedge i_clk,posedge i_rst)
beginif(i_rst) ro_read_sop <= 'd0;else if(r_fifo_read_pos)ro_read_sop <= 'd1;elsero_read_sop <= 'd0;
end//结束fifo数据输出
always@(posedge i_clk,posedge i_rst)
beginif(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)
beginif(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)
beginif(i_rst)ro_read_data <= 'd0;else ro_read_data <= w_read_data;
end//---------------------------将读到的数据写入FIFO------------------------------*/
always@(posedge i_clk,posedge i_rst)
beginif(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