module SPIX4_TT #(
parameter CNT_NUM = 10,
parameter ADDR_W = 16,
parameter DATA_W = 8
)(
input clk ,
input srst ,
output s_axis_tready ,
input s_axis_tvalid ,
input s_axis_rw ,//高为读,从器件到FPGA;低为写,从FPGA到器件;
input [ADDR_W-1:0] s_axis_taddr ,//不只是地址,控制指令
input [DATA_W-1:0] s_axis_tdata ,
output T ,//高为输入,高阻;低为输出;
output CS_B ,
output SCLK ,
output SDO ,
input SDI ,
output m_axis_tvalid ,
output [ADDR_W+DATA_W-1:0] m_axis_tdata
);
localparam STATE_IDLE = 4'd0;
localparam STATE_S1 = 4'd1;
localparam STATE_S2 = 4'd2;
localparam STATE_S3 = 4'd3;
localparam STATE_S4 = 4'd4;
reg [ 3: 0] state_c = STATE_IDLE;
reg [ 3: 0] state_n;
wire idle2s1_start;
wire s12s2_start;
wire s22s3_start;
wire s32s4_start;
wire s42idle_start;
reg [ 7: 0] cnt = 0;
wire add_cnt;
wire end_cnt;
reg [ 7: 0] cnta = 0;
wire add_cnta;
wire end_cnta;
reg [ 7: 0] cntd = 0;
wire add_cntd;
wire end_cntd;
reg [ADDR_W-1:0] addr_sc = 0;
reg [DATA_W-1:0] data_sc = 0;
reg rw_sc = 0;
reg sclk_r = 0;
reg cs_b_r = 1;
reg [ADDR_W+DATA_W-1:0] sdo_r = 0;
reg [DATA_W-1:0] jieshou = 0;
/************************************************************
状态机
************************************************************/
always @(posedge clk)begin
if(srst)begin
state_c <= STATE_IDLE;
end
else begin
state_c <= state_n;
end
end
always @(*)begin
case(state_c)
STATE_IDLE:begin
if(idle2s1_start)begin
state_n = STATE_S1;
end
else begin
state_n = state_c;
end
end
STATE_S1:begin
if(s12s2_start)begin
state_n = STATE_S2;
end
else begin
state_n = state_c;
end
end
STATE_S2:begin
if(s22s3_start)begin
state_n = STATE_S3;
end
else begin
state_n = state_c;
end
end
STATE_S3:begin
if(s32s4_start)begin
state_n = STATE_S4;
end
else begin
state_n = state_c;
end
end
STATE_S4:begin
if(s42idle_start)begin
state_n = STATE_IDLE;
end
else begin
state_n = state_c;
end
end
default:state_n = STATE_IDLE;
endcase
end
assign idle2s1_start = state_c == STATE_IDLE && s_axis_tvalid;
assign s12s2_start = state_c == STATE_S1 && end_cnt;
assign s22s3_start = state_c == STATE_S2 && end_cnta;
assign s32s4_start = state_c == STATE_S3 && end_cntd;
assign s42idle_start = state_c == STATE_S4 && end_cnt;
assign s_axis_tready = state_c == STATE_IDLE;
/************************************************************
锁存数据
************************************************************/
always @(posedge clk)begin
if(idle2s1_start)begin
addr_sc <= s_axis_taddr;
data_sc <= s_axis_tdata;
rw_sc <= s_axis_rw;
end
end
/************************************************************
分频
************************************************************/
always @(posedge clk)begin
if(srst)begin
cnt <= 0;
end
else if(add_cnt)begin
if(end_cnt)begin
cnt <= 0;
end
else begin
cnt <= cnt + 1'b1;
end
end
end
assign add_cnt = !(state_c == STATE_IDLE);
assign end_cnt = add_cnt && cnt == CNT_NUM - 1;
/************************************************************
地址
************************************************************/
always @(posedge clk)begin
if(srst)begin
cnta <= 0;
end
else if(add_cnta)begin
if(end_cnta)begin
cnta <= 0;
end
else begin
cnta <= cnta + 1'b1;
end
end
end
assign add_cnta = state_c == STATE_S2;
assign end_cnta = add_cnta && cnta == ADDR_W - 1;
/************************************************************
数据
************************************************************/
always @(posedge clk)begin
if(srst)begin
cntd <= 0;
end
else if(add_cntd)begin
if(end_cntd)begin
cntd <= 0;
end
else begin
cntd <= cntd + 1'b1;
end
end
end
assign add_cntd = state_c == STATE_S3;
assign end_cntd = add_cntd && cntd == DATA_W - 1;
/************************************************************
SCLK
************************************************************/
always @(posedge clk)begin
if(srst)begin
sclk_r <= 0;
end
else if(end_cnt)begin
sclk_r <= 0;
end
else if(cnt == (CNT_NUM/2-1))begin
sclk_r <= 1;
end
end
assign SCLK = sclk_r;
/************************************************************
CS_B
************************************************************/
always @(posedge clk)begin
if(srst)begin
cs_b_r <= 1;
end
else if(s32s4_start)begin
cs_b_r <= 1;
end
else if(s12s2_start)begin
cs_b_r <= 0;
end
end
assign CS_B = cs_b_r;
/************************************************************
SDO
************************************************************/
always @(posedge clk)begin
if(s12s2_start)begin
sdo_r <= {addr_sc,data_sc};
end
else if(end_cnt)begin
sdo_r <= addr_sc;
end
end
assign SDO = sdo_r[ADDR_W+DATA_W-1];
/************************************************************
T
************************************************************/
assign T = (state_c == STATE_S3) && rw_sc;
/************************************************************
SDI
************************************************************/
always @(posedge clk)begin
if(T && (cnt == (CNT_NUM/2-1)))begin
jieshou <= {jieshou[DATA_W-2:0],SDI};
end
end
assign m_axis_tdata = {addr_sc,jieshou};
assign m_axis_tvalid = s32s4_start;
endmodule