Skip to content

Commit 97314af

Browse files
committed
rtl: add OBI timer
1 parent 9f3e3ac commit 97314af

File tree

2 files changed

+122
-0
lines changed

2 files changed

+122
-0
lines changed

rtl/obi_timer/obi_timer.sv

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
module obi_timer #(
2+
parameter type obi_req_t = logic,
3+
parameter type obi_rsp_t = logic
4+
) (
5+
input logic clk_i,
6+
input logic rst_ni,
7+
input obi_req_t obi_req_i,
8+
output obi_rsp_t obi_rsp_o,
9+
output logic expired_o,
10+
output logic overflow_o
11+
);
12+
13+
// Registers
14+
logic [31:0] count_d, count_q;
15+
logic [31:0] compare_d, compare_q;
16+
logic enable_d, enable_q;
17+
18+
// Internal signals
19+
obi_req_t obi_req_d, obi_req_q;
20+
logic err_d, err_q;
21+
logic [31:0] rdata_d, rdata_q;
22+
23+
assign obi_req_d = obi_req_i;
24+
25+
// bit enable mask: defines which bits are written to by wdata of the OBI request
26+
logic [31:0] be_mask;
27+
for (genvar i = 0; unsigned'(i) < 32/8; ++i ) begin : gen_write_mask
28+
assign be_mask[8*i +: 8] = {8{obi_req_i.a.be[i]}};
29+
end
30+
31+
// Output assignment
32+
assign expired_o = (compare_q != 32'h0 && compare_q == count_q) ? 1'b1 1'b0;
33+
assign overflow_o = (count_q == 32'hffff_ffff) ? 1'b1 : 1'b0;
34+
35+
always_comb begin : obi_response
36+
obi_rsp_o = '0;
37+
obi_rsp_o.gnt = 1'b1;
38+
obi_rsp_o.rvalid = obi_req_q.req;
39+
obi_rsp_o.r.err = err_q;
40+
obi_rsp_o.r.rid = obi_req_q.a.aid;
41+
obi_rsp_o.r.rdata = rdata_q;
42+
end
43+
44+
always_comb begin
45+
err_d = '0;
46+
rdata_d = '0;
47+
count_d = count_q;
48+
compare_d = compare_q;
49+
enable_d = enable_q;
50+
51+
if (expired_o)
52+
count_d = '0;
53+
else if (enable_q)
54+
count_d = count_q + 1;
55+
56+
if (obi_req_i.req) begin
57+
58+
if (obi_req_i.a.we) begin : write
59+
automatic logic [31:0] wdata = obi_req_i.a.wdata & be_mask;
60+
unique case ({obi_req_i.a.addr[IntAddrWidth-1:2], 2'b00})
61+
OBI_TIMER_COUNT_OFFSET: begin
62+
count_d = wdata;
63+
end
64+
OBI_TIMER_COMPARE_OFFSET: begin
65+
compare_d = wdata;
66+
count_d = '0;
67+
end
68+
OBI_TIMER_ENABLE_OFFSET: begin
69+
enable_d = wdata[0];
70+
end
71+
default: begin
72+
err_d = 1'b1;
73+
end
74+
endcase
75+
76+
end else begin : read
77+
unique case ({obi_req_i.a.addr[IntAddrWidth-1:2], 2'b00})
78+
OBI_TIMER_COUNT_OFFSET: begin
79+
rdata_d = count_q;
80+
end
81+
OBI_TIMER_COMPARE_OFFSET: begin
82+
rdata_d = compare_q;
83+
end
84+
OBI_TIMER_ENABLE_OFFSET: begin
85+
rdata_d = {31'h0, enable_q};
86+
end
87+
default: begin
88+
rdata_d = 32'hBADCAB1E;
89+
err_d = 1'b1;
90+
end
91+
endcase
92+
end
93+
94+
end
95+
end
96+
97+
always_ff @(posedge clk_i or negedge rst_ni) begin
98+
if (~rst_ni) begin
99+
count_q <= '0;
100+
compare_q <= '0;
101+
enable_q <= '0;
102+
end else begin
103+
count_q <= count_d;
104+
compare_q <= compare_d;
105+
enable_q <= enable_d;
106+
end
107+
end
108+
109+
110+
endmodule

rtl/obi_timer/obi_timer_pkg.sv

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
package obi_timer_pkg;
2+
3+
// Internal address width. We only need 4 bits to
4+
// store the offsets of the three registers implemented.
5+
localparam int unsigned IntAddrWidth = 5;
6+
7+
// Register offsets
8+
parameter logic [IntAddrWidth-1:0] OBI_TIMER_COUNT_OFFSET = 4'h0;
9+
parameter logic [IntAddrWidth-1:0] OBI_TIMER_COMPARE_OFFSET = 4'h4;
10+
parameter logic [IntAddrWidth-1:0] OBI_TIMER_ENABLE_OFFSET = 4'h8;
11+
12+
endpackage

0 commit comments

Comments
 (0)