blob: 76f09f2241eae2270c838093025fc28617bce5fe [file] [log] [blame]
`default_nettype none
module timer_wb(
`ifdef USE_POWER_PINS
inout vccd1, // User area 1 1.8V supply
inout vssd1, // User area 1 digital ground
`endif
// RCC
input wire i_clk,
input wire i_reset,
// Trigger out signal
output wire o_timer_trigger,
// Wishbone
input wire [31:0] i_wb_adr,
input wire [31:0] i_wb_dat,
input wire [3:0] i_wb_sel,
input wire i_wb_we,
input wire i_wb_cyc,
input wire i_wb_stb,
output reg [31:0] o_wb_dat,
output reg o_wb_ack
);
// Default prescaler value. Reloaded on reset.
parameter DEFAULT_PRESCALER = 32'hFFFF_FFFF;
// Prescaler value. Reloaded onto the downcounter on update.
reg [31:0] prescaler = DEFAULT_PRESCALER;
// Downcounter. Trigger output is latched high when this hits zero.
reg [31:0] downcounter = DEFAULT_PRESCALER;
// Register the output trigger signal
reg timer_trigger = 0;
assign o_timer_trigger = timer_trigger;
// Bit indices for the flags register
localparam wb_r_FLAGS__TRIGGER = 0;
// Flags register is just a collection of bits, in this case just the trigger
wire [31:0] flags;
assign flags[wb_r_FLAGS__TRIGGER] = timer_trigger;
assign flags[31:1] = 0;
// Wishbone register addresses
// Each register is 32 bits wide
localparam
wb_r_PRESCALER = 1'b0,
wb_r_FLAGS = 1'b1,
wb_r_MAX = 1'b1;
// Since the incoming wishbone address from the CPU increments by 4 bytes, we
// need to right shift by 2 to get the register index
localparam reg_sel_bits = $clog2(wb_r_MAX + 1);
wire [reg_sel_bits-1:0] register_index = i_wb_adr[reg_sel_bits+1:2];
always @(posedge i_clk) begin
if (i_reset) begin
o_wb_ack <= 0;
prescaler <= DEFAULT_PRESCALER;
downcounter <= DEFAULT_PRESCALER;
timer_trigger <= 1'b0;
end else begin
// Handle the downcounter
if (downcounter > 0) begin
downcounter <= downcounter - 1;
end else begin
downcounter <= prescaler;
timer_trigger <= 1'b1;
end
// Wishbone interface logic
o_wb_ack <= 1'b0;
if (i_wb_cyc && i_wb_stb && !o_wb_ack) begin
o_wb_ack <= 1'b1;
// Register read
case (register_index)
wb_r_PRESCALER: o_wb_dat <= prescaler;
wb_r_FLAGS: o_wb_dat <= flags;
endcase
// Register write
if (i_wb_we) begin
case (register_index)
wb_r_PRESCALER: begin
// Load the new prescaler, also reset the downcounter
prescaler <= i_wb_dat;
downcounter <= i_wb_dat;
end
wb_r_FLAGS: begin
// If the trigger bit is written, clear the trig state
if (i_wb_dat[wb_r_FLAGS__TRIGGER])
timer_trigger <= 1'b0;
end
endcase
end
end
end
end
endmodule