|
![](static/image/common/ico_lz.png)
楼主 |
发表于 2021-9-2 23:33:18
|
显示全部楼层
学习到了,按照两位大神的建议重新改了一下:
module quad_spi_ctrl(
mem_data_i,
mem_data_o,
mem_addr_i,
mem_sel_i,
mem_we_i,
mem_cyc_i,
mem_stb_i,
mem_ack_o,
mem_err_o,
mem_rty_o,
mem_clk_i,
mem_rst_i,
spi_ctrl_cs,
spi_ctrl_clk,
spi_ctrl_io
);
parameter CRC_CODE = 16'h1021;
parameter NO_QUAD_SPI = 0 ;
parameter SPI_WIDTH = NO_QUAD_SPI ? 2 : 4;
input [31:0] mem_data_i;
output reg [31:0] mem_data_o;
input [31:0] mem_addr_i;
input [3:0] mem_sel_i;
input mem_we_i;
input mem_cyc_i;
input mem_stb_i;
output reg mem_ack_o;
output mem_err_o;
output mem_rty_o;
input mem_clk_i;
input mem_rst_i;
output spi_ctrl_cs;
output reg spi_ctrl_clk;
inout [SPI_WIDTH-1:0] spi_ctrl_io;
//---------------------------------------------------
// outputs
reg [31:0] reg_sbuf;
reg [31:0] reg_rbuf;
reg [1:0] state;
reg [4:0] xmit_cnt;
reg idle;
reg spi_cs;
reg [7:0] clk_div;
reg [8:0] div_cnt;
reg spi_mode;
reg [15:0] crc16_reg;
assign mem_err_o = 1'b0;
assign mem_rty_o = 1'b0;
wire quad_spi_io[3:0];
generate
if(NO_QUAD_SPI == 0) begin
assign quad_spi_io[0] = (state[0]) ? reg_sbuf[28] : reg_sbuf[31];
assign spi_ctrl_io[0] = (state[0]^state[1] ) ? 1'bz : quad_spi_io[0];
assign spi_ctrl_io[1] = (state[1:0] == 2'b11) ? reg_sbuf[29] : 1'bz ;
assign quad_spi_io[2] = (state[1:0]==2'b11) ? reg_sbuf[30] : 1'b1 ;
assign spi_ctrl_io[2] = (state[1:0]==2'b10) ? 1'bz : quad_spi_io[2];
assign quad_spi_io[3] = (state[1:0]==2'b11) ? reg_sbuf[31] : 1'b1 ;
assign spi_ctrl_io[3] = (state[1:0]==2'b10) ? 1'bz : quad_spi_io[3];
end
else begin
assign spi_ctrl_io[0] = reg_sbuf[31];
assign spi_ctrl_io[1] = 1'bz;
end
endgenerate
assign spi_ctrl_cs = spi_cs ;
wire div_trig = ( div_cnt == clk_div );
wire stb = mem_cyc_i & mem_stb_i;
wire wb_rw_ctrl_reg = (mem_addr_i[3:2]==2'b00);
wire wb_rw_data_reg = (mem_addr_i[3:2]==2'b01);
always @(posedge mem_clk_i)
if(mem_rst_i) begin
state <= 2'b01;
xmit_cnt[4:0] <= 0;
idle <= 1'b1;
spi_cs <= 1'b1;
spi_ctrl_clk <= 1'b0;
reg_sbuf <= 32'hffffffff;
reg_rbuf <= 32'hffffffff;
mem_ack_o <= 1'b0;
clk_div <= 8'b0;
spi_mode <= 1'b0;
end else begin
mem_ack_o <= idle & stb ;
if(div_trig || idle) begin
div_cnt <= 8'b0;
end else begin
div_cnt <= div_cnt + 1'b1;
end
if(idle) begin
if(stb) begin
if(mem_we_i) begin
if( mem_sel_i[0] && wb_rw_ctrl_reg )begin
state <= mem_data_i[7:6] ;
idle <= mem_data_i[5];
xmit_cnt[4:0] <= mem_data_i[4:0] ;
end
if(wb_rw_data_reg) begin
reg_sbuf[7:0] <= mem_sel_i[0] ? mem_data_i[7:0] : reg_sbuf[7:0];
reg_sbuf[15:8] <= mem_sel_i[1] ? mem_data_i[15:8] : reg_sbuf[15:8];
reg_sbuf[23:16] <= mem_sel_i[2] ? mem_data_i[23:16] : reg_sbuf[23:16];
reg_sbuf[31:24] <= mem_sel_i[3] ? mem_data_i[31:24] : reg_sbuf[31:24];
end
if( mem_sel_i[2] && wb_rw_ctrl_reg ) begin
clk_div <= mem_data_i[23:16];
end
if( mem_sel_i[1] && wb_rw_ctrl_reg ) begin
spi_cs <= mem_data_i[8];
spi_ctrl_clk <= mem_data_i[9];
spi_mode <= mem_data_i[10];
if(mem_data_i[11]) begin
crc16_reg <= 16'b0;
end
end
end else begin
mem_data_o <= wb_rw_data_reg ? reg_rbuf : {crc16_reg ,4'b0 , 1'b0 , spi_mode , spi_ctrl_clk , spi_cs , state,idle,xmit_cnt};
end
end
end else if(div_trig) begin
spi_ctrl_clk <= ~spi_ctrl_clk;
case(state)
2'b00: begin
xmit_cnt[4:0] <= xmit_cnt[4:0] + spi_ctrl_clk;
if(xmit_cnt[4:0] == 5'b11111 && spi_ctrl_clk)
idle <= 1;
if( spi_ctrl_clk ^ spi_mode ) begin
reg_sbuf <= {reg_sbuf[30:0],1'b1};
end else begin
reg_rbuf <= {reg_rbuf[30:0],spi_ctrl_io[1]};
crc16_reg <= (spi_ctrl_io[1] ^ crc16_reg[15]) ?( { crc16_reg[14:0] , 1'b0 } ^ CRC_CODE) : { crc16_reg[14:0] , 1'b0 } ;
end
end
2'b01: begin
xmit_cnt[4:1] <= xmit_cnt[4:1] + spi_ctrl_clk;
if(xmit_cnt[4:1] == 4'b1111 && spi_ctrl_clk)
idle <= 1;
if( !spi_ctrl_clk )
reg_rbuf <= {reg_rbuf[29:0],spi_ctrl_io[1:0] };
end
2'b10: begin
xmit_cnt[4:2] <= xmit_cnt[4:2] + spi_ctrl_clk;
if(xmit_cnt[4:2] == 3'b111 && spi_ctrl_clk)
idle <= 1;
if( !spi_ctrl_clk )
reg_rbuf <= {reg_rbuf[32-SPI_WIDTH-1:0] , spi_ctrl_io[SPI_WIDTH-1:0] };
end
2'b11: begin
xmit_cnt[4:2] <= xmit_cnt[4:2] + spi_ctrl_clk;
if(xmit_cnt[4:2] == 3'b111 && spi_ctrl_clk)
idle <= 1;
if( spi_ctrl_clk )
reg_sbuf <= {reg_sbuf[27:0] , 4'b1111 };
end
endcase
end
end
endmodule
|
|