1
0
mirror of git://projects.qi-hardware.com/nn-usb-fpga.git synced 2025-01-09 20:00:14 +02:00
nn-usb-fpga/lm32/logic/sakc/rtl/wb_timer/wb_timer.v
2010-05-25 21:49:58 -05:00

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