mirror of
git://projects.qi-hardware.com/nn-usb-fpga.git
synced 2025-01-09 20:00:14 +02:00
145 lines
3.3 KiB
Verilog
145 lines
3.3 KiB
Verilog
//---------------------------------------------------------------------------
|
|
//
|
|
// Wishbone Timer
|
|
//
|
|
// Register Description:
|
|
//
|
|
// 0x00 TCR0
|
|
// 0x04 COMPARE0
|
|
// 0x08 COUNTER0
|
|
// 0x0C TCR1
|
|
// 0x10 COMPARE1
|
|
// 0x14 COUNTER1
|
|
//
|
|
// TCRx:
|
|
// +-------------------+-------+-------+-------+-------+
|
|
// | 28'b0 | EN | AR | IRQEN | TRIG |
|
|
// +-------------------+-------+-------+-------+-------+
|
|
//
|
|
// EN i (rw) if set to '1', COUNTERX counts upwards until it reaches
|
|
// COMPAREX
|
|
// AR (rw) AutoRecwstartload -- if COUNTER reaches COMPAREX, shall we
|
|
// restart at 1, or disable this counter?
|
|
// IRQEN (rw) Indicate interrupt condition when triggered?
|
|
// TRIG (ro)
|
|
//
|
|
//---------------------------------------------------------------------------
|
|
|
|
module wb_timer #(
|
|
parameter clk_freq = 50000000
|
|
) (
|
|
input clk,
|
|
input reset,
|
|
// Wishbone interface
|
|
input wb_stb_i,
|
|
input wb_cyc_i,
|
|
output wb_ack_o,
|
|
input wb_we_i,
|
|
input [31:0] wb_adr_i,
|
|
input [3:0] wb_sel_i,
|
|
input [31:0] wb_dat_i,
|
|
output reg [31:0] wb_dat_o,
|
|
//
|
|
output [1:0] intr
|
|
);
|
|
|
|
//---------------------------------------------------------------------------
|
|
//
|
|
//---------------------------------------------------------------------------
|
|
|
|
reg irqen0, irqen1;
|
|
reg trig0, trig1;
|
|
reg en0, en1;
|
|
reg ar0, ar1;
|
|
|
|
wire [31:0] tcr0 = { 28'b0, en0, ar0, irqen0, trig0 };
|
|
wire [31:0] tcr1 = { 28'b0, en1, ar1, irqen1, trig1 };
|
|
|
|
reg [31:0] counter0;
|
|
reg [31:0] counter1;
|
|
|
|
reg [31:0] compare0;
|
|
reg [31:0] compare1;
|
|
|
|
wire match0 = (counter0 == compare0);
|
|
wire match1 = (counter1 == compare1);
|
|
|
|
assign intr = { trig1, trig0 };
|
|
|
|
reg ack;
|
|
assign wb_ack_o = wb_stb_i & wb_cyc_i & ack;
|
|
|
|
wire wb_rd = wb_stb_i & wb_cyc_i & ~wb_we_i;
|
|
wire wb_wr = wb_stb_i & wb_cyc_i & wb_we_i;
|
|
|
|
always @(posedge clk)
|
|
begin
|
|
if (reset) begin
|
|
ack <= 0;
|
|
en0 <= 0;
|
|
en1 <= 0;
|
|
ar0 <= 0;
|
|
ar1 <= 0;
|
|
trig0 <= 0;
|
|
trig1 <= 0;
|
|
counter0 <= 0;
|
|
counter1 <= 0;
|
|
compare0 <= 32'hFFFFFFFF;
|
|
compare1 <= 32'hFFFFFFFF;
|
|
end else begin
|
|
|
|
// Handle counter 0
|
|
if ( en0 & ~match0) counter0 <= counter0 + 1;
|
|
if ( en0 & match0) trig0 <= 1;
|
|
if ( ar0 & match0) counter0 <= 1;
|
|
if (~ar0 & match0) en0 <= 0;
|
|
|
|
// Handle counter 1
|
|
if ( en1 & ~match1) counter1 <= counter1 + 1;
|
|
if ( en1 & match1) trig1 <= 1;
|
|
if ( ar1 & match1) counter1 <= 1;
|
|
if (~ar1 & match1) en1 <= 0;
|
|
|
|
// Handle WISHBONE access
|
|
ack <= 0;
|
|
|
|
if (wb_rd & ~ack) begin // read cycle
|
|
ack <= 1;
|
|
|
|
case (wb_adr_i[7:0])
|
|
'h00: wb_dat_o <= tcr0;
|
|
'h04: wb_dat_o <= compare0;
|
|
'h08: wb_dat_o <= counter0;
|
|
'h0c: wb_dat_o <= tcr1;
|
|
'h10: wb_dat_o <= compare1;
|
|
'h14: wb_dat_o <= counter1;
|
|
default: wb_dat_o <= 32'b0;
|
|
endcase
|
|
end else if (wb_wr & ~ack ) begin // write cycle
|
|
ack <= 1;
|
|
|
|
case (wb_adr_i[7:0])
|
|
'h00: begin
|
|
trig0 <= 0;
|
|
irqen0 <= wb_dat_i[1];
|
|
ar0 <= wb_dat_i[2];
|
|
en0 <= wb_dat_i[3];
|
|
end
|
|
'h04: compare0 <= wb_dat_i;
|
|
'h08: counter0 <= wb_dat_i;
|
|
'h0c: begin
|
|
trig1 <= 0;
|
|
irqen1 <= wb_dat_i[1];
|
|
ar1 <= wb_dat_i[2];
|
|
en1 <= wb_dat_i[3];
|
|
end
|
|
'h10: compare1 <= wb_dat_i;
|
|
'h14: counter1 <= wb_dat_i;
|
|
endcase
|
|
end
|
|
end
|
|
end
|
|
|
|
|
|
endmodule
|