Add interrupt based timer and test code

This commit is contained in:
Byron Lathi
2023-01-03 18:20:34 -05:00
parent 1ac3bdf614
commit 32a78a4aff
10 changed files with 639 additions and 74 deletions

View File

@@ -6,8 +6,8 @@ module timer
output logic [7:0] o_data,
input cs,
input rwb,
input [2:0] addr,
output logic irq
input [1:0] addr,
output logic irqb
);
//new idea for timer:
@@ -15,43 +15,88 @@ module timer
//it can either cause an interrupt or not.
//if you want it to do both, add another timer.
/*
Addr Read Write
0 Counter Low Latch Low
1 Counter High Latch High
2 Divisor Divisor
3 Status Control
*/
logic [15:0] timer_latch, timer_counter;
//control register
// bit 0: Enable interrupts
// bit 1: Enable 1 shot mode
//by default it just starts counting up
//writing to latch low starts the timer
logic [7:0] divisor, status, control;
logic count_en;
assign status[0] = count_en;
logic [15:0] pulsecount;
//I think this should be negedge so that writes go through
always @(negedge clk) begin
if (reset) begin
count_en = '0;
timer_counter <= '0;
pulsecount <= '0;
timer_latch <= '0;
timer_latch <= '1;
divisor <= '0;
status <= '0;
control <= '0;
irq <= '1;
irqb <= '1;
end else begin
if (pulsecount[15:8] == divisor) begin
timer_counter <= timer_counter + 16'b1;
pulsecount <= '0;
end else begin
pulsecount <= pulsecount + 16'b1;
if (count_en) begin
if (pulsecount[15:8] == divisor) begin
timer_counter <= timer_counter + 16'b1;
pulsecount <= '0;
end else begin
pulsecount <= pulsecount + 16'b1;
end
end
if (timer_counter == timer_latch) begin
// if interrupts are enabled
if (control[0]) begin
irqb <= '0;
end
// if oneshot mode is enabled
if (control[1]) begin
count_en <= '0;
end else begin
timer_counter <= '0;
end
end
if (cs & rwb) begin
irqb <= '1;
end
if (cs & ~rwb) begin
case (addr)
3'h5: begin
2'h0: begin
count_en <= '1;
timer_latch[7:0] <= i_data;
end
2'h1: begin
timer_latch[15:8] <= i_data;
end
2'h2: begin
divisor <= i_data;
end
end
2'h3: begin
control <= i_data;
end
endcase
end
@@ -62,36 +107,20 @@ always_comb begin
o_data = '0;
unique case (addr)
3'h0: begin
2'h0: begin
o_data = timer_counter[7:0];
end
3'h1: begin
2'h1: begin
o_data = timer_counter[15:8];
end
3'h2: begin
2'h2: begin
o_data = divisor;
end
3'h3: begin
end
3'h4: begin
end
3'h5: begin
end
3'h6: begin
end
3'h7: begin
2'h3: begin
o_data = status;
end
endcase