Forum Discussion
Altera_Forum
Honored Contributor
8 years agomodule 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 [1:0] ps, ns; reg out_change; reg out; reg [BIT_DEPTH:0] 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