Merge branch '23-create-a-better-simulation-environment' into 'master'

Resolve "Create a better simulation environment"

Closes #23

See merge request bslathi19/super6502!23
This commit is contained in:
Byron Lathi
2023-09-28 04:16:59 +00:00
25 changed files with 1654 additions and 291 deletions

3
.gitmodules vendored
View File

@@ -1,3 +1,6 @@
[submodule "sw/cc65"]
path = sw/cc65
url = https://git.byronlathi.com/bslathi19/cc65
[submodule "hw/efinix_fpga/simulation/src/verilog-6502"]
path = hw/efinix_fpga/simulation/src/verilog-6502
url = https://git.byronlathi.com/bslathi19/verilog-6502

View File

@@ -1,20 +1,27 @@
TARGETS= timer interrupt_controller spi_controller
TB=$(patsubst %, %_tb.sv, $(TARGETS))
SRCS=$(shell find src/ -type f -name "*.*v")
SRCS+=$(shell find ../ip/ -type f -name "*.*v" -not \( -name "*tmpl*" \))
SRCS+=$(shell find ../src/ -type f -name "*.*v")
all: $(TARGETS)
INC=$(shell find include/ -type f)
timer: timer_tb.sv
iverilog -g2005-sv -s sim -o $@ $@_tb.sv ../$@.sv
TEST_PROGRAM_NAME?=loop_test
spi_controller: spi_controller_tb.sv ../spi_controller.sv
iverilog -g2005-sv -s sim -o $@ $@_tb.sv ../$@.sv
TEST_PROGRAM?=$(REPO_TOP)/sw/test_code/$(TEST_PROGRAM_NAME)/$(TEST_PROGRAM_NAME).hex
interrupt_controller: interrupt_controller_tb.sv
iverilog -g2005-sv -s sim -o $@ $@_tb.sv ../$@.sv
#TODO implement something like sources.list
TOP_MODULE=sim_top
TARGET=sim_top
INIT_MEM=init_hex.mem
FLAGS=-DSIM -DRTL_SIM
all: $(INIT_MEM)
iverilog -g2005-sv $(FLAGS) -s $(TOP_MODULE) -o $(TARGET) $(INC) $(SRCS)
$(INIT_MEM):
cp $(TEST_PROGRAM) ./init_hex.mem
.PHONY: clean
clean:
rm -f $(TARGETS)
rm -f *.vcd
rm -f *.vvp
rm -rf $(TARGET)
rm -rf $(INIT_MEM)

View File

@@ -0,0 +1,80 @@
// =============================================================================
// Generated by efx_ipmgr
// Version: 2023.1.150
// IP Version: 5.0
// =============================================================================
////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2013-2023 Efinix Inc. All rights reserved.
//
// This document contains proprietary information which is
// protected by copyright. All rights are reserved. This notice
// refers to original work by Efinix, Inc. which may be derivitive
// of other work distributed under license of the authors. In the
// case of derivative work, nothing in this notice overrides the
// original author's license agreement. Where applicable, the
// original license agreement is included in it's original
// unmodified form immediately below this header.
//
// WARRANTY DISCLAIMER.
// THE DESIGN, CODE, OR INFORMATION ARE PROVIDED “AS IS” AND
// EFINIX MAKES NO WARRANTIES, EXPRESS OR IMPLIED WITH
// RESPECT THERETO, AND EXPRESSLY DISCLAIMS ANY IMPLIED WARRANTIES,
// INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
// MERCHANTABILITY, NON-INFRINGEMENT AND FITNESS FOR A PARTICULAR
// PURPOSE. SOME STATES DO NOT ALLOW EXCLUSIONS OF AN IMPLIED
// WARRANTY, SO THIS DISCLAIMER MAY NOT APPLY TO LICENSEE.
//
// LIMITATION OF LIABILITY.
// NOTWITHSTANDING ANYTHING TO THE CONTRARY, EXCEPT FOR BODILY
// INJURY, EFINIX SHALL NOT BE LIABLE WITH RESPECT TO ANY SUBJECT
// MATTER OF THIS AGREEMENT UNDER TORT, CONTRACT, STRICT LIABILITY
// OR ANY OTHER LEGAL OR EQUITABLE THEORY (I) FOR ANY INDIRECT,
// SPECIAL, INCIDENTAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES OF ANY
// CHARACTER INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF
// GOODWILL, DATA OR PROFIT, WORK STOPPAGE, OR COMPUTER FAILURE OR
// MALFUNCTION, OR IN ANY EVENT (II) FOR ANY AMOUNT IN EXCESS, IN
// THE AGGREGATE, OF THE FEE PAID BY LICENSEE TO EFINIX HEREUNDER
// (OR, IF THE FEE HAS BEEN WAIVED, $100), EVEN IF EFINIX SHALL HAVE
// BEEN INFORMED OF THE POSSIBILITY OF SUCH DAMAGES. SOME STATES DO
// NOT ALLOW THE EXCLUSION OR LIMITATION OF INCIDENTAL OR
// CONSEQUENTIAL DAMAGES, SO THIS LIMITATION AND EXCLUSION MAY NOT
// APPLY TO LICENSEE.
//
////////////////////////////////////////////////////////////////////////////////
localparam fSYS_MHz = 100;
localparam fCK_MHz = 200;
localparam tIORT_u = 2;
localparam CL = 3;
localparam BL = 1;
localparam DDIO_TYPE = "SOFT";
localparam DQ_WIDTH = 8;
localparam DQ_GROUP = 2;
localparam BA_WIDTH = 2;
localparam ROW_WIDTH = 13;
localparam COL_WIDTH = 9;
localparam tPWRUP = 200000;
localparam tRAS = 44;
localparam tRAS_MAX = 120000;
localparam tRC = 66;
localparam tRCD = 20;
localparam tREF = 64000000;
localparam tRFC = 66;
localparam tRP = 20;
localparam tWR = 2;
localparam tMRD = 2;
localparam SDRAM_MODE = "Native";
localparam DATA_RATE = 2;
localparam AXI_AWADDR_WIDTH = 24;
localparam AXI_WDATA_WIDTH = 32;
localparam AXI_ARADDR_WIDTH = 24;
localparam AXI_RDATA_WIDTH = 32;
localparam AXI_AWID_WIDTH = 4;
localparam AXI_AWUSER_WIDTH = 2;
localparam AXI_WUSER_WIDTH = 2;
localparam AXI_BID_WIDTH = 4;
localparam AXI_BUSER_WIDTH = 2;
localparam AXI_ARID_WIDTH = 4;
localparam AXI_ARUSER_WIDTH = 3;
localparam AXI_RUSER_WIDTH = 3;

View File

@@ -1,76 +0,0 @@
module sim();
timeunit 10ns;
timeprecision 1ns;
logic clk;
logic reset;
logic [2:0] addr;
logic [7:0] i_data;
logic [7:0] o_data;
logic cs;
logic rwb;
logic irqb_master;
logic irqb0, irqb1, irqb2, irqb3, irqb4, irqb5, irqb6, irqb7;
interrupt_controller dut(
.*);
always #100 clk = clk === 1'b0;
task write_reg(input logic [2:0] _addr, input logic [7:0] _data);
@(negedge clk);
cs <= '1;
addr <= _addr;
rwb <= '0;
i_data <= '1;
@(posedge clk);
i_data <= _data;
@(negedge clk);
cs <= '0;
rwb <= '1;
endtask
task read_reg(input logic [2:0] _addr, output logic [7:0] _data);
@(negedge clk);
cs <= '1;
addr <= _addr;
rwb <= '1;
i_data <= '1;
@(posedge clk);
_data <= o_data;
@(negedge clk);
cs <= '0;
rwb <= '1;
endtask
initial
begin
$dumpfile("interrupt_controller.vcd");
$dumpvars(0,sim);
end
initial begin
reset <= '1;
irqb0 <= '1;
irqb1 <= '1;
irqb2 <= '1;
irqb3 <= '1;
irqb4 <= '1;
irqb5 <= '1;
irqb6 <= '1;
irqb7 <= '1;
repeat(5) @(posedge clk);
reset <= '0;
repeat(5) @(posedge clk);
irqb0 <= '0;
repeat(5) @(posedge clk);
$finish();
end
endmodule

View File

@@ -1,102 +0,0 @@
module sim();
timeunit 10ns;
timeprecision 1ns;
logic clk_50;
logic i_clk;
logic i_rst;
logic i_cs;
logic i_rwb;
logic [1:0] i_addr;
logic [7:0] i_data;
logic [7:0] o_data;
logic o_spi_cs;
logic o_spi_clk;
logic o_spi_mosi;
logic i_spi_miso;
spi_controller dut(.*);
always #1 clk_50 = clk_50 === 1'b0;
always #100 i_clk = i_clk === 1'b0;
task write_reg(input logic [2:0] _addr, input logic [7:0] _data);
@(negedge i_clk);
i_cs <= '1;
i_addr <= _addr;
i_rwb <= '0;
i_data <= '1;
@(posedge i_clk);
i_data <= _data;
@(negedge i_clk);
i_cs <= '0;
i_rwb <= '1;
endtask
task read_reg(input logic [2:0] _addr, output logic [7:0] _data);
@(negedge i_clk);
i_cs <= '1;
i_addr <= _addr;
i_rwb <= '1;
i_data <= '1;
@(posedge i_clk);
_data <= o_data;
@(negedge i_clk);
i_cs <= '0;
i_rwb <= '1;
endtask
initial
begin
$dumpfile("spi_controller.vcd");
$dumpvars(0,sim);
end
logic [7:0] data;
initial begin
i_rst <= '1;
repeat(5) @(posedge i_clk);
i_cs <= '0;
i_rwb <= '1;
i_addr <= '0;
i_rst <= '0;
repeat(5) @(posedge i_clk);
write_reg(3, 1);
write_reg(2, 8'hFF);
data = (1 << 7);
while(data & (1 << 7)) begin
read_reg(3, data);
end
write_reg(3, 0);
read_reg(1, data);
assert(data == 8'h55);
repeat(50) @(posedge i_clk);
$finish();
end
logic [7:0] _spi_device_data;
initial begin
_spi_device_data <= 8'h55;
end
always @(edge o_spi_clk) begin
if (o_spi_cs == '0) begin
if (o_spi_clk == '1)
i_spi_miso <= _spi_device_data[7];
if (o_spi_clk == '0)
_spi_device_data <= _spi_device_data << 1;
end
end
endmodule

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,154 @@
`timescale 1ns/1ps
module sim_top();
`include "include/super6502_sdram_controller_define.vh"
logic r_sysclk, r_sdrclk, r_clk_50, r_clk_2;
// clk_100
initial begin
r_sysclk <= '1;
forever begin
#5 r_sysclk <= ~r_sysclk;
end
end
// clk_200
initial begin
r_sdrclk <= '1;
forever begin
#2.5 r_sdrclk <= ~r_sdrclk;
end
end
// clk_50
initial begin
r_clk_50 <= '1;
forever begin
#10 r_clk_50 <= ~r_clk_50;
end
end
// clk_2
initial begin
r_clk_2 <= '1;
forever begin
#250 r_clk_2 <= ~r_clk_2;
end
end
initial begin
$dumpfile("sim_top.vcd");
$dumpvars(0,sim_top);
end
logic button_reset;
initial begin
button_reset <= '0;
repeat(10) @(r_clk_2);
button_reset <= '1;
repeat(20000) @(r_clk_2);
$finish();
end
logic w_cpu_reset;
logic [15:0] w_cpu_addr;
logic [7:0] w_cpu_data_from_cpu, w_cpu_data_from_dut;
logic w_cpu_rdy;
logic w_cpu_we;
logic w_cpu_phi2;
//TODO: this
cpu_65c02 u_cpu(
.phi2(w_cpu_phi2),
.reset(~w_cpu_reset),
.AB(w_cpu_addr),
.RDY(w_cpu_rdy),
.IRQ('0),
.NMI('0),
.DI_s1(w_cpu_data_from_dut),
.DO(w_cpu_data_from_cpu),
.WE(w_cpu_we)
);
// Having the super6502 causes an infinite loop,
// but just the rom works. Need to whittle down
// which block is causing it.
// rom #(.DATA_WIDTH(8), .ADDR_WIDTH(12)) u_rom(
// .addr(w_cpu_addr[11:0]),
// .clk(r_clk_2),
// .data(w_cpu_data_from_dut)
// );
//TODO: also this
super6502 u_dut(
.i_sysclk(r_sysclk),
.i_sdrclk(r_sdrclk),
.i_tACclk(~r_sdrclk),
.clk_50(r_clk_50),
.clk_2(r_clk_2),
.button_reset(button_reset),
.cpu_resb(w_cpu_reset),
.cpu_addr(w_cpu_addr),
.cpu_data_out(w_cpu_data_from_dut),
.cpu_data_in(w_cpu_data_from_cpu),
.cpu_rwb(~w_cpu_we),
.cpu_rdy(w_cpu_rdy),
.cpu_phi2(w_cpu_phi2),
.o_sdr_CKE(w_sdr_CKE),
.o_sdr_n_CS(w_sdr_n_CS),
.o_sdr_n_WE(w_sdr_n_WE),
.o_sdr_n_RAS(w_sdr_n_RAS),
.o_sdr_n_CAS(w_sdr_n_CAS),
.o_sdr_BA(w_sdr_BA),
.o_sdr_ADDR(w_sdr_ADDR),
.i_sdr_DATA(w_sdr_DQ),
.o_sdr_DATA(w_sdr_DATA),
.o_sdr_DATA_oe(w_sdr_DATA_oe),
.o_sdr_DQM(w_sdr_DQM)
);
wire w_sdr_CKE;
wire w_sdr_n_CS;
wire w_sdr_n_WE;
wire w_sdr_n_RAS;
wire w_sdr_n_CAS;
wire [BA_WIDTH -1:0]w_sdr_BA;
wire [ROW_WIDTH -1:0]w_sdr_ADDR;
wire [DQ_GROUP *DQ_WIDTH -1:0]w_sdr_DATA;
wire [DQ_GROUP *DQ_WIDTH -1:0]w_sdr_DATA_oe;
wire [DQ_GROUP -1:0]w_sdr_DQM;
wire [DQ_GROUP *DQ_WIDTH -1:0]w_sdr_DQ;
genvar i, j;
generate
for (i=0; i<DQ_GROUP*DQ_WIDTH; i=i+1)
begin: DQ_map
assign w_sdr_DQ[i] = (w_sdr_DATA_oe[i])?
w_sdr_DATA[i]:1'bz;
end
for (j=0; j<DQ_GROUP; j=j+1)
begin : mem_inst
generic_sdr inst_sdr
(
.Dq(w_sdr_DQ[((j+1)*(DQ_WIDTH))-1:((j)*DQ_WIDTH)]),
.Addr(w_sdr_ADDR[ROW_WIDTH-1:0]),
.Ba(w_sdr_BA[BA_WIDTH-1:0]),
.Clk(~r_sdrclk),
.Cke(w_sdr_CKE),
.Cs_n(w_sdr_n_CS),
.Ras_n(w_sdr_n_RAS),
.Cas_n(w_sdr_n_CAS),
.We_n(w_sdr_n_WE),
.Dqm(w_sdr_DQM[j])
);
end
endgenerate
endmodule

View File

@@ -1,75 +0,0 @@
module sim();
timeunit 10ns;
timeprecision 1ns;
logic clk;
logic rwb;
logic clk_50;
logic reset;
logic [2:0] addr;
logic [7:0] i_data;
logic [7:0] o_data;
logic cs;
logic irq;
timer dut(
.*);
always #1 clk_50 = clk_50 === 1'b0;
always #100 clk = clk === 1'b0;
task write_reg(input logic [2:0] _addr, input logic [7:0] _data);
@(negedge clk);
cs <= '1;
addr <= _addr;
rwb <= '0;
i_data <= '1;
@(posedge clk);
i_data <= _data;
@(negedge clk);
cs <= '0;
rwb <= '1;
endtask
task read_reg(input logic [2:0] _addr, output logic [7:0] _data);
@(negedge clk);
cs <= '1;
addr <= _addr;
rwb <= '1;
i_data <= '1;
@(posedge clk);
_data <= o_data;
@(negedge clk);
cs <= '0;
rwb <= '1;
endtask
initial
begin
$dumpfile("timer.vcd");
$dumpvars(0,sim);
end
logic [7:0] read_data;
initial begin
reset <= '1;
repeat(5) @(posedge clk);
reset <= '0;
write_reg(5, 16);
repeat(1024) @(posedge clk);
repeat(10) begin
read_reg(0, read_data);
$display("Read: %d", read_data);
repeat(1024) @(posedge clk);
end
$finish();
end
endmodule

View File

@@ -1,17 +1,21 @@
module addr_decode
(
input [15:0] i_addr,
input logic [15:0] i_addr,
output o_rom_cs,
output o_leds_cs,
output o_timer_cs,
output o_multiplier_cs,
output o_divider_cs,
output o_uart_cs,
output o_spi_cs,
output o_sdram_cs
output logic o_rom_cs,
output logic o_leds_cs,
output logic o_timer_cs,
output logic o_multiplier_cs,
output logic o_divider_cs,
output logic o_uart_cs,
output logic o_spi_cs,
output logic o_sdram_cs
);
// assign o_rom_cs = '1;
always_comb begin
o_rom_cs = (i_addr >= 16'hf000) ? 1 : 0;
end
assign o_rom_cs = i_addr >= 16'hf000 && i_addr <= 16'hffff;
assign o_timer_cs = i_addr >= 16'heff8 && i_addr <= 16'heffb;
assign o_multiplier_cs = i_addr >= 16'heff0 && i_addr <= 16'heff7;

View File

@@ -104,7 +104,7 @@ end
logic r_wait;
logic _r_wait;
assign o_wait = r_wait;
assign o_wait = r_wait & i_cs;
// we need to assert rdy low until a falling edge if a reset happens
@@ -245,10 +245,11 @@ logic [3:0] o_dbg_BA;
logic [25:0] o_dbg_ADDR;
logic [31:0] o_dbg_DATA_out;
logic [31:0] o_dbg_DATA_in;
logic o_sdr_init_done;
logic sdr_init_done;
logic [3:0] o_sdr_state;
assign o_ref_req = o_dbg_ref_req;
assign o_sdr_init_done = sdr_init_done;
sdram_controller u_sdram_controller(
@@ -265,7 +266,7 @@ sdram_controller u_sdram_controller(
.i_din(r_write_data), //Data to write to SDRAM. Twice normal width when running at half speed (hence the even addresses)
.i_dm(r_dm), //dm (r_dm)
.o_dout(w_data_o), //Data read from SDRAM, doubled as above.
.o_sdr_init_done(o_sdr_init_done), //Indicates that the SDRAM initialization is done.
.o_sdr_init_done(sdr_init_done), //Indicates that the SDRAM initialization is done.
.o_wr_ack(w_wr_ack), //Write acknowledge, handshake with we
.o_rd_ack(w_rd_ack), //Read acknowledge, handshake with re
.o_rd_valid(w_rd_valid),//Read valid. The data on o_dout is valid

View File

@@ -90,6 +90,7 @@ always_comb begin
1: o_data = r_input_data;
2:;
3: o_data = {active, r_control[6:0]};
default: o_data = 'x;
endcase
end

View File

@@ -81,17 +81,6 @@ logic w_divider_cs;
logic w_uart_cs;
logic w_spi_cs;
addr_decode u_addr_decode(
.i_addr(cpu_addr),
.o_rom_cs(w_rom_cs),
.o_leds_cs(w_leds_cs),
.o_timer_cs(w_timer_cs),
.o_multiplier_cs(w_multiplier_cs),
.o_divider_cs(w_divider_cs),
.o_uart_cs(w_uart_cs),
.o_spi_cs(w_spi_cs),
.o_sdram_cs(w_sdram_cs)
);
logic [7:0] w_rom_data_out;
logic [7:0] w_leds_data_out;
@@ -103,6 +92,16 @@ logic [7:0] w_spi_data_out;
logic [7:0] w_sdram_data_out;
always_comb begin
w_rom_cs = cpu_addr >= 16'hf000 && cpu_addr <= 16'hffff;
w_timer_cs = cpu_addr >= 16'heff8 && cpu_addr <= 16'heffb;
w_multiplier_cs = cpu_addr >= 16'heff0 && cpu_addr <= 16'heff7;
w_divider_cs = cpu_addr >= 16'hefe8 && cpu_addr <= 16'hefef;
w_uart_cs = cpu_addr >= 16'hefe6 && cpu_addr <= 16'hefe7;
w_spi_cs = cpu_addr >= 16'hefd8 && cpu_addr <= 16'hefdb;
w_leds_cs = cpu_addr == 16'hefff;
w_sdram_cs = cpu_addr < 16'he000;
if (w_rom_cs)
cpu_data_out = w_rom_data_out;
else if (w_leds_cs)

View File

@@ -123,6 +123,8 @@ always_comb begin
o_data = status;
end
default: o_data = 'x;
endcase
end

View File

@@ -46,8 +46,9 @@ enum bit [1:0] {READY, WAIT, TRANSMIT} state, next_state;
always_ff @(posedge clk_50) begin
if (reset) begin
state = READY;
state <= READY;
irqb <= '1;
status <= '0;
end else begin
state <= next_state;
end

View File

@@ -20,6 +20,8 @@
# export PATH=$PATH:"$EFXPT_HOME/bin"
source $EFX_SETUP
export REPO_TOP=$(git rev-parse --show-toplevel)
# python -m venv .user_venv --system-site-packages
# . .user_venv/bin/activate

View File

@@ -7,7 +7,7 @@ NAME=bios
BIN=$(NAME).bin
HEX=$(NAME).hex
FPGA_IMG=../../hw/efinix_fpga/init_hex.mem
FPGA_IMG=$(REPO_TOP)/hw/efinix_fpga/init_hex.mem
EFX_RUN=/home/byron/Software/efinity/2023.1/scripts/efx_run.py
EFX_PRJ=/home/byron/Projects/super6502/hw/efinix_fpga/super6502.xml

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=loop_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,16 @@
.export _init, _nmi_int, _irq_int
.code
_nmi_int:
_irq_int:
_init:
lda #$00
@1: inc
sta $01
lda $01
cmp $01
beq @1
@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=simple_mem_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,24 @@
.export _init, _nmi_int, _irq_int
.code
_nmi_int:
_irq_int:
_init:
lda #$aa
sta $10
lda #$55
sta $11
lda #$ff
sta $12
lda #$00
sta $13
lda $10
lda $11
lda $12
lda $13
@1: bra @1

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