Merge branch '38-increase-cpu-speed' into 'master'

Resolve "Increase CPU Speed"

Closes #38

See merge request bslathi19/super6502!33
This commit is contained in:
Byron Lathi
2023-10-16 01:45:44 +00:00
13 changed files with 392 additions and 145 deletions

View File

@@ -4,7 +4,7 @@ module sim_top();
`include "include/super6502_sdram_controller_define.vh" `include "include/super6502_sdram_controller_define.vh"
logic r_sysclk, r_sdrclk, r_clk_50, r_clk_2; logic r_sysclk, r_sdrclk, r_clk_50, r_clk_cpu;
// clk_100 // clk_100
initial begin initial begin
@@ -30,14 +30,18 @@ initial begin
end end
end end
// clk_2 // clk_cpu
initial begin initial begin
r_clk_2 <= '1; r_clk_cpu <= '1;
forever begin forever begin
#250 r_clk_2 <= ~r_clk_2; #125 r_clk_cpu <= ~r_clk_cpu;
end end
end end
// initial begin
// #275000 $finish();
// end
initial begin initial begin
$dumpfile("sim_top.vcd"); $dumpfile("sim_top.vcd");
$dumpvars(0,sim_top); $dumpvars(0,sim_top);
@@ -47,9 +51,9 @@ logic button_reset;
initial begin initial begin
button_reset <= '0; button_reset <= '0;
repeat(10) @(r_clk_2); repeat(10) @(r_clk_cpu);
button_reset <= '1; button_reset <= '1;
repeat(1000000) @(r_clk_2); repeat(1000000) @(r_clk_cpu);
$finish(); $finish();
end end
@@ -101,7 +105,7 @@ super6502 u_dut(
.i_sdrclk(r_sdrclk), .i_sdrclk(r_sdrclk),
.i_tACclk(~r_sdrclk), .i_tACclk(~r_sdrclk),
.clk_50(r_clk_50), .clk_50(r_clk_50),
.clk_2(r_clk_2), .clk_cpu(r_clk_cpu),
.button_reset(button_reset), .button_reset(button_reset),
.cpu_resb(w_cpu_reset), .cpu_resb(w_cpu_reset),
.cpu_addr(w_cpu_addr), .cpu_addr(w_cpu_addr),

View File

@@ -70,10 +70,11 @@ assign o_sdr_DQM = w_sdr_DQM[0+:2];
// But basically if we are in access, and cpuclk goes low, go back to wait. // But basically if we are in access, and cpuclk goes low, go back to wait.
// If something actually happened, we would be in one of the read/write states. // If something actually happened, we would be in one of the read/write states.
enum bit [1:0] {ACCESS, READ_WAIT, WRITE_WAIT, WAIT} state, next_state; enum bit [2:0] {ACCESS, PRE_READ, READ_WAIT, PRE_WRITE, WRITE_WAIT, WAIT} state, next_state;
logic w_read, w_write, w_last; logic w_read, w_write, w_last;
logic [23:0] w_addr, r_addr; logic [23:0] w_read_addr, w_write_addr;
logic [23:0] r_read_addr, r_write_addr;
logic [31:0] w_data_i, w_data_o; logic [31:0] w_data_i, w_data_o;
logic [3:0] w_dm, r_dm; logic [3:0] w_dm, r_dm;
@@ -86,25 +87,15 @@ logic [31:0] r_write_data;
logic [1:0] counter, next_counter; logic [1:0] counter, next_counter;
always @(posedge i_sysclk) begin logic [7:0] o_data_next;
if (i_arst) begin
state <= WAIT;
counter <= '0;
end else begin
state <= next_state;
counter <= next_counter;
r_write_data <= w_data_i;
r_addr <= w_addr;
r_dm <= w_dm;
end
if (w_data_valid) logic [23:0] addr_mux_out;
o_data <= _data;
end logic slow_mem;
logic r_wait; logic r_wait;
logic _r_wait; logic _r_wait;
assign o_wait = r_wait & i_cs; assign o_wait = (r_wait | slow_mem) & i_cs;
// we need to assert rdy low until a falling edge if a reset happens // we need to assert rdy low until a falling edge if a reset happens
@@ -126,6 +117,20 @@ always @(posedge i_sysclk or posedge i_arst) begin
end end
end end
end end
if (i_arst) begin
state <= WAIT;
counter <= '0;
end else begin
state <= next_state;
counter <= next_counter;
r_write_data <= w_data_i;
r_read_addr <= w_read_addr;
r_write_addr <= w_write_addr;
r_dm <= w_dm;
end
o_data <= o_data_next;
end end
//because of timing issues, We really need to trigger //because of timing issues, We really need to trigger
@@ -157,10 +162,12 @@ end
always_comb begin always_comb begin
slow_mem = '0;
next_state = state; next_state = state;
next_counter = counter; next_counter = counter;
w_addr = '0; w_read_addr = '0;
w_write_addr = '0;
w_dm = '0; w_dm = '0;
w_read = '0; w_read = '0;
w_write = '0; w_write = '0;
@@ -171,65 +178,81 @@ always_comb begin
unique case (state) unique case (state)
WAIT: begin WAIT: begin
if (i_cs & i_cpuclk) if (i_cs & ~i_cpuclk)
next_state = ACCESS; next_state = ACCESS;
end end
ACCESS: begin ACCESS: begin
// only do something if selected // only do something if selected
if (i_cs) begin if (i_cs) begin
w_addr = {{i_addr[24:2]}, {1'b0}};; // divide by 2, set last bit to 0 w_read_addr = {{i_addr[24:2]}, {1'b0}}; // divide by 2, set last bit to 0
w_write_addr = {{i_addr[24:2]}, {1'b0}}; // divide by 2, set last bit to 0
addr_mux_out = w_read_addr;
if (i_rwb) begin //read if (i_rwb) begin //read
w_read = '1; next_state = PRE_READ;
w_last = '1;
// dm is not needed for reads?
if (w_rd_ack) next_state = READ_WAIT;
end else begin //write end else begin //write
w_data_i = i_data << (8*i_addr[1:0]); w_data_i = i_data << (8*i_addr[1:0]);
//w_data_i = {4{i_data}}; //does anything get through?
w_dm = ~(4'b1 << i_addr[1:0]); w_dm = ~(4'b1 << i_addr[1:0]);
next_state = PRE_WRITE;
end
end
end
PRE_WRITE: begin
w_data_i = r_write_data;
w_write_addr = r_write_addr;
addr_mux_out = w_write_addr;
w_dm = r_dm;
//w_data_i = {4{i_data}}; //does anything get through?
if (~i_cpuclk) begin if (~i_cpuclk) begin
w_write = '1; w_write = '1;
w_last = '1; w_last = '1;
next_state = WRITE_WAIT; next_state = WRITE_WAIT;
end end
end end
end
end
WRITE_WAIT: begin WRITE_WAIT: begin
// stay in this state until write is acknowledged. // stay in this state until write is acknowledged.
w_write_addr = r_write_addr;
addr_mux_out = w_write_addr;
w_write = '1; w_write = '1;
w_last = '1; w_last = '1;
w_data_i = r_write_data; w_data_i = r_write_data;
w_dm = r_dm; w_dm = r_dm;
w_addr = r_addr;
if (w_wr_ack) next_state = WAIT; if (w_wr_ack) next_state = WAIT;
end end
PRE_READ: begin
w_read_addr = r_read_addr;
addr_mux_out = w_read_addr;
w_read = '1;
w_last = '1;
slow_mem = '1;
// dm is not needed for reads?
if (w_rd_ack) next_state = READ_WAIT;
end
READ_WAIT: begin READ_WAIT: begin
w_read_addr = r_read_addr;
addr_mux_out = w_read_addr;
slow_mem = '1;
if (w_rd_valid) begin if (w_rd_valid) begin
w_data_valid = '1; w_data_valid = '1;
_data = w_data_o[8*i_addr[1:0]+:8]; _data = w_data_o[8*i_addr[1:0]+:8];
end end
// you must wait until the next cycle! // you must wait until the next cycle!
if (~i_cpuclk) begin if (w_data_valid) begin
next_state = WAIT; next_state = WAIT;
end end
end end
endcase endcase
end
//this seems scuffed if (w_data_valid) begin
logic [23:0] addr_mux_out; o_data_next = _data;
always_comb begin
if (state == ACCESS) begin
addr_mux_out = w_addr;
end else begin end else begin
addr_mux_out = r_addr; o_data_next = o_data;
end end
end end

View File

@@ -11,7 +11,7 @@ module super6502
input button_reset, input button_reset,
input pll_cpu_locked, input pll_cpu_locked,
input clk_50, input clk_50,
input clk_2, input clk_cpu,
input logic [15:0] cpu_addr, input logic [15:0] cpu_addr,
output logic [7:0] cpu_data_out, output logic [7:0] cpu_data_out,
output logic [7:0] cpu_data_oe, output logic [7:0] cpu_data_oe,
@@ -56,11 +56,11 @@ assign cpu_nmib = '1;
logic w_wait; logic w_wait;
assign cpu_rdy = ~w_wait; assign cpu_rdy = ~w_wait;
assign cpu_phi2 = clk_2; assign cpu_phi2 = clk_cpu;
logic w_sdr_init_done; logic w_sdr_init_done;
always @(posedge clk_2) begin always @(posedge clk_cpu) begin
if (button_reset == '0) begin if (button_reset == '0) begin
cpu_resb <= '0; cpu_resb <= '0;
end end
@@ -124,12 +124,12 @@ end
rom #(.DATA_WIDTH(8), .ADDR_WIDTH(12)) u_rom( rom #(.DATA_WIDTH(8), .ADDR_WIDTH(12)) u_rom(
.addr(cpu_addr[11:0]), .addr(cpu_addr[11:0]),
.clk(clk_2), .clk(clk_cpu),
.data(w_rom_data_out) .data(w_rom_data_out)
); );
leds u_leds( leds u_leds(
.clk(clk_2), .clk(clk_cpu),
.i_data(cpu_data_in), .i_data(cpu_data_in),
.o_data(w_leds_data_out), .o_data(w_leds_data_out),
.cs(w_leds_cs), .cs(w_leds_cs),
@@ -140,7 +140,7 @@ leds u_leds(
logic w_timer_irqb; logic w_timer_irqb;
timer u_timer( timer u_timer(
.clk(clk_2), .clk(clk_cpu),
.reset(~cpu_resb), .reset(~cpu_resb),
.i_data(cpu_data_in), .i_data(cpu_data_in),
.o_data(w_timer_data_out), .o_data(w_timer_data_out),
@@ -151,7 +151,7 @@ timer u_timer(
); );
multiplier u_multiplier( multiplier u_multiplier(
.clk(clk_2), .clk(clk_cpu),
.reset(~cpu_resb), .reset(~cpu_resb),
.i_data(cpu_data_in), .i_data(cpu_data_in),
.o_data(w_multiplier_data_out), .o_data(w_multiplier_data_out),
@@ -161,7 +161,7 @@ multiplier u_multiplier(
); );
divider_wrapper u_divider( divider_wrapper u_divider(
.clk(clk_2), .clk(clk_cpu),
.divclk(clk_50), .divclk(clk_50),
.reset(~cpu_resb), .reset(~cpu_resb),
.i_data(cpu_data_in), .i_data(cpu_data_in),
@@ -174,7 +174,7 @@ divider_wrapper u_divider(
logic w_uart_irqb; logic w_uart_irqb;
uart_wrapper u_uart( uart_wrapper u_uart(
.clk(clk_2), .clk(clk_cpu),
.clk_50(clk_50), .clk_50(clk_50),
.reset(~cpu_resb), .reset(~cpu_resb),
.i_data(cpu_data_in), .i_data(cpu_data_in),
@@ -188,7 +188,7 @@ uart_wrapper u_uart(
); );
spi_controller spi_controller( spi_controller spi_controller(
.i_clk(clk_2), .i_clk(clk_cpu),
.i_rst(~cpu_resb), .i_rst(~cpu_resb),
.i_cs(w_spi_cs), .i_cs(w_spi_cs),
.i_rwb(cpu_rwb), .i_rwb(cpu_rwb),
@@ -204,7 +204,7 @@ spi_controller spi_controller(
sdram_adapter u_sdram_adapter( sdram_adapter u_sdram_adapter(
.i_cpuclk(clk_2), .i_cpuclk(clk_cpu),
.i_arst(~button_reset), .i_arst(~button_reset),
.i_sysclk(i_sysclk), .i_sysclk(i_sysclk),
.i_sdrclk(i_sdrclk), .i_sdrclk(i_sdrclk),
@@ -234,7 +234,7 @@ sdram_adapter u_sdram_adapter(
); );
interrupt_controller u_interrupt_controller( interrupt_controller u_interrupt_controller(
.clk(clk_2), .clk(clk_cpu),
.reset(~cpu_resb), .reset(~cpu_resb),
.i_data(cpu_data_in), .i_data(cpu_data_in),
.o_data(w_irq_data_out), .o_data(w_irq_data_out),

View File

@@ -1,4 +1,5 @@
<efx:project xmlns:efx="http://www.efinixinc.com/enf_proj" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" name="super6502" description="" last_change_date="Thu Sep 28 2023 09:38:33 PM" location="/home/byron/ServerProjects/super6502/hw/efinix_fpga" sw_version="2023.1.150" last_run_state="pass" last_run_tool="efx_pgm" last_run_flow="bitstream" config_result_in_sync="sync" design_ood="sync" place_ood="sync" route_ood="sync" xsi:schemaLocation="http://www.efinixinc.com/enf_proj enf_proj.xsd"> <?xml version="1.0" encoding="UTF-8"?>
<efx:project name="super6502" description="" last_change_date="Sun October 15 2023 13:52:14" location="/home/byron/ServerProjects/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="sync" 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:device_info>
<efx:family name="Trion"/> <efx:family name="Trion"/>
<efx:device name="T20F256"/> <efx:device name="T20F256"/>

View File

@@ -17,6 +17,6 @@ kernel:
clean: clean:
@$(MAKE) -C bootloader --no-print-directory $@ @$(MAKE) -C bios --no-print-directory $@
@$(MAKE) -C kernel --no-print-directory $@ @$(MAKE) -C kernel --no-print-directory $@
@$(MAKE) -C cc65 --no-print-directory $@ @$(MAKE) -C cc65 --no-print-directory $@

View File

@@ -0,0 +1,39 @@
CC=../../cc65/bin/cl65
LD=../../cc65/bin/cl65
CFLAGS=-T -t none -I. --cpu "65C02"
LDFLAGS=-C link.ld -m $(NAME).map
NAME=indirect_test
BIN=$(NAME).bin
HEX=$(NAME).hex
LISTS=lists
SRCS=$(wildcard *.s) $(wildcard *.c)
SRCS+=$(wildcard **/*.s) $(wildcard **/*.c)
OBJS+=$(patsubst %.s,%.o,$(filter %s,$(SRCS)))
OBJS+=$(patsubst %.c,%.o,$(filter %c,$(SRCS)))
# Make sure the kernel linked to correct address, no relocation!
all: $(HEX)
$(HEX): $(BIN)
objcopy --input-target=binary --output-target=verilog $(BIN) $(HEX)
$(BIN): $(OBJS)
$(CC) $(CFLAGS) $(LDFLAGS) $(OBJS) -o $@
%.o: %.c $(LISTS)
$(CC) $(CFLAGS) -l $(LISTS)/$<.list -c $< -o $@
%.o: %.s $(LISTS)
$(CC) $(CFLAGS) -l $(LISTS)/$<.list -c $< -o $@
$(LISTS):
mkdir -p $(addprefix $(LISTS)/,$(sort $(dir $(SRCS))))
.PHONY: clean
clean:
rm -rf $(OBJS) $(BIN) $(HEX) $(LISTS) $(NAME).map

View File

@@ -0,0 +1,35 @@
MEMORY
{
ZP: start = $0, size = $100, type = rw, define = yes;
SDRAM: start = $9200, size = $4d00, type = rw, define = yes;
ROM: start = $F000, size = $1000, file = %O;
}
SEGMENTS {
ZEROPAGE: load = ZP, type = zp, define = yes;
DATA: load = ROM, type = rw, define = yes, run = SDRAM;
BSS: load = SDRAM, type = bss, define = yes;
HEAP: load = SDRAM, type = bss, optional = yes;
STARTUP: load = ROM, type = ro;
ONCE: load = ROM, type = ro, optional = yes;
CODE: load = ROM, type = ro;
RODATA: load = ROM, type = ro;
VECTORS: load = ROM, type = ro, start = $FFFA;
}
FEATURES {
CONDES: segment = STARTUP,
type = constructor,
label = __CONSTRUCTOR_TABLE__,
count = __CONSTRUCTOR_COUNT__;
CONDES: segment = STARTUP,
type = destructor,
label = __DESTRUCTOR_TABLE__,
count = __DESTRUCTOR_COUNT__;
}
SYMBOLS {
# Define the stack size for the application
__STACKSIZE__: value = $0200, type = weak;
__STACKSTART__: type = weak, value = $0800; # 2k stack
}

View File

@@ -0,0 +1,20 @@
.export _init, _nmi_int, _irq_int
.code
_nmi_int:
_irq_int:
_init:
ldx #$ff
txs
lda #$aa
sta $01
lda #$bb
sta $00
ldy #$1
lda #$cc
sta ($00),y
@end: bra @end

View File

@@ -0,0 +1,14 @@
; ---------------------------------------------------------------------------
; vectors.s
; ---------------------------------------------------------------------------
;
; Defines the interrupt vector table.
.import _init
.import _nmi_int, _irq_int
.segment "VECTORS"
.addr _nmi_int ; NMI vector
.addr _init ; Reset vector
.addr _irq_int ; IRQ/BRK vector

View File

@@ -0,0 +1,39 @@
CC=../../cc65/bin/cl65
LD=../../cc65/bin/cl65
CFLAGS=-T -t none -I. --cpu "65C02"
LDFLAGS=-C link.ld -m $(NAME).map
NAME=jsr_test
BIN=$(NAME).bin
HEX=$(NAME).hex
LISTS=lists
SRCS=$(wildcard *.s) $(wildcard *.c)
SRCS+=$(wildcard **/*.s) $(wildcard **/*.c)
OBJS+=$(patsubst %.s,%.o,$(filter %s,$(SRCS)))
OBJS+=$(patsubst %.c,%.o,$(filter %c,$(SRCS)))
# Make sure the kernel linked to correct address, no relocation!
all: $(HEX)
$(HEX): $(BIN)
objcopy --input-target=binary --output-target=verilog $(BIN) $(HEX)
$(BIN): $(OBJS)
$(CC) $(CFLAGS) $(LDFLAGS) $(OBJS) -o $@
%.o: %.c $(LISTS)
$(CC) $(CFLAGS) -l $(LISTS)/$<.list -c $< -o $@
%.o: %.s $(LISTS)
$(CC) $(CFLAGS) -l $(LISTS)/$<.list -c $< -o $@
$(LISTS):
mkdir -p $(addprefix $(LISTS)/,$(sort $(dir $(SRCS))))
.PHONY: clean
clean:
rm -rf $(OBJS) $(BIN) $(HEX) $(LISTS) $(NAME).map

View File

@@ -0,0 +1,35 @@
MEMORY
{
ZP: start = $0, size = $100, type = rw, define = yes;
SDRAM: start = $9200, size = $4d00, type = rw, define = yes;
ROM: start = $F000, size = $1000, file = %O;
}
SEGMENTS {
ZEROPAGE: load = ZP, type = zp, define = yes;
DATA: load = ROM, type = rw, define = yes, run = SDRAM;
BSS: load = SDRAM, type = bss, define = yes;
HEAP: load = SDRAM, type = bss, optional = yes;
STARTUP: load = ROM, type = ro;
ONCE: load = ROM, type = ro, optional = yes;
CODE: load = ROM, type = ro;
RODATA: load = ROM, type = ro;
VECTORS: load = ROM, type = ro, start = $FFFA;
}
FEATURES {
CONDES: segment = STARTUP,
type = constructor,
label = __CONSTRUCTOR_TABLE__,
count = __CONSTRUCTOR_COUNT__;
CONDES: segment = STARTUP,
type = destructor,
label = __DESTRUCTOR_TABLE__,
count = __DESTRUCTOR_COUNT__;
}
SYMBOLS {
# Define the stack size for the application
__STACKSIZE__: value = $0200, type = weak;
__STACKSTART__: type = weak, value = $0800; # 2k stack
}

View File

@@ -0,0 +1,23 @@
.export _init, _nmi_int, _irq_int
.code
_nmi_int:
_irq_int:
_init:
ldx #$ff
txs
lda #$00
jsr subroutine
sta $00
@1: bra @1
subroutine:
inc
jsr suborutine2
rts
suborutine2:
inc
rts

View File

@@ -0,0 +1,14 @@
; ---------------------------------------------------------------------------
; vectors.s
; ---------------------------------------------------------------------------
;
; Defines the interrupt vector table.
.import _init
.import _nmi_int, _irq_int
.segment "VECTORS"
.addr _nmi_int ; NMI vector
.addr _init ; Reset vector
.addr _irq_int ; IRQ/BRK vector