blob: adffe0e05960e171cecaf37b34d2ddb176bfb3b2 (
plain) (
blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
|
`timescale 1ns / 1ps
module clock_divider (
input wire clk_in,
input wire rst_n,
output wire clk_12mhz,
output wire clk_50mhz,
output wire clk_sdio,
output wire clk_spi
);
reg [1:0] div_counter_50mhz;
reg [7:0] div_counter_sdio;
reg [7:0] div_counter_spi;
reg clk_50mhz_reg;
reg clk_sdio_reg;
reg clk_spi_reg;
reg [7:0] sdio_div_ratio;
reg [7:0] spi_div_ratio;
reg sdio_clk_en;
reg spi_clk_en;
assign clk_12mhz = clk_in;
assign clk_50mhz = clk_50mhz_reg;
assign clk_sdio = sdio_clk_en ? clk_sdio_reg : 1'b0;
assign clk_spi = spi_clk_en ? clk_spi_reg : 1'b0;
always @(posedge clk_in or negedge rst_n) begin
if (!rst_n) begin
div_counter_50mhz <= 2'b00;
clk_50mhz_reg <= 1'b0;
end else begin
div_counter_50mhz <= div_counter_50mhz + 1;
case (div_counter_50mhz)
2'b00: clk_50mhz_reg <= 1'b1;
2'b01: clk_50mhz_reg <= 1'b1;
2'b10: clk_50mhz_reg <= 1'b0;
2'b11: clk_50mhz_reg <= 1'b0;
endcase
end
end
always @(posedge clk_50mhz_reg or negedge rst_n) begin
if (!rst_n) begin
div_counter_sdio <= 8'd0;
clk_sdio_reg <= 1'b0;
sdio_div_ratio <= 8'd1;
end else if (sdio_clk_en) begin
if (div_counter_sdio >= sdio_div_ratio) begin
div_counter_sdio <= 8'd0;
clk_sdio_reg <= ~clk_sdio_reg;
end else begin
div_counter_sdio <= div_counter_sdio + 1;
end
end else begin
div_counter_sdio <= 8'd0;
clk_sdio_reg <= 1'b0;
end
end
always @(posedge clk_50mhz_reg or negedge rst_n) begin
if (!rst_n) begin
div_counter_spi <= 8'd0;
clk_spi_reg <= 1'b0;
spi_div_ratio <= 8'd1;
end else if (spi_clk_en) begin
if (div_counter_spi >= spi_div_ratio) begin
div_counter_spi <= 8'd0;
clk_spi_reg <= ~clk_spi_reg;
end else begin
div_counter_spi <= div_counter_spi + 1;
end
end else begin
div_counter_spi <= 8'd0;
clk_spi_reg <= 1'b0;
end
end
always @(posedge clk_50mhz_reg or negedge rst_n) begin
if (!rst_n) begin
sdio_clk_en <= 1'b0;
spi_clk_en <= 1'b0;
end else begin
sdio_clk_en <= 1'b1;
spi_clk_en <= 1'b1;
end
end
task set_sdio_frequency;
input [7:0] divider;
begin
sdio_div_ratio <= divider;
end
endtask
task set_spi_frequency;
input [7:0] divider;
begin
spi_div_ratio <= divider;
end
endtask
task enable_sdio_clock;
input enable;
begin
sdio_clk_en <= enable;
end
endtask
task enable_spi_clock;
input enable;
begin
spi_clk_en <= enable;
end
endtask
function [7:0] calc_sdio_divider;
input [7:0] freq_mhz;
begin
if (freq_mhz == 0)
calc_sdio_divider = 8'd0;
else
calc_sdio_divider = 8'd25 / freq_mhz;
end
endfunction
function [7:0] calc_spi_divider;
input [7:0] freq_mhz;
begin
if (freq_mhz == 0)
calc_spi_divider = 8'd0;
else
calc_spi_divider = 8'd25 / freq_mhz;
end
endfunction
initial begin
sdio_div_ratio = calc_sdio_divider(8'd25);
spi_div_ratio = calc_spi_divider(8'd25);
end
endmodule
|