module SIM_spi_flash_TB();
localparam P_CLK_CYCLE =20;
reg clk,rst;
initial
begin
rst ='d1;
#100;
@(posedge clk) rst='d0;
end
localparam P_OP_TYPE_INS =0,
P_OPREAD =1,
P_OP_WRITE =2;
always
begin
clk =0;
#(P_CLK_CYCLE/2);
clk=1;
#(P_CLK_CYCLE/2);
end
reg [31:0] i_user_op_data ;
reg [1:0] i_user_op_type ;
reg [15:0] i_user_op_len ;
reg [15:0] i_user_clk_len ;
reg i_user_op_valid ;
reg [7:0] r_user_data ;
reg r_user_valid;
reg i_user_write_data;
reg r_user_read_data;
wire o_user_op_ready ;
wire w_spi_clk;
wire w_spi_cs ;
wire w_spi_mosi;
wire w_user_ready ;
wire [7:0] w_user_read_data ;
wire w_user_read_valid;
wire w_user_active;
wire o_user_write_req;
assign w_user_active = i_user_op_valid&o_user_op_ready;
spi_flash_drive#(
. P_DATA_WIDTH (8),
. P_CPOL (0),
. P_READ_DATA_WIDTH (8),
. P_CPHL (0),
. P_OP_LEN (32)
)
spi_flash_drive_u0
(
. i_clk (clk),
. i_rst (rst),
. o_spi_clk ( ) ,
. o_spi_cs ( ),
. o_spi_mosi(),
. i_spi_miso(),
. i_user_op_data (i_user_op_data ),
. i_user_op_type (i_user_op_type ),
. i_user_op_len (i_user_op_len ),
. i_user_clk_len (i_user_clk_len ),
. i_user_op_valid (i_user_op_valid ),
. o_user_op_ready (o_user_op_ready ),
. o_user_read_data (w_user_read_data),
. o_user_read_valid(w_user_read_valid),
. i_user_write_data(i_user_write_data),
. o_user_write_req (o_user_write_req)
);
always@(posedge clk, posedge rst)
begin
if(rst)
i_user_op_valid <= 'd0;
else if(o_user_op_ready)
i_user_op_valid <= 'd1;
else
i_user_op_valid <= 'd0;
end
always@(posedge clk, posedge rst)
begin
if(rst)begin
i_user_op_data <= 'd0;
i_user_op_type <= 'd0;
i_user_op_len <= 'd0;
i_user_clk_len <= 'd0;
end
else if(o_user_op_ready)begin
i_user_op_data <= {8'h55,8'h01,8'h02,8'h03};
i_user_op_type <= P_OP_WRITE;
i_user_op_len <= 'd32;
i_user_clk_len <= 32+(8<<(2-1));
end
else begin
i_user_op_data <= i_user_op_data ;
i_user_op_type <= i_user_op_type ;
i_user_op_len <= i_user_op_len ;
i_user_clk_len <= i_user_clk_len ;
end
end
always@(posedge clk,posedge rst)
begin
if(rst)
i_user_write_data <='d0;
else if(o_user_write_req)
i_user_write_data <= i_user_write_data+1;
else
i_user_write_data <= i_user_write_data;
end
always@(posedge clk,posedge rst)
begin
if(rst)
r_user_read_data <='d0;
else if(o_user_read_valid)
r_user_read_data <=o_user_read_data;
else
r_user_read_data <= r_user_read_data;
end
endmodule
module spi_flash_top(
input i_clk,
output o_spi_clk,
output o_spi_cs,
output o_spi_mosi,
input i_spi_miso
);
wire w_clk_5Mhz;
wire w_clk_5Mhz_lock;
wire w_user_ready ;
wire [7:0] w_user_read_data ;
wire w_user_read_valid;
SYSTEM_CLK SYSTEM_CLK_U0
(
.clk_in1(i_clk),
// Clock out ports
.clk_out1(clk_out1), // output clk_out1
// Status and control signals
.locked( w_clk_5Mhz_lock) // output locked
// Clock in ports
); // input clk_in1
spi_flash_drive#(
. P_DATA_WIDTH (8),
. P_CPOL (0),
. P_READ_DATA_WIDTH (8),
. P_CPHL (0)
)
spi_flash_drive_u0
(
. i_clk (clk),
. i_rst ( ~w_clk_5Mhz_lock),
. o_spi_clk (o_spi_clk) ,
. o_spi_cs (o_spi_cs),
. o_spi_mosi(o_spi_mosi),
. i_spi_miso(i_spi_miso),
. o_user_read_data (w_user_read_data),
. o_user_read_valid(w_user_read_valid)
);
endmodule
module spi_flash_drive#(
parameter P_DATA_WIDTH=8,
P_CPOL =0,
P_READ_DATA_WIDTH =8,
P_CPHL =0,
P_OP_LEN =32
)
(
input i_clk,
input i_rst,
output o_spi_clk,
output o_spi_cs,
output o_spi_mosi,
input i_spi_miso,
input [P_OP_LEN -1:0] i_user_op_data,
input [1:0] i_user_op_type,
input [15:0] i_user_op_len,
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
);
/***************function**************/
/***************parameter*************/
localparam P_OP_TYPE_INS =0,
P_OP_READ =1,
P_OP_WRITE =2;
/***************port******************/
/***************mechine***************/
/***************reg*******************/
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 [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 r_run;
reg [15:0] r_cnt;
reg r_spi_cnt;
reg [P_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 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 w_user_active = i_user_op_valid & o_user_op_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****************/
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 if(r_spi_cnt)
// r_user_data <=r_user_data <<1;
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
always@(posedge i_clk,posedge i_rst)
begin
if(i_rst)
r_user_op_data <= 'd0;
else if(ro_user_write_req_1d)
r_user_op_data<= i_user_op_data;
else if(r_spi_cnt)
r_user_op_data <= r_user_op_data <<1;
else
r_user_op_data <= r_user_op_data;
end
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
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==r_user_clk_len-1)
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_op_data[P_OP_LEN-1];
else if(r_spi_cnt && r_cnt < r_user_op_len)
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
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==30) || r_write_cnt == 15)
ro_user_write_req <='d1;
else
ro_user_write_req <= 'd0;
end
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_1d;
end
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
/*always@(posedge i_clk,posedge i_rst)
begin
if(i_rst)
r_write_cnt <='d0;
else if(r_write_cnt == P_DATA_WIDTH -1)
r_write_cnt <= 'd0;
else if((ro_user_write_req || (r_write_cnt&&r_spi_cnt) )&& r_spi_cnt &&r_user_op_type ==P_OP_WRITE)
r_write_cnt <= r_write_cnt+1;
else
r_write_cnt <= r_write_cnt;
end
*/
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>0)
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_spi_cnt)
else if(r_cnt>=P_OP_LEN-1)
ro_user_read_data <= {ro_user_read_data[P_DATA_WIDTH-2:0],i_spi_miso};
// else if(w_user_active)
else
ro_user_read_data <= ro_user_read_data;
end
always@(posedge ro_spi_clk, posedge i_rst)
begin
if(i_rst)
r_read_cnt <='d0;
else if(r_read_cnt ==7)
r_read_cnt <='d0;
else if(r_cnt>=P_OP_LEN-1)
r_read_cnt <= r_read_cnt +1;
else
end
always@(posedge ro_spi_clk,posedge i_rst)
begin
if(i_rst)
ro_user_read_valid <= 'd0;
else if(r_read_cnt ==7)
ro_user_read_valid <= 'd1;
else
ro_user_read_valid <= 'd0;
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
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
endmodule