The basic gist is I'm trying to write an audio synthesizer. The note sequencer engine is based on a "tick" of 60Hz. Each note duration is a multiple of 5 ticks, let's call this a beat (even though it's really a thirty-second note). As such, I'd like a 1-clock pulse (strobe?) every tick and a 1-clock pulse every beat (5 ticks). Then I can count beat pulses for note duration. For example, a note could play for 8 beats (40 ticks), then another note for 4 beats (20 ticks), etc. However, I'm struggling to figure out how to do this.
The tick pulse is pretty easy:
localparam CLOCKS_PER_TICK = 415_667; // 25MHz / 60Hz localparam TICK_WIDTH = $clog2(CLOCKS_PER_TICK); reg [TICK_WIDTH-1:0] r_tick_counter = 0; reg r_tick_pulse = 0; always @(posedge i_clk) begin if (r_tick_counter == CLOCKS_PER_TICK) begin r_tick_counter <= 0; r_tick_pulse <= 1; end else begin r_tick_counter <= r_tick_counter + 1; r_tick_pulse <= 0; end end
The beat pulse seems like it should pretty straightforward: Count 5 tick pulses. However, it ends up being fairly complicated, which means I'm likely doing it wrong:
localparam TICKS_PER_BEAT = 5; localparam BEAT_WIDTH = $clog2(TICKS_PER_BEAT); reg [BEAT_WIDTH-1:0] r_beat_counter = 0; reg r_beat_clk = 0; reg r_last_beat_clk = 0; always @(posedge i_clk) begin if (r_tick_pulse) begin if (r_beat_counter == TICKS_PER_BEAT-1) begin r_beat_counter <= 0; r_beat_clk <= ~r_beat_clk; end else begin r_beat_counter <= r_beat_counter + 1; end end r_last_beat_clk <= r_beat_clk; end wire r_beat_pulse = r_beat_clk != r_last_beat_clk;
The idea here is
r_beat_counter counts up on every
4. However, figuring out how to get a 1-clock wide pulse seems to require making a fake "clock"
r_beat_clk and then using
r_last_beat_clk to effectively detect any edge (both pos and neg) in this "clock". This feels overly complicated, though. Is there some simpler way to accomplish this?