Forum Discussion
Altera_Forum
Honored Contributor
8 years ago
module clk_divider_fsm
(
in_clk,
rst_n,
out_clk
);
input in_clk, rst_n;
output out_clk;
parameter prescaler = 10;
parameter BIT_DEPTH = `CLOG2(prescaler);
parameter S0 = 2'b00, S1 = 2'b01, S2 = 2'b10;
parameter CNT_RESET = {BIT_DEPTH{1'b0}};
//parameter CNT_FIRST = {BIT_DEPTH-1{1'b0}, 1'b1};
reg ps, ns;
reg out_change;
reg out;
reg cnt;
initial
begin
ps = S0;
ns = S0;
cnt = CNT_RESET;
out_change = 1'b0;
out = 1'b0;
end
always @ (in_clk)
begin
if(!rst_n)
ps = S0;
else
ps = ns;
// begin
// if(ns != ps)
// ps = ns;
// end
end
always @ (in_clk)
begin
case(ps)
S0: begin
if(in_clk === 1'b1)
begin
out_change <= 1'b1;
ns <= S1;
cnt <= CNT_RESET + 1'b1;
end
else
begin
out_change <= 1'b0;
cnt <= CNT_RESET;
ns <= S0;
end
end
S1: begin
if(in_clk === 1'b0)
begin
if(cnt == prescaler)
begin
cnt <= CNT_RESET + 1'b1;
out_change <= 1'b1;
ns <= S2;
end
else
begin
cnt <= cnt + 1'b1;
out_change <= 1'b0;
ns <= S2;
end
end
else
begin
out_change = 1'b0;
ns = S1;
cnt <= cnt;
end
end
S2: begin
if(in_clk == 1'b1)
begin
if(cnt == prescaler)
begin
cnt <= CNT_RESET + 1'b1;
out_change <= 1'b1;
ns <= S1;
end
else
begin
cnt <= cnt + 1'b1;
out_change <= 1'b0;
ns <= S1;
end
end
else
begin
out_change = 1'b0;
ns = S2;
cnt <= cnt;
end
end
default: begin
out_change <= 1'b0;
cnt <= CNT_RESET;
ns <= S0;
end
endcase
if(!rst_n)
begin
ns <= S0;
cnt <= CNT_RESET;
end
end
always @ (posedge out_change or negedge rst_n)
begin
if(!rst_n)
out <= 1'b0;
else
out <= ~out;
end
assign out_clk = (prescaler == 1) ? (in_clk & rst_n) : out;
endmodule