SPI的CPHA固定为0,CPOL可配置,仿真时可参考的spi_slave 模块代码如下:
module spi_slave (
input I_SPI_DI ,
output reg O_SPI_DO ,
input I_SPI_ENB ,
input I_SPI_CLK
);
parameter p_SCLK_CNT_WIDTH = 5 ;
parameter p_OP_ADDR = 13 ;
parameter p_SPI_CPHA = 0 ;
localparam p_SPI_CPOL = 0 ;
reg [p_SCLK_CNT_WIDTH -1 :0] r_SCLK_CNT ;
reg r_WR_FLAG ;
reg [p_OP_ADDR -1 :0] r_OP_ADDR ;
reg [ 7:0] r_WR_DATA ;
generate
if(p_SPI_CPHA == 0) begin
always @(posedge I_SPI_CLK or posedge I_SPI_ENB)
begin
if(I_SPI_ENB)
r_SCLK_CNT <= 'b0;
else
r_SCLK_CNT <= r_SCLK_CNT + 'b1;
end
always @(posedge I_SPI_CLK or posedge I_SPI_ENB)
begin
if(I_SPI_ENB) begin
r_WR_FLAG <= 'b1;
end else begin
if(r_SCLK_CNT == 'b0)
r_WR_FLAG <= I_SPI_DI;
else
r_WR_FLAG <= r_WR_FLAG;
end
end
always @(posedge I_SPI_CLK)
begin
if(I_SPI_ENB) begin
r_OP_ADDR <= 'b1;
end else begin
if((r_SCLK_CNT >= 'b1) && (r_SCLK_CNT <= 'd15) )
r_OP_ADDR <= {r_OP_ADDR,I_SPI_DI};
else
r_OP_ADDR <= r_OP_ADDR;
end
end
always @(posedge I_SPI_CLK)
begin
if((r_SCLK_CNT >= 'd16) && (r_WR_FLAG == 'b1))
r_WR_DATA <= {r_WR_DATA,I_SPI_DI};
else
r_WR_DATA <= r_WR_DATA;
end
always @(negedge I_SPI_CLK or posedge I_SPI_ENB)
begin
if(I_SPI_ENB) begin
O_SPI_DO <= 'b1;
end else begin
if(r_WR_FLAG == 'b0)
O_SPI_DO <= r_WR_DATA[23-r_SCLK_CNT];
else
O_SPI_DO <= O_SPI_DO;
end
end
end else begin
always @(negedge I_SPI_CLK or posedge I_SPI_ENB)
begin
if(I_SPI_ENB)
r_SCLK_CNT <= 'b0;
else
r_SCLK_CNT <= r_SCLK_CNT + 'b1;
end
always @(negedge I_SPI_CLK or posedge I_SPI_ENB)
begin
if(I_SPI_ENB) begin
r_WR_FLAG <= 'b1;
end else begin
if(r_SCLK_CNT == 'b0)
r_WR_FLAG <= I_SPI_DI;
else
r_WR_FLAG <= r_WR_FLAG;
end
end
always @(negedge I_SPI_CLK)
begin
if(I_SPI_ENB) begin
r_OP_ADDR <= 'b1;
end else begin
if((r_SCLK_CNT >= 'b1) && (r_SCLK_CNT <= 'd15) )
r_OP_ADDR <= {r_OP_ADDR,I_SPI_DI};
else
r_OP_ADDR <= r_OP_ADDR;
end
end
always @(negedge I_SPI_CLK)
begin
if((r_SCLK_CNT >= 'd16) && (r_WR_FLAG == 'b1))
r_WR_DATA <= {r_WR_DATA,I_SPI_DI};
else
r_WR_DATA <= r_WR_DATA;
end
always @(posedge I_SPI_CLK or posedge I_SPI_ENB)
begin
if(I_SPI_ENB) begin
O_SPI_DO <= 'b1;
end else begin
if(r_WR_FLAG == 'b0)
O_SPI_DO <= r_WR_DATA[23-r_SCLK_CNT];
else
O_SPI_DO <= O_SPI_DO;
end
end
end
endgenerate
endmodule