mirror of
https://github.com/Polprzewodnikowy/SummerCart64.git
synced 2024-12-01 17:44:14 +01:00
108 lines
2.5 KiB
Verilog
108 lines
2.5 KiB
Verilog
module sd_clk (
|
|
input i_clk,
|
|
input i_reset,
|
|
|
|
output reg o_sd_clk,
|
|
|
|
input [1:0] i_sd_clk_config,
|
|
|
|
output reg o_sd_clk_strobe_rising,
|
|
output reg o_sd_clk_strobe_falling
|
|
);
|
|
|
|
// Clock configuration values
|
|
|
|
localparam [1:0] SD_CLK_CONFIG_STOP = 2'd0;
|
|
localparam [1:0] SD_CLK_CONFIG_DIV_256 = 2'd1;
|
|
localparam [1:0] SD_CLK_CONFIG_DIV_4 = 2'd2;
|
|
localparam [1:0] SD_CLK_CONFIG_DIV_2 = 2'd3;
|
|
|
|
|
|
// Clock configuration change detection
|
|
|
|
reg [1:0] r_prev_sd_clk_config;
|
|
|
|
wire w_sd_clk_config_changed = r_prev_sd_clk_config != i_sd_clk_config;
|
|
|
|
always @(posedge i_clk) begin
|
|
if (i_reset) begin
|
|
r_prev_sd_clk_config <= SD_CLK_CONFIG_STOP;
|
|
end else begin
|
|
r_prev_sd_clk_config <= i_sd_clk_config;
|
|
end
|
|
end
|
|
|
|
|
|
// Clock divider
|
|
|
|
reg [7:0] r_sd_clk_counter;
|
|
|
|
always @(posedge i_clk) begin
|
|
if (i_reset || w_sd_clk_config_changed) begin
|
|
r_sd_clk_counter <= 8'd0;
|
|
end else begin
|
|
r_sd_clk_counter <= r_sd_clk_counter + 1'd1;
|
|
end
|
|
end
|
|
|
|
|
|
// Clock divider selector
|
|
|
|
reg r_selected_sd_clk;
|
|
|
|
always @(*) begin
|
|
case (r_prev_sd_clk_config)
|
|
SD_CLK_CONFIG_STOP:
|
|
r_selected_sd_clk = 1'b0;
|
|
SD_CLK_CONFIG_DIV_256:
|
|
r_selected_sd_clk = r_sd_clk_counter[7];
|
|
SD_CLK_CONFIG_DIV_4:
|
|
r_selected_sd_clk = r_sd_clk_counter[1];
|
|
SD_CLK_CONFIG_DIV_2:
|
|
r_selected_sd_clk = r_sd_clk_counter[0];
|
|
endcase
|
|
end
|
|
|
|
|
|
// Clock strobe generation
|
|
|
|
reg r_prev_selected_sd_clk;
|
|
|
|
always @(posedge i_clk) begin
|
|
o_sd_clk_strobe_rising <= 1'b0;
|
|
o_sd_clk_strobe_falling <= 1'b0;
|
|
|
|
if (i_reset) begin
|
|
r_prev_selected_sd_clk <= 1'b0;
|
|
end else begin
|
|
r_prev_selected_sd_clk <= r_selected_sd_clk;
|
|
|
|
if (!r_prev_selected_sd_clk && r_selected_sd_clk) begin
|
|
o_sd_clk_strobe_rising <= 1'b1;
|
|
end
|
|
|
|
if (r_prev_selected_sd_clk && !r_selected_sd_clk) begin
|
|
o_sd_clk_strobe_falling <= 1'b1;
|
|
end
|
|
end
|
|
end
|
|
|
|
|
|
// SD clock generation
|
|
|
|
always @(posedge i_clk) begin
|
|
if (i_reset) begin
|
|
o_sd_clk <= 1'b0;
|
|
end else begin
|
|
if (o_sd_clk_strobe_rising) begin
|
|
o_sd_clk <= 1'b1;
|
|
end
|
|
|
|
if (o_sd_clk_strobe_falling) begin
|
|
o_sd_clk <= 1'b0;
|
|
end
|
|
end
|
|
end
|
|
|
|
endmodule
|