`timescale 1 ns / 1 ps
module qspi_stream_ip_v1_0_S00_AXIS #
(
// Users to add parameters here
// User parameters ends
// Do not modify the parameters beyond this line
// AXI4Stream sink: Data Width
parameter integer C_S_AXIS_TDATA_WIDTH = 512
)
(
// Users to add ports here
input qspi_clk,
input qspi_clk_rstn,
output csx,
output sck,
output [3:0] dout,
// User ports ends
// Do not modify the ports beyond this line
// AXI4Stream sink: Clock
input wire S_AXIS_ACLK,
// AXI4Stream sink: Reset
input wire S_AXIS_ARESETN,
// Ready to accept data in
output wire S_AXIS_TREADY,
// Data in
input wire [C_S_AXIS_TDATA_WIDTH-1 : 0] S_AXIS_TDATA,
// Byte qualifier
input wire [(C_S_AXIS_TDATA_WIDTH/8)-1 : 0] S_AXIS_TSTRB,
// Indicates boundary of last packet
input wire S_AXIS_TLAST,
// Data is in valid
input wire S_AXIS_TVALID
);
// function called clogb2 that returns an integer which has the
// value of the ceiling of the log base 2.
function integer clogb2 (input integer bit_depth);
begin
for(clogb2=0; bit_depth>0; clogb2=clogb2+1)
bit_depth = bit_depth >> 1;
end
endfunction
// Total number of input data.
localparam NUMBER_OF_INPUT_WORDS = 128;
// bit_num gives the minimum number of bits needed to address 'NUMBER_OF_INPUT_WORDS' size of FIFO.
localparam bit_num = clogb2(NUMBER_OF_INPUT_WORDS-1);
// Define the states of state machine
// The control state machine oversees the writing of input streaming data to the FIFO,
// and outputs the streaming data from the FIFO
parameter [1:0] IDLE = 1'b0, // This is the initial/idle state
WRITE_FIFO = 1'b1; // In this state FIFO is written with the
// input stream data S_AXIS_TDATA
wire axis_tready;
// State variable
reg mst_exec_state;
// FIFO implementation signals
genvar byte_index;
// FIFO write enable
wire fifo_wren;
// FIFO full flag
// reg fifo_full_flag;
// FIFO write pointer
// reg [bit_num-1:0] write_pointer;
// sink has accepted all the streaming data and stored in FIFO
reg writes_done;
// I/O Connections assignments
reg fifo_rden;
reg xfer_start;
assign S_AXIS_TREADY = axis_tready;
// Control state machine implementation
always @(posedge S_AXIS_ACLK)
begin
if (!S_AXIS_ARESETN)
// Synchronous reset (active low)
begin
mst_exec_state <= IDLE;
end
else
case (mst_exec_state)
IDLE:
// The sink starts accepting tdata when
// there tvalid is asserted to mark the
// presence of valid streaming data
if (S_AXIS_TVALID)
begin
mst_exec_state <= WRITE_FIFO;
end
else
begin
mst_exec_state <= IDLE;
end
WRITE_FIFO:
// When the sink has accepted all the streaming input data,
// the interface swiches functionality to a streaming master
if (writes_done)
begin
mst_exec_state <= IDLE;
end
else
begin
// The sink accepts and stores tdata
// into FIFO
mst_exec_state <= WRITE_FIFO;
end
endcase
end
// AXI Streaming Sink
//
// The example design sink is always ready to accept the S_AXIS_TDATA until
// the FIFO is not filled with NUMBER_OF_INPUT_WORDS number of input words.
assign axis_tready = ((mst_exec_state == WRITE_FIFO) && ~full);
always@(posedge S_AXIS_ACLK)
begin
if(!S_AXIS_ARESETN)
begin
writes_done <= 1'b0;
end
else
if (~full)
begin
if (fifo_wren)
begin
// write pointer is incremented after every write to the FIFO
// when FIFO write signal is enabled.
writes_done <= 1'b0;
end
if (~full|| S_AXIS_TLAST)
begin
// reads_done is asserted when NUMBER_OF_INPUT_WORDS numbers of streaming data
// has been written to the FIFO which is also marked by S_AXIS_TLAST(kept for optional usage).
writes_done <= 1'b1;
end
end
end
// FIFO write enable generation
assign fifo_wren = S_AXIS_TVALID && axis_tready;
// Add user logic here
wire full;
wire empty;
wire [0:511] fifo_dout;
wire [6:0] rd_data_count;
wire [6:0] wr_data_count;
fifo_generator_0 your_instance_name (
.wr_clk(S_AXIS_ACLK), // input wire wr_clk
.rd_clk(qspi_clk), // input wire rd_clk
.din(S_AXIS_TDATA), // input wire [511 : 0] din
.wr_en(fifo_wren), // input wire wr_en
.rd_en(fifo_rden), // input wire rd_en
.dout(fifo_dout), // output wire [511 : 0] dout
.full(full), // output wire full
.almost_full(almost_full), // output wire almost_full
.empty(empty), // output wire empty
.almost_empty(almost_empty), // output wire almost_empty
.rd_data_count(rd_data_count), // output wire [6 : 0] rd_data_count
.wr_data_count(wr_data_count) // output wire [6 : 0] wr_data_count
);
reg empty_d;
always @(posedge qspi_clk or negedge qspi_clk_rstn)
if(qspi_clk_rstn==0)
empty_d<=0;
else
empty_d<=empty;
assign first_rd_en=(~empty) & empty_d & xfer_rdy; //第一次读,由empty信号下降沿自动启动
always @(posedge qspi_clk or negedge qspi_clk_rstn)
if(qspi_clk_rstn==0) begin
fifo_rden <= 0;
xfer_start<=0;
end
else begin
fifo_rden <= (first_rd_en|xfer_final) & (~empty); //fifo不为空的时候才可以读
xfer_start<= fifo_rden;
end
wire [7:0] cmd;
wire [23:0] addr;
reg [0:480-1] din;
wire [10:0] vadid_length; /* Max suppport DATA_SIZE=2047*8=16376 */
wire [1:0] data_mode; /*00: cmd, 01: cmd+addr, 10: cmd+addr+1wire data, 11: cmd+addr+4wire data*/
wire cs_mode; /*IDLE state, 0: cs=0, 1:cs=1, to support multi data_bursts while keep cs=0*/
wire byte_mode; /* (0:for init) 0->1->2->3, (1: for rgb565 color) 2->3->0->1 */
qspi2 #(.DATA_SIZE(480)) qspi2_inst(
// Input Ports - Single Bit
.clk (qspi_clk),
.rst_n (qspi_clk_rstn),
.cs_mode (cs_mode),
.xfer_start (xfer_start),
// Input Ports - Busses
.addr (addr),
.cmd (cmd),
.data_mode (data_mode),
.din (din),
.vadid_length (vadid_length),
// Output Ports - Single Bit
.csx (csx),
.sck (sck),
.xfer_final (xfer_final),
.xfer_rdy (xfer_rdy),
// Output Ports - Busses
.dout (dout)
// InOut Ports - Single Bit
// InOut Ports - Busses
);
reg [0:511] fifo_dout_rev;
integer i;
always @(*)
begin
for (i = 0; i < 16; i = i + 1) begin
fifo_dout_rev[32*i +: 32] = fifo_dout[(480-32*i) +: 32];
end
end
always @( *) begin
if(byte_mode==0)
for(i=1; i<16; i=i+1) begin
din[(32*(i-1)+0) +:8]= fifo_dout_rev[32*i+24 +:8];
din[(32*(i-1)+8) +:8]= fifo_dout_rev[32*i+16 +:8];
din[(32*(i-1)+16) +:8]= fifo_dout_rev[32*i+8 +:8];
din[(32*(i-1)+24) +:8]= fifo_dout_rev[32*i+0 +:8];
end
else
for(i=1; i<16; i=i+1) begin
din[(32*(i-1)+0) +:8]= fifo_dout_rev[32*i+16 +:8];
din[(32*(i-1)+8) +:8]= fifo_dout_rev[32*i+24 +:8];
din[(32*(i-1)+16) +:8]= fifo_dout_rev[32*i+0 +:8];
din[(32*(i-1)+24) +:8]= fifo_dout_rev[32*i+8 +:8];
end
end
wire [31:0] reg0;
assign reg0=fifo_dout_rev[0:31];
// assign din=fifo_dout_rev[32:511];
assign cmd=reg0[7:0];
assign addr={8'h00, reg0[15:8], 8'h00};
assign {byte_mode,cs_mode,data_mode}=reg0[19:16];
assign vadid_length=reg0[30:20];
//仅供波形分析使用
// reg [31:0] regx1 [0:15];
// always @(*)
// begin
// for (i = 0; i < 16; i = i + 1) begin
// regx1[i]=fifo_dout[32*i+:32];
// end
// end
// reg [31:0] regx2 [0:15];
// always @(*)
// begin
// for (i = 0; i < 16; i = i + 1) begin
// regx2[i]=fifo_dout_rev[32*i+:32];
// end
// end
// reg [31:0] regx3 [0:14];
// always @(*)
// begin
// for (i = 0; i < 15; i = i + 1) begin
// regx3[i]=din[32*i+:32];
// end
// end
// User logic ends
endmodule