Cocotb tests.
diff --git a/cocotb_tests/Makefile b/cocotb_tests/Makefile
new file mode 100644
index 0000000..63d8c80
--- /dev/null
+++ b/cocotb_tests/Makefile
@@ -0,0 +1,13 @@
+SIM ?= icarus
+TOPLEVEL_LANG ?= verilog
+
+# normal simulation
+VERILOG_SOURCES += $(PWD)/tb.v $(PWD)/synthesized.v
+
+# TOPLEVEL is the name of the toplevel module in your Verilog or VHDL file
+TOPLEVEL = tb
+
+# MODULE is the basename of the Python test file
+MODULE = test
+
+include $(shell cocotb-config --makefiles)/Makefile.sim
diff --git a/cocotb_tests/as2650.v b/cocotb_tests/as2650.v
new file mode 120000
index 0000000..be03868
--- /dev/null
+++ b/cocotb_tests/as2650.v
@@ -0,0 +1 @@
+../verilog/rtl/as2650.v
\ No newline at end of file
diff --git a/cocotb_tests/synth.sh b/cocotb_tests/synth.sh
new file mode 100644
index 0000000..5595d8d
--- /dev/null
+++ b/cocotb_tests/synth.sh
@@ -0,0 +1 @@
+./yosys_e -p "read_verilog as2650.v; synth -top as2650; write_verilog synthesized.v;" && clear
diff --git a/cocotb_tests/tb.v b/cocotb_tests/tb.v
new file mode 100644
index 0000000..59914c9
--- /dev/null
+++ b/cocotb_tests/tb.v
@@ -0,0 +1,43 @@
+`default_nettype none
+`timescale 1ns/1ps
+
+module tb (
+ input reset,
+ input clk,
+ input sense,
+
+ output [12:0] adr,
+ output rw,
+ output opreq,
+ output m_io,
+ output d_c,
+ output flag,
+ output wrp,
+
+ input [7:0] dbus_in,
+ output [7:0] dbus_out,
+ output oeb
+ );
+
+ initial begin
+ $dumpfile ("tb.vcd");
+ $dumpvars (0, tb);
+ #1;
+ end
+
+ as2650 as2650 (
+ .reset(reset),
+ .clk(clk),
+ .sense(sense),
+ .adr(adr),
+ .rw(rw),
+ .opreq(opreq),
+ .m_io(m_io),
+ .d_c(d_c),
+ .flag(flag),
+ .dbus_in(dbus_in),
+ .dbus_out(dbus_out),
+ .oeb(oeb),
+ .wrp(wrp)
+ );
+endmodule
diff --git a/cocotb_tests/test.asm b/cocotb_tests/test.asm
new file mode 100644
index 0000000..3bf4a03
--- /dev/null
+++ b/cocotb_tests/test.asm
@@ -0,0 +1,409 @@
+PSL_CC1 equ 0b10000000
+PSL_CC0 equ 0b01000000
+PSL_IDC equ 0b00100000
+PSL_BANK equ 0b00010000
+PSL_WITH_CARRY equ 0b00001000
+PSL_OVERFLOW equ 0b00000100
+PSL_LOGICAL_COMP equ 0b00000010
+PSL_CARRY_FLAG equ 0b00000001
+
+mem_end equ 8191
+
+org 0
+programentry:
+ lodi,r0 0x16
+ strz,r1
+
+ stra,r1 mem_end
+
+ lodi,r3 0xFF
+ stra,r3 mem_end-1
+
+ lodi,r2 2
+ stra,r0 mem_end-4,r2
+
+ lodi,r0 data>>8%256
+ stra,r0 mem_end-6
+ lodi,r0 data%256
+ stra,r0 mem_end-5
+ loda,r2 *mem_end-6
+ lodz,r2
+ lodi,r1 4
+ stra,r0 mem_end-10,r1-
+ lodz,r1
+ stra,r0 mem_end-10,r1-
+ eorz,r0
+ strz,r3
+ loda,r0 *mem_end-6,r3+
+ strz,r1
+ stra,r1 mem_end-9
+
+relative_data_0:
+ nop
+ nop
+ lodi,r1 66
+ strr,r1 relative_data_0
+ eorz r0
+ lodr,r3 relative_data_0
+ stra,r3 mem_end-10
+
+ lodi,r0 data+2>>8%256
+ strr,r0 relative_data_0
+ lodi,r0 data+2%256
+ strr,r0 relative_data_0+1
+ lodr,r3 *relative_data_0
+ stra,r3 mem_end-11
+
+ lodi,r0 0xFF
+ eora,r0 data+3
+ stra,r0 mem_end-12
+
+ lodi,r3 0b10001010
+ iori,r3 0b10000101
+ stra,r3 mem_end-13
+
+relative_data_1:
+ nop
+ lodi,r0 16
+ strr,r0 relative_data_1
+ lodi,r2 8
+ addr,r2 relative_data_1
+ stra,r2 mem_end-14
+
+ lodi,r1 0xFF
+ addi,r1 3
+ stra,r1 mem_end-15
+ eorz,r0
+ addi,r0 1
+ stra,r0 mem_end-16
+
+ ppsl PSL_WITH_CARRY
+ lodi,r1 0xFF
+ addi,r1 3
+ stra,r1 mem_end-17
+ eorz,r0
+ addi,r0 1
+ stra,r0 mem_end-18
+ cpsl PSL_WITH_CARRY
+ lodi,r1 0xFF
+ addi,r1 3
+ stra,r1 mem_end-19
+ eorz,r0
+ addi,r0 1
+ stra,r0 mem_end-20
+
+ lodi,r0 16
+ suba,r0 data+4
+ stra,r0 mem_end-21
+
+ lodi,r3 5
+ subi,r3 8
+ stra,r3 mem_end-22
+ lodi,r0 15
+ lodi,r1 0
+ subz,r1
+ stra,r0 mem_end-23
+
+ ppsl PSL_WITH_CARRY
+ ppsl PSL_CARRY_FLAG
+ lodi,r3 5
+ subi,r3 8
+ stra,r3 mem_end-24
+ lodi,r0 15
+ lodi,r1 0
+ subz,r1
+ stra,r0 mem_end-25
+
+ cpsl PSL_CARRY_FLAG
+ lodi,r0 5
+ addi,r0 5
+ stra,r0 mem_end-26
+ addz,r0
+ stra,r0 mem_end-27
+ cpsl PSL_WITH_CARRY
+
+ redd,r0
+ redd,r1
+ redd,r2
+ redd,r3
+ addz,r1
+ addz,r2
+ addz,r3
+
+ stra,r0 mem_end-28
+
+ lodi,r0 100
+ redc,r3
+ redc,r3
+ redc,r3
+ subz,r3
+
+ stra,r0 mem_end-29
+
+ lodi,r1 55
+ lodi,r2 66
+ lodi,r3 10
+ wrtd,r1
+ wrtd,r2
+ wrtd,r3
+
+ lodi,r1 12
+ lodi,r2 38
+ lodi,r3 33
+ wrtc,r1
+ wrtc,r2
+ wrtc,r3
+
+ lodi,r0 0b00001111
+ rrr,r0
+ stra,r0 mem_end-30
+ rrl,r0
+ stra,r0 mem_end-31
+
+ ppsl PSL_WITH_CARRY
+ cpsl PSL_CARRY_FLAG
+ rrr,r0
+ stra,r0 mem_end-32
+ rrr,r0
+ stra,r0 mem_end-33
+ eorz,r0
+ rrl,r0
+ stra,r0 mem_end-34
+ rrl,r0
+ stra,r0 mem_end-35
+
+ lodi,r1 128
+ rrl,r1
+ spsl
+ stra,r0 mem_end-36
+ strz,r2
+ andi,r0 0b11110110
+ lpsl
+ spsl
+ stra,r0 mem_end-37
+ lodz,r2
+ lpsl
+ tpsl 0b00001001
+ spsl
+ andi,r0 0b11000000
+ stra,r0 mem_end-38
+ tpsl 2
+ spsl
+ andi,r0 0b11000000
+ stra,r0 mem_end-39
+ cpsl PSL_WITH_CARRY
+
+ lodi,r0 0b00001011
+ strz,r1
+ strz,r2
+ db 0xF6 ; tmi,r2 (not recognized by my assembler yet)
+ db 0b00000001
+ spsl
+ andi,r0 0b11000000
+ stra,r0 mem_end-40
+ db 0xF5 ; tmi,r1 (not recognized by my assembler yet)
+ db 0b11100001
+ spsl
+ andi,r0 0b11000000
+ stra,r0 mem_end-41
+
+ lodi,r0 55
+ bctr,un skip_1
+ eorz,r0
+skip_1:
+ stra,r0 mem_end-42
+
+ lodi,r1 6
+ stra,r0 mem_end-444,r1-
+ stra,r1 mem_end-43
+ stra,r0 mem_end-444,r1-
+ stra,r1 mem_end-44
+ stra,r0 mem_end-444,r1-
+ stra,r1 mem_end-45
+loop:
+ stra,r0 mem_end-444,r1-
+ brnr,r1 loop
+
+ lodi,r3 2
+ lodi,r0 55
+back_1:
+ bcfa,1 skip_2
+ lodi,r0 103
+skip_2:
+ stra,r0 mem_end-47,r3-
+ lodi,r0 180
+ brna,r3 back_1
+
+ lodi,r3 99
+ lodi,r0 200
+ subz,r3
+ spsl
+ andi,r0 0b11000000
+ stra,r0 mem_end-48
+
+ lodi,r2 120
+ adda,r2 data+7
+ bcta,2 skip_3
+ lodi,r2 0
+skip_3:
+ stra,r2 mem_end-49
+
+ lodi,r0 5
+ lodi,r3 0
+loop_2:
+ addi,r3 1
+ bdra,r0 loop_2
+ stra,r3 mem_end-50
+
+ lodi,r1 248
+ lodi,r2 0
+loop_3:
+ addi,r2 1
+ bira,r1 loop_3
+ stra,r2 mem_end-51
+
+ lodi,r0 5
+ lodi,r3 0
+loop_4:
+ addi,r3 1
+ bdrr,r0 loop_4
+ stra,r3 mem_end-52
+
+ lodi,r1 248
+ lodi,r2 0
+loop_5:
+ addi,r2 1
+ birr,r1 loop_5
+ stra,r2 mem_end-53
+
+ lodi,r2 55
+ comi,r2 55
+ spsl
+ andi,r0 0b11000000
+ stra,r0 mem_end-54
+
+ lodi,r3 7
+ coma,r3 data+8
+ spsl
+ andi,r0 0b11000000
+ stra,r0 mem_end-55
+
+ ppsl PSL_LOGICAL_COMP
+ lodi,r3 7
+ coma,r3 data+8
+ spsl
+ andi,r0 0b11000000
+ stra,r0 mem_end-56
+ cpsl PSL_LOGICAL_COMP
+
+ loda,r2 data+8
+ eorz,r0
+ comz,r2
+ spsl
+ andi,r0 0b11000000
+ stra,r0 mem_end-57
+
+ ppsl PSL_LOGICAL_COMP
+ comz,r2
+ spsl
+ andi,r0 0b11000000
+ stra,r0 mem_end-58
+
+ lodz,r2
+ comz,r2
+ spsl
+ andi,r0 0b11000000
+ stra,r0 mem_end-59
+ cpsl PSL_LOGICAL_COMP
+
+ lodi,r1 1
+ lodi,r2 2
+ lodi,r3 3
+ ppsl PSL_BANK
+ lodi,r1 4
+ lodi,r2 5
+ lodi,r3 6
+ cpsl PSL_BANK
+
+ stra,r1 mem_end-60
+ stra,r2 mem_end-61
+ stra,r3 mem_end-62
+ ppsl PSL_BANK
+ stra,r1 mem_end-63
+ stra,r2 mem_end-64
+ stra,r3 mem_end-65
+ cpsl PSL_BANK
+
+ bcta,un sub_1_end
+a_subroutine_1:
+ lodi,r0 5
+ addi,r0 10
+ addz,r1
+ retc,un
+sub_1_end:
+ lodi,r1 1
+ bstr,un a_subroutine_1
+ stra,r0 mem_end-66
+ eorz,r0
+ strz,r1
+ bsta,un a_subroutine_1
+ stra,r0 mem_end-67
+ bctr,un sub_2_end
+a_subroutine_2:
+ lodi,r3 6
+ comi,r2 0
+ retc,eq
+ lodi,r3 7
+ retc,un
+sub_2_end:
+ lodi,r2 5
+ bstr,un a_subroutine_2
+ stra,r3 mem_end-68
+ lodi,r2 0
+ bsta,un a_subroutine_2
+ stra,r3 mem_end-69
+
+ lodi,r2 5
+ lodi,r3 8
+ bsta,un mul_8x8_8
+ stra,r0 mem_end-70
+
+ lodi,r0 5
+ lodi,r1 8
+ db 0x90
+ stra,r2 mem_end-71
+
+ halt
+
+mul_8x8_8:
+ spsl
+ lodi,r1 8
+ eorz r0
+ ppsl PSL_WITH_CARRY
+mul_8x8_8_loop:
+ rrr,r2
+ ;tpsl PSL_CARRY_FLAG
+ db 183 ;Same instruction, but alternative encoding
+ db 1
+ bcfr,0 mul_8x8_8_no_carry
+ cpsl PSL_CARRY_FLAG
+ addz r3
+mul_8x8_8_no_carry:
+ rrl,r3
+ andi,r3 254
+ bdrr,r1 mul_8x8_8_loop
+ strz r1
+ lpsl
+ lodz r1
+ retc,un
+
+data:
+ db 70
+ db 6
+ db 11
+ db 0xAA
+ db 8
+ db 0
+ db 0
+ db 100
+ db 200
diff --git a/cocotb_tests/test.py b/cocotb_tests/test.py
new file mode 100644
index 0000000..166666f
--- /dev/null
+++ b/cocotb_tests/test.py
@@ -0,0 +1,132 @@
+import cocotb
+import random
+from cocotb.clock import Clock
+from cocotb.triggers import Timer, ClockCycles
+
+@cocotb.test()
+async def test_cpu(dut):
+ dut._log.info("start")
+
+ memory = [0] * 8192
+
+ with open("test.bin", mode='rb') as file:
+ for i in range(0, 8192):
+ a = file.read(1)
+ if len(a) > 0:
+ memory[i] = a[0]
+
+ dut.sense.value = 0
+ dut.dbus_in.value = 0
+ dut.reset.value = 1
+ clock = Clock(dut.clk, 1, units="us")
+ cocotb.start_soon(clock.start())
+ await ClockCycles(dut.clk, 3)
+ dut.reset.value = 0
+
+ d_counter = 0
+ c_counter = 0
+ expected_io_out_d = [55, 66, 10]
+ expected_io_out_c = [12, 38, 33]
+ d_out_counter = 0
+ c_out_counter = 0
+ tt = 0
+ while dut.as2650.halted == 0:
+ await Timer(0.25, units="us")
+ tt += 1
+ dut.dbus_in.value = 0
+ if dut.oeb.value == 0:
+ if dut.rw.value == 1 and dut.opreq.value == 1 and dut.wrp.value == 1:
+ if dut.m_io == 1:
+ memory[dut.adr.value] = dut.dbus_out.value
+ else:
+ if dut.wrp.value == 1:
+ if dut.d_c.value == 1:
+ assert dut.dbus_out.value == expected_io_out_d[d_out_counter]
+ if tt % 5 == 4:
+ d_out_counter += 1
+ else:
+ assert dut.dbus_out.value == expected_io_out_c[c_out_counter]
+ if tt % 5 == 4:
+ c_out_counter += 1
+ else:
+ if dut.rw.value == 0 and dut.opreq.value == 1:
+ if dut.m_io.value == 1:
+ dut.dbus_in.value = memory[dut.adr.value]
+ else:
+ if dut.d_c.value == 1:
+ dut.dbus_in.value = d_counter
+ if tt % 4 == 3:
+ d_counter += 1
+ else:
+ dut.dbus_in.value = c_counter
+ if tt % 4 == 3:
+ c_counter += 2
+
+ assert memory[8191] == 0x16
+ assert memory[8190] == 0xFF
+ assert memory[8189] == 0x16
+ assert memory[8191-7] == 70
+ assert memory[8191-8] == 3
+ assert memory[8191-9] == 6
+ assert memory[8191-10] == 66
+ assert memory[8191-11] == 11
+ assert memory[8191-12] == 0b01010101
+ assert memory[8191-13] == 0b10001111
+ assert memory[8191-14] == 24
+ assert memory[8191-15] == 2
+ assert memory[8191-16] == 1
+ assert memory[8191-17] == 2
+ assert memory[8191-18] == 2
+ assert memory[8191-19] == 2
+ assert memory[8191-20] == 1
+ assert memory[8191-21] == 8
+ assert memory[8191-22] == 0b11111101
+ assert memory[8191-23] == 15
+ assert memory[8191-24] == 0b11111101
+ assert memory[8191-25] == 14
+ assert memory[8191-26] == 10
+ assert memory[8191-27] == 20
+ assert memory[8191-28] == 6
+ assert memory[8191-29] == 96
+ assert memory[8191-30] == 0b10000111
+ assert memory[8191-31] == 0b00001111
+ assert memory[8191-32] == 0b00000111
+ assert memory[8191-33] == 0b10000011
+ assert memory[8191-34] == 0b00000001
+ assert memory[8191-35] == 0b00000010
+ assert memory[8191-36] == 0b00001001
+ assert memory[8191-37] == 0
+ assert memory[8191-38] == 0
+ assert memory[8191-39] == 0b10000000
+ assert memory[8191-40] == 0
+ assert memory[8191-41] == 0b10000000
+ assert memory[8191-42] == 55
+ assert memory[8191-43] == 5
+ assert memory[8191-44] == 4
+ assert memory[8191-45] == 3
+ assert memory[8191-46] == 103
+ assert memory[8191-47] == 180
+ assert memory[8191-48] == 0b01000000
+ assert memory[8191-49] == 220
+ assert memory[8191-50] == 5
+ assert memory[8191-51] == 8
+ assert memory[8191-52] == 5
+ assert memory[8191-53] == 8
+ assert memory[8191-54] == 0
+ assert memory[8191-55] == 0b01000000
+ assert memory[8191-56] == 0b10000000
+ assert memory[8191-57] == 0b01000000
+ assert memory[8191-58] == 0b10000000
+ assert memory[8191-59] == 0
+ assert memory[8191-60] == 1
+ assert memory[8191-61] == 2
+ assert memory[8191-62] == 3
+ assert memory[8191-63] == 4
+ assert memory[8191-64] == 5
+ assert memory[8191-65] == 6
+ assert memory[8191-66] == 16
+ assert memory[8191-67] == 15
+ assert memory[8191-68] == 7
+ assert memory[8191-69] == 6
+ assert memory[8191-70] == 40
+ assert memory[8191-71] == 40
diff --git a/cocotb_tests/test.sh b/cocotb_tests/test.sh
new file mode 100644
index 0000000..4554b4a
--- /dev/null
+++ b/cocotb_tests/test.sh
@@ -0,0 +1 @@
+./2650Tools asm test.asm && make
diff --git a/verilog/rtl/as2650.v b/verilog/rtl/as2650.v
index acb2d3d..052f562 100644
--- a/verilog/rtl/as2650.v
+++ b/verilog/rtl/as2650.v
@@ -332,7 +332,7 @@
* Misc instructions
*/
if(cycle == 2) begin
- if(ins_reg == 'h90 || ins_reg == 'h91) begin //Hijacking undocumented opcodes to add a multiply instruction
+ if(ins_reg == 'h90 || ins_reg == 'h91) begin //Using undocumented opcodes to add a multiply instruction
//(psl[4] ? r123_2[2] : r123[2]);
if(psl[4]) begin
r123_2[1] <= r0 * r123_2[0];