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

@@ -10,7 +10,7 @@ module addr_decode
assign o_rom_cs = i_addr >= 16'hf000 && i_addr <= 16'hffff;
assign o_leds_cs = i_addr == 16'hefff;
assign o_timer_cs = i_addr >= 16'heff8 && i_addr <= 16'heffe;
assign o_timer_cs = i_addr >= 16'heff8 && i_addr <= 16'heffb;
assign o_sdram_cs = i_addr < 16'h8000;
endmodule

View File

@@ -3,7 +3,7 @@
{
"name": "la0",
"type": "la",
"uuid": "eca5777d2e5a40ed85ba29fd5435f87f",
"uuid": "281a52604f2c437c9bde96b89d672260",
"trigin_en": false,
"trigout_en": false,
"auto_inserted": true,
@@ -30,6 +30,36 @@
"name": "cpu_sync",
"width": 1,
"probe_type": 1
},
{
"name": "u_timer/count_en",
"width": 1,
"probe_type": 1
},
{
"name": "cpu_data_out",
"width": 8,
"probe_type": 1
},
{
"name": "u_timer/timer_latch",
"width": 16,
"probe_type": 1
},
{
"name": "u_timer/pulsecount",
"width": 16,
"probe_type": 1
},
{
"name": "u_timer/timer_counter",
"width": 16,
"probe_type": 1
},
{
"name": "cpu_irqb",
"width": 1,
"probe_type": 1
}
]
}
@@ -289,6 +319,394 @@
"name": "la0_probe3",
"net": "cpu_sync",
"path": []
},
{
"name": "la0_probe4",
"net": "count_en",
"path": [
"u_timer"
]
},
{
"name": "la0_probe5[0]",
"net": "cpu_data_out[0]",
"path": []
},
{
"name": "la0_probe5[1]",
"net": "cpu_data_out[1]",
"path": []
},
{
"name": "la0_probe5[2]",
"net": "cpu_data_out[2]",
"path": []
},
{
"name": "la0_probe5[3]",
"net": "cpu_data_out[3]",
"path": []
},
{
"name": "la0_probe5[4]",
"net": "cpu_data_out[4]",
"path": []
},
{
"name": "la0_probe5[5]",
"net": "cpu_data_out[5]",
"path": []
},
{
"name": "la0_probe5[6]",
"net": "cpu_data_out[6]",
"path": []
},
{
"name": "la0_probe5[7]",
"net": "cpu_data_out[7]",
"path": []
},
{
"name": "la0_probe6[0]",
"net": "timer_latch[0]",
"path": [
"u_timer"
]
},
{
"name": "la0_probe6[1]",
"net": "timer_latch[1]",
"path": [
"u_timer"
]
},
{
"name": "la0_probe6[2]",
"net": "timer_latch[2]",
"path": [
"u_timer"
]
},
{
"name": "la0_probe6[3]",
"net": "timer_latch[3]",
"path": [
"u_timer"
]
},
{
"name": "la0_probe6[4]",
"net": "timer_latch[4]",
"path": [
"u_timer"
]
},
{
"name": "la0_probe6[5]",
"net": "timer_latch[5]",
"path": [
"u_timer"
]
},
{
"name": "la0_probe6[6]",
"net": "timer_latch[6]",
"path": [
"u_timer"
]
},
{
"name": "la0_probe6[7]",
"net": "timer_latch[7]",
"path": [
"u_timer"
]
},
{
"name": "la0_probe6[8]",
"net": "timer_latch[8]",
"path": [
"u_timer"
]
},
{
"name": "la0_probe6[9]",
"net": "timer_latch[9]",
"path": [
"u_timer"
]
},
{
"name": "la0_probe6[10]",
"net": "timer_latch[10]",
"path": [
"u_timer"
]
},
{
"name": "la0_probe6[11]",
"net": "timer_latch[11]",
"path": [
"u_timer"
]
},
{
"name": "la0_probe6[12]",
"net": "timer_latch[12]",
"path": [
"u_timer"
]
},
{
"name": "la0_probe6[13]",
"net": "timer_latch[13]",
"path": [
"u_timer"
]
},
{
"name": "la0_probe6[14]",
"net": "timer_latch[14]",
"path": [
"u_timer"
]
},
{
"name": "la0_probe6[15]",
"net": "timer_latch[15]",
"path": [
"u_timer"
]
},
{
"name": "la0_probe7[0]",
"net": "pulsecount[0]",
"path": [
"u_timer"
]
},
{
"name": "la0_probe7[1]",
"net": "pulsecount[1]",
"path": [
"u_timer"
]
},
{
"name": "la0_probe7[2]",
"net": "pulsecount[2]",
"path": [
"u_timer"
]
},
{
"name": "la0_probe7[3]",
"net": "pulsecount[3]",
"path": [
"u_timer"
]
},
{
"name": "la0_probe7[4]",
"net": "pulsecount[4]",
"path": [
"u_timer"
]
},
{
"name": "la0_probe7[5]",
"net": "pulsecount[5]",
"path": [
"u_timer"
]
},
{
"name": "la0_probe7[6]",
"net": "pulsecount[6]",
"path": [
"u_timer"
]
},
{
"name": "la0_probe7[7]",
"net": "pulsecount[7]",
"path": [
"u_timer"
]
},
{
"name": "la0_probe7[8]",
"net": "pulsecount[8]",
"path": [
"u_timer"
]
},
{
"name": "la0_probe7[9]",
"net": "pulsecount[9]",
"path": [
"u_timer"
]
},
{
"name": "la0_probe7[10]",
"net": "pulsecount[10]",
"path": [
"u_timer"
]
},
{
"name": "la0_probe7[11]",
"net": "pulsecount[11]",
"path": [
"u_timer"
]
},
{
"name": "la0_probe7[12]",
"net": "pulsecount[12]",
"path": [
"u_timer"
]
},
{
"name": "la0_probe7[13]",
"net": "pulsecount[13]",
"path": [
"u_timer"
]
},
{
"name": "la0_probe7[14]",
"net": "pulsecount[14]",
"path": [
"u_timer"
]
},
{
"name": "la0_probe7[15]",
"net": "pulsecount[15]",
"path": [
"u_timer"
]
},
{
"name": "la0_probe8[0]",
"net": "timer_counter[0]",
"path": [
"u_timer"
]
},
{
"name": "la0_probe8[1]",
"net": "timer_counter[1]",
"path": [
"u_timer"
]
},
{
"name": "la0_probe8[2]",
"net": "timer_counter[2]",
"path": [
"u_timer"
]
},
{
"name": "la0_probe8[3]",
"net": "timer_counter[3]",
"path": [
"u_timer"
]
},
{
"name": "la0_probe8[4]",
"net": "timer_counter[4]",
"path": [
"u_timer"
]
},
{
"name": "la0_probe8[5]",
"net": "timer_counter[5]",
"path": [
"u_timer"
]
},
{
"name": "la0_probe8[6]",
"net": "timer_counter[6]",
"path": [
"u_timer"
]
},
{
"name": "la0_probe8[7]",
"net": "timer_counter[7]",
"path": [
"u_timer"
]
},
{
"name": "la0_probe8[8]",
"net": "timer_counter[8]",
"path": [
"u_timer"
]
},
{
"name": "la0_probe8[9]",
"net": "timer_counter[9]",
"path": [
"u_timer"
]
},
{
"name": "la0_probe8[10]",
"net": "timer_counter[10]",
"path": [
"u_timer"
]
},
{
"name": "la0_probe8[11]",
"net": "timer_counter[11]",
"path": [
"u_timer"
]
},
{
"name": "la0_probe8[12]",
"net": "timer_counter[12]",
"path": [
"u_timer"
]
},
{
"name": "la0_probe8[13]",
"net": "timer_counter[13]",
"path": [
"u_timer"
]
},
{
"name": "la0_probe8[14]",
"net": "timer_counter[14]",
"path": [
"u_timer"
]
},
{
"name": "la0_probe8[15]",
"net": "timer_counter[15]",
"path": [
"u_timer"
]
},
{
"name": "la0_probe9",
"net": "cpu_irqb",
"path": []
}
]
}
@@ -340,6 +758,70 @@
"selected_probe_type": "DATA AND TRIGGER",
"child": [],
"path": []
},
{
"name": "count_en",
"width": 1,
"clk_domain": "clk_2",
"selected_probe_type": "DATA AND TRIGGER",
"child": [],
"path": [
"u_timer"
]
},
{
"name": "cpu_data_out",
"width": 8,
"clk_domain": "clk_2",
"selected_probe_type": "DATA AND TRIGGER",
"child": [],
"path": [],
"net_idx_left": 7,
"net_idx_right": 0
},
{
"name": "timer_latch",
"width": 16,
"clk_domain": "clk_2",
"selected_probe_type": "DATA AND TRIGGER",
"child": [],
"path": [
"u_timer"
],
"net_idx_left": 15,
"net_idx_right": 0
},
{
"name": "pulsecount",
"width": 16,
"clk_domain": "clk_2",
"selected_probe_type": "DATA AND TRIGGER",
"child": [],
"path": [
"u_timer"
],
"net_idx_left": 15,
"net_idx_right": 0
},
{
"name": "timer_counter",
"width": 16,
"clk_domain": "clk_2",
"selected_probe_type": "DATA AND TRIGGER",
"child": [],
"path": [
"u_timer"
],
"net_idx_left": 15,
"net_idx_right": 0
},
{
"name": "cpu_irqb",
"width": 1,
"clk_domain": "clk_2",
"selected_probe_type": "DATA AND TRIGGER",
"child": [],
"path": []
}
],
"top_module": "super6502",

View File

@@ -4,9 +4,9 @@ input integer index;//Mode type
input integer val_; //Port A index, Port B Index, Number of Items in Loop, Port A Start, Port B Start, reserved
case (index)
0: bram_ini_table=
(val_== 0)?256'h00ef000ff0009c0001000085000ef000f8000ad000ef000fd0008d000ff000a9:
(val_== 1)?256'h086000f40009000020000e90003800010000e500038000aa000ef000f8000ad0:
(val_== 2)?256'h00000000000000000000000000000000000ed00080000ef000ff000ee0001000:
(val_== 0)?256'h008d00000000a9000ef000fb0008d00001000a9000ef000fa0008d000ff000a9:
(val_== 1)?256'h0f8000ad000fd00080000cb00058000ef000f80008d00010000a9000ef000f90:
(val_== 2)?256'h000000000000000000000000000000000000000040000ef000ff000ee000ef00:
(val_== 3)?256'h0000000000000000000000000000000000000000000000000000000000000000:
(val_== 4)?256'h0000000000000000000000000000000000000000000000000000000000000000:
(val_== 5)?256'h0000000000000000000000000000000000000000000000000000000000000000:
@@ -23,7 +23,7 @@ case (index)
(val_==16)?256'h0000000000000000000000000000000000000000000000000000000000000000:
(val_==17)?256'h0000000000000000000000000000000000000000000000000000000000000000:
(val_==18)?256'h0000000000000000000000000000000000000000000000000000000000000000:
(val_==19)?256'h000ff00000000ff00000000ff000000000000000000000000000000000000000:
(val_==19)?256'h000ff00018000ff00000000ff000000000000000000000000000000000000000:
(val_==20)?256'h0000000000000000000000000000000000000000000000000000000000000000:
(val_==21)?256'h0000000000000000000000000000000000000000000000000000000000000000:
(val_==22)?256'h0000000000000000000000000000000000000000000000000000000000000000:

View File

@@ -1,35 +1,35 @@
a9
ff
8d
fa
ef
a9
01
8d
fb
ef
a9
00
8d
f9
ef
a9
10
8d
f8
ef
58
cb
80
fd
ef
ad
f8
ef
85
10
9c
ff
ef
ad
f8
ef
aa
38
e5
10
38
e9
20
90
f4
86
10
ee
ff
ef
80
ed
40
00
00
00
00
@@ -252,5 +252,5 @@ ed
ff
00
ff
00
18
ff

View File

@@ -114,7 +114,7 @@ leds u_leds(
.o_leds(leds)
);
logic w_timer_irq;
logic w_timer_irqb;
timer u_timer(
.clk(clk_2),
@@ -123,8 +123,8 @@ timer u_timer(
.o_data(w_timer_data_out),
.cs(w_timer_cs),
.rwb(cpu_rwb),
.addr(cpu_addr[2:0]),
.irq(w_timer_irq)
.addr(cpu_addr[1:0]),
.irqb(w_timer_irqb)
);
sdram_adapter u_sdram_adapter(
@@ -164,7 +164,7 @@ interrupt_controller u_interrupt_controller(
.cs(w_irq_cs),
.rwb(cpu_rwb),
.irqb_master(cpu_irqb),
.irqb0(w_timer_irq),
.irqb0(w_timer_irqb),
.irqb1('1),
.irqb2('1),
.irqb3('1),

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<efx:project name="super6502" description="" last_change_date="Tue January 3 2023 15:48:31" location="/home/byron/Projects/super6502/hw/efinix_fpga" sw_version="2022.2.322" last_run_state="pass" last_run_tool="efx_pgm" last_run_flow="bitstream" config_result_in_sync="true" design_ood="sync" place_ood="sync" route_ood="sync" xmlns:efx="http://www.efinixinc.com/enf_proj" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.efinixinc.com/enf_proj enf_proj.xsd">
<efx:project name="super6502" description="" last_change_date="Tue January 3 2023 18:18:26" location="/home/byron/Projects/super6502/hw/efinix_fpga" sw_version="2022.2.322" last_run_state="pass" last_run_tool="efx_pgm" last_run_flow="bitstream" config_result_in_sync="true" design_ood="sync" place_ood="sync" route_ood="sync" xmlns:efx="http://www.efinixinc.com/enf_proj" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.efinixinc.com/enf_proj enf_proj.xsd">
<efx:device_info>
<efx:family name="Trion"/>
<efx:device name="T20F256"/>

View File

@@ -1,11 +1,18 @@
TARGETS=stacktest runram timer
TARGETS=stacktest runram timer timer_irq
SRC=$(wildcard *.s)
DIR=../ip/bram
all: $(TARGETS)
$(TARGETS):
$(TARGETS): $(SRC)
cl65 --cpu 65c02 -C link.ld -l $@.list $@.s
xxd -ps $@ | fold -w 2 > $@.hex
install:
cp $(TARGET).hex $(DIR)/init_hex.mem
cd $(DIR);python3 efx_mem_init_script.py hex init_hex.mem
clean:
rm -f $(TARGETS)
rm *.hex

View File

@@ -2,13 +2,21 @@
LEDS = $efff
TIMER_BASE = $eff8
TIMER_DIVISOR = 5
TIMER_DIVISOR = 2
TIMER_CL = 0
TIMER_LL = 0
TIMER_CH = 1
TIMER_LH = 1
TIMER_STATUS = 3
TIMER_OLD = $10
main:
lda #$ff
lda #$01
sta TIMER_BASE+TIMER_DIVISOR
lda #$00
sta TIMER_BASE+TIMER_LH
lda #$0F
sta TIMER_BASE+TIMER_LL
lda TIMER_BASE
sta TIMER_OLD
stz LEDS

View File

@@ -0,0 +1,39 @@
.code
LEDS = $efff
TIMER_BASE = $eff8
TIMER_DIVISOR = 2
TIMER_CL = 0
TIMER_LL = 0
TIMER_CH = 1
TIMER_LH = 1
TIMER_STATUS = 3
TIMER_CONTROL = 3
TIMER_OLD = $10
main:
lda #$ff
sta TIMER_BASE+TIMER_DIVISOR
lda #$01
sta TIMER_BASE+TIMER_CONTROL
lda #$00
sta TIMER_BASE+TIMER_LH
lda #$10
sta TIMER_BASE+TIMER_LL
cli
loop:
wai
bra loop
irq:
lda TIMER_BASE
inc LEDS
rti
.segment "VECTORS"
.addr main
.addr main
.addr irq

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 (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
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