Files
retroSoC/rtl/ip/ribp/storage/spisd_init.sv
T
maksyuki 1b4b53c650 feat: refactor RIB to RIBP: Update tests and scripts to reflect RIBP interface changes
- Updated test cases in , , , , , , , and  to replace references from RIB to RIBP.
- Modified file names and paths in tests to align with the new RIBP naming conventions.
- Ensured that all assertions and checks in the tests are consistent with the updated RIBP interfaces and functionality.
- Added a new test for migrating user core RIBP interfaces in .
2026-08-04 10:56:36 +08:00

271 lines
8.1 KiB
Systemverilog

// Copyright 2019 EmbedFire http://www.embedfire.com
// https://github.com/Embedfire-altera <embedfire@embedfire.com>
//
// The first version of this code was derived from EmbedFire sd_init.v. The
// original code is open source on Github, but it doesn't specify an open-source
// license. I'm re-releasing it here under the most compatible license(PSL License).
// If anyone knows what the original license is, please contact <miaoyuchi@ict.ac.cn>.
//
// -- Adaptable modifications are redistributed under compatible License --
//
// Copyright (c) 2023-2026 Yuchi Miao <miaoyuchi@ict.ac.cn>
// retroSoC is licensed under Mulan PSL v2.
// You can use this software according to the terms and conditions of the Mulan PSL v2.
// You may obtain a copy of Mulan PSL v2 at:
// http://license.coscl.org.cn/MulanPSL2
// THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
// EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
// MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
// See the Mulan PSL v2 for more details.
module spisd_init (
input logic clk_i,
input logic rst_n_i,
output logic init_done_o,
output logic spisd_clk_o,
output logic spisd_cs_o,
output logic spisd_mosi_o,
input logic spisd_miso_i
);
localparam CMD0 = {8'h40, 8'h00, 8'h00, 8'h00, 8'h00, 8'h95};
localparam CMD8 = {8'h48, 8'h00, 8'h00, 8'h01, 8'hAA, 8'h87};
localparam CMD55 = {8'h77, 8'h00, 8'h00, 8'h00, 8'h00, 8'hFF};
localparam ACMD41 = {8'h69, 8'h40, 8'h00, 8'h00, 8'h00, 8'hFF};
localparam DIV_FREQ = 200;
localparam OVER_TIME_NUM = 25000;
localparam FSM_IDLE = 3'd0;
localparam FSM_SEND_CMD0 = 3'd1;
localparam FSM_WAIT_CMD0 = 3'd2;
localparam FSM_SEND_CMD8 = 3'd3;
localparam FSM_SEND_CMD55 = 3'd4;
localparam FSM_SEND_ACMD41 = 3'd5;
localparam FSM_INIT_DONE = 3'd6;
logic s_div_clk_d, s_div_clk_q;
logic [7:0] s_div_cnt_d, s_div_cnt_q; // 512 div
logic [6:0] s_boot_cnt_d, s_boot_cnt_q; // count 128
logic [2:0] s_fsm_d, s_fsm_q;
logic s_fir_clk_edge, s_sec_clk_edge;
// resp
logic r_resp_en;
logic [47:0] r_resp_data;
logic r_resp_flag;
logic [ 5:0] r_resp_bit_cnt;
// utils
logic [ 5:0] r_cmd_bit_cnt;
logic [15:0] r_overflow_cnt;
logic r_overflow_en;
// spi if
logic r_init_done;
logic r_spisd_cs, r_spisd_mosi;
assign init_done_o = r_init_done;
assign spisd_clk_o = s_div_clk_q;
assign spisd_cs_o = r_spisd_cs;
assign spisd_mosi_o = r_spisd_mosi;
// fir: fall sec: pos
assign s_fir_clk_edge = s_div_clk_q && (s_div_cnt_q == '0);
assign s_sec_clk_edge = (~s_div_clk_q) && (s_div_cnt_q == '0);
always_comb begin
s_div_cnt_d = s_div_cnt_q;
s_div_clk_d = s_div_clk_q;
if (s_div_cnt_q == '0) begin
s_div_cnt_d = '1;
s_div_clk_d = ~s_div_clk_q;
end else begin
s_div_cnt_d = s_div_cnt_q - 1'b1;
end
end
dffrh #(8) u_div_cnt_dffrh (
clk_i,
rst_n_i,
s_div_cnt_d,
s_div_cnt_q
);
dffrh #(1) u_div_clk_dffrh (
clk_i,
rst_n_i,
s_div_clk_d,
s_div_clk_q
);
always_comb begin
s_boot_cnt_d = s_boot_cnt_q;
if (s_fir_clk_edge) begin
if (s_fsm_q == FSM_IDLE) begin
if (s_boot_cnt_q != '0) s_boot_cnt_d = s_boot_cnt_q - 1'b1;
end else begin
s_boot_cnt_d = '1;
end
end
end
dfferh #(7) u_boot_cnt_dfferh (
clk_i,
rst_n_i,
s_fir_clk_edge,
s_boot_cnt_d,
s_boot_cnt_q
);
always_ff @(posedge clk_i or negedge rst_n_i) begin
if (!rst_n_i) begin
r_resp_en <= '0;
r_resp_data <= '0;
r_resp_flag <= '0;
r_resp_bit_cnt <= '0;
end else begin
if (s_sec_clk_edge) begin
if (spisd_miso_i == 1'b0 && r_resp_flag == 1'b0) begin
r_resp_flag <= 1'b1;
r_resp_data <= {r_resp_data[46:0], spisd_miso_i};
r_resp_bit_cnt <= r_resp_bit_cnt + 6'd1;
r_resp_en <= 1'b0;
end else if (r_resp_flag) begin
r_resp_data <= {r_resp_data[46:0], spisd_miso_i};
r_resp_bit_cnt <= r_resp_bit_cnt + 6'd1;
if (r_resp_bit_cnt == 6'd47) begin
r_resp_flag <= 1'b0;
r_resp_bit_cnt <= '0;
r_resp_en <= 1'b1;
end
end else r_resp_en <= 1'b0;
end
end
end
always_comb begin
s_fsm_d = s_fsm_q;
case (s_fsm_q)
FSM_IDLE: begin
if (s_boot_cnt_q == '0) s_fsm_d = FSM_SEND_CMD0;
end
FSM_SEND_CMD0: begin
if (r_cmd_bit_cnt == 6'd47) s_fsm_d = FSM_WAIT_CMD0;
end
FSM_WAIT_CMD0: begin
if (r_resp_en) begin
if (r_resp_data[47:40] == 8'h01) s_fsm_d = FSM_SEND_CMD8;
else s_fsm_d = FSM_IDLE;
end else if (r_overflow_en) s_fsm_d = FSM_IDLE;
end
FSM_SEND_CMD8: begin
if (r_resp_en) begin
if (r_resp_data[19:16] == 4'b0001) s_fsm_d = FSM_SEND_CMD55;
else s_fsm_d = FSM_IDLE;
end
end
FSM_SEND_CMD55: begin
if (r_resp_en) begin
if (r_resp_data[47:40] == 8'h01) s_fsm_d = FSM_SEND_ACMD41;
end
end
FSM_SEND_ACMD41: begin
if (r_resp_en) begin
if (r_resp_data[47:40] == 8'h00) s_fsm_d = FSM_INIT_DONE;
else s_fsm_d = FSM_SEND_CMD55;
end
end
FSM_INIT_DONE: s_fsm_d = FSM_INIT_DONE;
default: s_fsm_d = FSM_IDLE;
endcase
end
dffer #(3) u_fsm_dffer (
clk_i,
rst_n_i,
s_fir_clk_edge,
s_fsm_d,
s_fsm_q
);
always @(posedge clk_i or negedge rst_n_i) begin
if (!rst_n_i) begin
r_init_done <= '0;
r_spisd_cs <= '1;
r_spisd_mosi <= '1;
r_cmd_bit_cnt <= '0;
r_overflow_cnt <= '0;
r_overflow_en <= '0;
end else begin
if (s_fir_clk_edge) begin
r_overflow_en <= 1'b0;
case (s_fsm_q)
FSM_IDLE: begin
r_spisd_cs <= 1'b1;
r_spisd_mosi <= 1'b1;
end
FSM_SEND_CMD0: begin
r_spisd_cs <= 1'b0;
r_spisd_mosi <= CMD0[6'd47-r_cmd_bit_cnt];
r_cmd_bit_cnt <= r_cmd_bit_cnt + 6'd1;
if (r_cmd_bit_cnt == 6'd47) r_cmd_bit_cnt <= '0;
end
FSM_WAIT_CMD0: begin
r_spisd_mosi <= 1'b1;
if (r_resp_en) r_spisd_cs <= 1'b1;
r_overflow_cnt <= r_overflow_cnt + 1'b1;
if (r_overflow_cnt == OVER_TIME_NUM) r_overflow_en <= 1'b1;
if (r_overflow_en) r_overflow_cnt <= '0;
end
FSM_SEND_CMD8: begin
if (r_cmd_bit_cnt <= 6'd47) begin
r_cmd_bit_cnt <= r_cmd_bit_cnt + 6'd1;
r_spisd_cs <= 1'b0;
r_spisd_mosi <= CMD8[6'd47-r_cmd_bit_cnt];
end else begin
r_spisd_mosi <= 1'b1;
if (r_resp_en) begin
r_spisd_cs <= 1'b1;
r_cmd_bit_cnt <= '0;
end
end
end
FSM_SEND_CMD55: begin
if (r_cmd_bit_cnt <= 6'd47) begin
r_cmd_bit_cnt <= r_cmd_bit_cnt + 6'd1;
r_spisd_cs <= 1'b0;
r_spisd_mosi <= CMD55[6'd47-r_cmd_bit_cnt];
end else begin
r_spisd_mosi <= 1'b1;
if (r_resp_en) begin
r_spisd_cs <= 1'b1;
r_cmd_bit_cnt <= '0;
end
end
end
FSM_SEND_ACMD41: begin
if (r_cmd_bit_cnt <= 6'd47) begin
r_cmd_bit_cnt <= r_cmd_bit_cnt + 6'd1;
r_spisd_cs <= 1'b0;
r_spisd_mosi <= ACMD41[6'd47-r_cmd_bit_cnt];
end else begin
r_spisd_mosi <= 1'b1;
if (r_resp_en) begin
r_spisd_cs <= 1'b1;
r_cmd_bit_cnt <= '0;
end
end
end
FSM_INIT_DONE: begin
r_init_done <= 1'b1;
r_spisd_cs <= 1'b1;
r_spisd_mosi <= 1'b1;
end
default: begin
r_spisd_cs <= 1'b1;
r_spisd_mosi <= 1'b1;
end
endcase
end
end
end
endmodule