Explorar o código

Big project update

Many changes. Switched from DRAM to M9K system memory. This enabled
mutliple things:
1. Properly synthisize processor on FPGA which allowed to discover fix multiple
   datapath and other logic problems.
2. Add flash function that allows read/update rom and ram content without synthesation.
3. Also read ram content during runtime for advanced debugging.
4. Assembler added sections that specify which memory to write to.
5. Writing new code, which lead to implementing new instructions:
	* ADDI, SUBI, ANDI, ORI, XORI
	* CI0, CI1, CI2
	* ADDC, SUBC
Min %!s(int64=6) %!d(string=hai) anos
pai
achega
b346abb6a3

+ 24 - 9
Makefile

@@ -19,9 +19,15 @@ GENTABLE_BIN = python3 tools/gen_sv.py
 ASMC = python3 tools/risc8asm.py
 
 MEMSIZE ?= 4096
+RAMSIZE ?= -1
 MEMDEP := $(shell find memory -name '*.asm')
 MEMSLICES = 0 1 2 3
-MEMRES = $(foreach i,$(MEMSLICES),$(MEMDEP:.asm=_$(i).mem)) $(foreach i,$(MEMSLICES),$(MEMDEP:.asm=_$(i).mif))
+MEMRES = $(foreach i,$(MEMSLICES),$(MEMDEP:.asm=.text_$(i).mem)) \
+		$(foreach i,$(MEMSLICES),$(MEMDEP:.asm=.text_$(i).mif)) \
+		$(foreach i,$(MEMSLICES),$(MEMDEP:.asm=.text_$(i).uhex)) \
+		$(MEMDEP:.asm=.data.mem) \
+		$(MEMDEP:.asm=.data.uhex) \
+		$(MEMDEP:.asm=.data.mif)
 
 VERILOG ?= $(wildcard src/*/*.sv) 
 
@@ -79,17 +85,26 @@ testbench: compile
 
 compile_mem: $(MEMRES)
 
-%_0.mem %_1.mem %_2.mem %_3.mem: %.asm
-	$(ASMC) -t mem -f $< -S $(words $(MEMSLICES)) -l $(MEMSIZE)
+%.text_0.mem %.text_1.mem %.text_2.mem %.text_3.mem: %.asm
+	$(ASMC) -t mem -f $< -S $(words $(MEMSLICES)) .text
 
-%_0.mif %_1.mif %_2.mif %_3.mif: %.asm
-	$(ASMC) -t mif -f $< -S $(words $(MEMSLICES)) -l $(MEMSIZE)
+%.text_0.mif %.text_1.mif %.text_2.mif %.text_3.mif: %.asm
+	$(ASMC) -t mif -f $< -S $(words $(MEMSLICES)) .text
 
-%.mem: %.asm
-	$(ASMC) -t mem -o $@ -f $< -l $(MEMSIZE)
+%.text_0.uhex %.text_1.uhex %.text_2.uhex %.text_3.uhex: %.asm
+	$(ASMC) -t uhex -f $< -S $(words $(MEMSLICES)) .text
 
-%.mif: %.asm
-	$(ASMC) -t mif -o $@ -f $< -l $(MEMSIZE)
+%.data.mem: %.asm
+	$(ASMC) -t mem -f $< .data
+
+%.data.mif: %.asm
+	$(ASMC) -t mif -f $< .data
+
+%.data.uhex: %.asm
+	$(ASMC) -t uhex -f $< .data
+
+flash: $(MEMRES)
+	$(QUARTUS_DIR)/bin/quartus_stp -t ./scripts/update_risc8.tcl
 
 clean:
 	rm -f $(MEMRES)

+ 2 - 1
UCL_project_y3.qsf

@@ -120,6 +120,7 @@ set_global_assignment -name EDA_TEST_BENCH_NAME top_tb -section_id eda_simulatio
 set_global_assignment -name EDA_DESIGN_INSTANCE_NAME NA -section_id top_tb
 set_global_assignment -name EDA_TEST_BENCH_MODULE_NAME top_tb -section_id top_tb
 set_global_assignment -name EDA_TEST_BENCH_FILE src/top.sv -section_id top_tb
+set_instance_assignment -name PARTITION_HIERARCHY root_partition -to | -section_id Top
 set_global_assignment -name SYSTEMVERILOG_FILE src/blocks/rom.sv
 set_global_assignment -name SYSTEMVERILOG_FILE src/project.sv
 set_global_assignment -name SYSTEMVERILOG_FILE src/top.sv
@@ -138,4 +139,4 @@ set_global_assignment -name SYSTEMVERILOG_FILE src/blocks/memory.sv
 set_global_assignment -name QIP_FILE quartus/pll_clk.qip
 set_global_assignment -name SYSTEMVERILOG_FILE src/blocks/alu.sv
 set_global_assignment -name QIP_FILE quartus/risc8_rom.qip
-set_instance_assignment -name PARTITION_HIERARCHY root_partition -to | -section_id Top
+set_global_assignment -name QIP_FILE quartus/m9k_ram_init.qip

+ 0 - 88
memory/risc8_test.asm

@@ -1,88 +0,0 @@
-b1111_0010 // 0x0000
-0x0008
-b1011_0000 // 0x0003 func AddAllBy1
-b1011_0100 // 0x0004
-b1011_1000 // 0x0005
-b1011_1100 // 0x0006
-b1111_0001 // 0x0007
-
-COPY r0 0x15 // 0x0008
-COPY r2 r0   // 0x000a
-COPY r1 0x0a // 0x000b
-
-b1111_0000 // 0x000d Call AddAllBy1
-0x0003
-ADD  r0 r1 // 0x000f
-COPY r0 r2 // 0x0010
-SUB  r0 r1 
-COPY r0 r2
-AND  r0 r1
-COPY r0 r2
-OR  r0 r1
-COPY r0 r2
-XOR  r0 r1
-COPY r0 r2
-COPY r0 100
-MUL  r0 r1
-b1011_1110 // Load ALU_HI to r3
-COPY r0 r2
-DIV  r0 r1
-b1011_1110
-DIV  r1 r2
-b1011_1110
-b1011_0000 // &r0++
-b1011_0000 // &r0++
-b1011_0001 // &r0--
-b1011_0001 // &r0--
-
-COPY r0 32h 
-COPY r1 4fh
-b1010_0001  // Store 32 to high memory
-b1010_0111  // Store 4f to low 000001h
-0x000001
-COPY r0 0
-COPY r1 r0
-b1010_0000
-0x000001
-b1010_0010
-0x000001
-
-
-b1101_0000 // Branch to 0x000f if r1 == 0
-0x00000f   
-COPY r3 40h
-b1101_1110 // Branch to 0x000f if r1 >= 41h
-0x41000f   
-b1101_1101 // Branch to 0x000f if r1 > 40h
-0x40000f   
-b1101_1110 // Branch to 0x000f if r1 >= 40h
-0x40000f   
-
-
-// Testing COM
-b1100_0010
-ffh
-
-// Testing Stack
-COPY r0 11h
-COPY r1 22h
-COPY r2 33h
-COPY r3 44h
-b1100_0000  // PUSH r0
-b1100_0100  // PUSH r1
-b1100_1000  // PUSH r2
-b1100_1100  // PUSH r3
-COPY r3 55h
-b1100_1100  // PUSH r2
-
-COPY r0 00h
-b1100_0001 // POP r2
-b1100_0001 // POP r2
-b1100_0001 // POP r2
-b1100_0001 // POP r2
-b1100_0001 // POP r2
-
-
-
-b1111_0010 // Reset
-0x0000

+ 0 - 10
memory/risc8_test.mem

@@ -1,10 +0,0 @@
-00 0f 08 05 0a 11 02 21
-02 31 02 41 02 51 02 00
-64 61 be 02 71 be 76 be
-b0 b0 b1 b1 00 32 05 4f
-a1 a7 01 00 00 00 00 04
-a0 01 00 00 a2 01 00 00
-c2 ff 00 11 05 22 0a 33
-0f 44 c0 c4 c8 cc 0f 55
-cc 00 00 c1 c1 c1 c1 c1
-

+ 0 - 16
memory/rom_test.mem

@@ -1,16 +0,0 @@
-00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f
-10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f
-20 21 22 23 24 25 26 27 28 29 2a 2b 2c 2d 2e 2f
-30 31 32 33 34 35 36 37 38 39 3a 3b 3c 3d 3e 3f
-40 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f
-50 51 52 53 54 55 56 57 58 59 5a 5b 5c 5d 5e 5f
-60 61 62 63 64 65 66 67 68 69 6a 6b 6c 6d 6e 6f
-70 71 72 73 74 75 76 77 78 79 7a 7b 7c 7d 7e 7f
-80 81 82 83 84 85 86 87 88 89 8a 8b 8c 8d 8e 8f
-90 91 92 93 94 95 96 97 98 99 9a 9b 9c 9d 9e 9f
-a0 a1 a2 a3 a4 a5 a6 a7 a8 a9 aa ab ac ad ae af
-b0 b1 b2 b3 b4 b5 b6 b7 b8 b9 ba bb bc bd be bf
-c0 c1 c2 c3 c4 c5 c6 c7 c8 c9 ca cb cc cd ce cf
-d0 d1 d2 d3 d4 d5 d6 d7 d8 d9 da db dc dd de df
-e0 e1 e2 e3 e4 e5 e6 e7 e8 e9 ea eb ec ed ee ef
-f0 f1 f2 f3 f4 f5 f6 f7 f8 f9 fa fb fc fd fe ff

+ 6 - 0
scripts/check_mem.sh

@@ -0,0 +1,6 @@
+#!/bin/bash
+
+h1=`sha1sum $1 | cut -d " " -f1`
+h2=`echo -n $2 | sha1sum | cut -d " " -f1`
+
+[[ "$h1" == "$h2" ]] && echo "OK" || echo "FAIL"

+ 26 - 0
scripts/check_rom_risc8.tcl

@@ -0,0 +1,26 @@
+foreach hardware_name [get_hardware_names] {
+	if { [string match "USB-Blaster*" $hardware_name] } {
+		set usbblaster_name $hardware_name
+	}
+}
+puts "JTAG chain: $usbblaster_name";
+foreach device_name [get_device_names -hardware_name $usbblaster_name] {
+	if { [string match "@1*" $device_name] } {
+		set test_device $device_name
+	}
+}
+puts "Device: $test_device";
+begin_memory_edit -hardware_name $hardware_name -device_name $device_name
+
+set content [read_content_from_memory -instance_index 1 -start_address 0 -word_count 1024 -content_in_hex]
+puts "Checking rom0...[exec ./check_mem.sh ./memory/risc8.text_0.uhex $content]"
+set content [read_content_from_memory -instance_index 2 -start_address 0 -word_count 1024 -content_in_hex]
+puts "Checking rom1...[exec ./check_mem.sh ./memory/risc8.text_1.uhex $content]"
+set content [read_content_from_memory -instance_index 3 -start_address 0 -word_count 1024 -content_in_hex]
+puts "Checking rom2...[exec ./check_mem.sh ./memory/risc8.text_2.uhex $content]"
+set content [read_content_from_memory -instance_index 4 -start_address 0 -word_count 1024 -content_in_hex]
+puts "Checking rom3...[exec ./check_mem.sh ./memory/risc8.text_3.uhex $content]"
+
+puts "Done!";
+end_memory_edit
+

+ 3 - 0
scripts/mem2hex.sh

@@ -0,0 +1,3 @@
+#!/bin/bash
+echo -n `grep -o '^[^//]*' "$1" | tr [:lower:] [:upper:] | tr -d '\n '`
+

+ 18 - 0
scripts/read_ram_risc8.tcl

@@ -0,0 +1,18 @@
+foreach hardware_name [get_hardware_names] {
+	if { [string match "USB-Blaster*" $hardware_name] } {
+		set usbblaster_name $hardware_name
+	}
+}
+puts "JTAG chain: $usbblaster_name";
+foreach device_name [get_device_names -hardware_name $usbblaster_name] {
+	if { [string match "@1*" $device_name] } {
+		set test_device $device_name
+	}
+}
+puts "Device: $test_device";
+begin_memory_edit -hardware_name $hardware_name -device_name $device_name
+
+set content [read_content_from_memory -instance_index 0 -start_address 0 -word_count 4096 -content_in_hex]
+end_memory_edit
+
+puts "\n[exec echo $content | fold -w64 ]\n"

+ 39 - 0
scripts/update_risc8.tcl

@@ -0,0 +1,39 @@
+foreach hardware_name [get_hardware_names] {
+	if { [string match "USB-Blaster*" $hardware_name] } {
+		set usbblaster_name $hardware_name
+	}
+}
+puts "JTAG chain: $usbblaster_name";
+foreach device_name [get_device_names -hardware_name $usbblaster_name] {
+	if { [string match "@1*" $device_name] } {
+		set test_device $device_name
+	}
+}
+puts "Device: $test_device";
+begin_memory_edit -hardware_name $hardware_name -device_name $device_name
+
+puts "Flashing rom0...";
+set content [exec cat ./memory/risc8.text_0.uhex]
+write_content_to_memory -instance_index 1 -content $content -content_in_hex -start_address 0 -word_count 1024
+
+puts "Flashing rom1...";
+set content [exec cat ./memory/risc8.text_1.uhex]
+write_content_to_memory -instance_index 2 -content $content -content_in_hex -start_address 0 -word_count 1024
+
+puts "Flashing rom2...";
+set content [exec cat ./memory/risc8.text_2.uhex]
+write_content_to_memory -instance_index 3 -content $content -content_in_hex -start_address 0 -word_count 1024
+
+puts "Flashing rom3...";
+set content [exec cat ./memory/risc8.text_3.uhex]
+write_content_to_memory -instance_index 4 -content $content -content_in_hex -start_address 0 -word_count 1024
+
+puts "Flashing ram0...";
+set content [exec cat ./memory/risc8.data.uhex]
+write_content_to_memory -instance_index 0 -content $content -content_in_hex -start_address 0 -word_count 4096
+
+puts "Done!";
+end_memory_edit
+
+
+

+ 19 - 0
simulation/modelsim/top_compile.do

@@ -0,0 +1,19 @@
+vlog -sv -work work +incdir+/home/min/devel/fpga/ucl_project_y3/db {/home/min/devel/fpga/ucl_project_y3/db/pll_clk_altpll.v}
+vlog -sv -work work +incdir+/home/min/devel/fpga/ucl_project_y3/quartus {/home/min/devel/fpga/ucl_project_y3/quartus/pll_clk.v}
+vlog -sv -work work +incdir+/home/min/devel/fpga/ucl_project_y3/src/blocks {/home/min/devel/fpga/ucl_project_y3/src/blocks/fifo.v}
+vlog -sv -work work +incdir+/home/min/devel/fpga/ucl_project_y3/src/blocks {/home/min/devel/fpga/ucl_project_y3/src/blocks/uart.v}
+vlog -sv -work work +incdir+/home/min/devel/fpga/ucl_project_y3/src/blocks {/home/min/devel/fpga/ucl_project_y3/src/blocks/rom.sv}
+vlog -sv -work work +incdir+/home/min/devel/fpga/ucl_project_y3/src/blocks {/home/min/devel/fpga/ucl_project_y3/src/blocks/sdram_control.sv}
+vlog -sv -work work +incdir+/home/min/devel/fpga/ucl_project_y3/src/blocks {/home/min/devel/fpga/ucl_project_y3/src/blocks/reg_file.sv}
+vlog -sv -work work +incdir+/home/min/devel/fpga/ucl_project_y3/src/blocks {/home/min/devel/fpga/ucl_project_y3/src/blocks/alu.sv}
+vlog -sv -work work +incdir+/home/min/devel/fpga/ucl_project_y3/src/blocks {/home/min/devel/fpga/ucl_project_y3/src/blocks/memory.sv}
+vlog -sv -work work +incdir+/home/min/devel/fpga/ucl_project_y3/src/blocks {/home/min/devel/fpga/ucl_project_y3/src/blocks/ram.sv}
+
+vlog -sv -work work +incdir+/home/min/devel/fpga/ucl_project_y3/src/risc {/home/min/devel/fpga/ucl_project_y3/src/risc/general.sv}
+vlog -sv -work work +incdir+/home/min/devel/fpga/ucl_project_y3/src/risc {/home/min/devel/fpga/ucl_project_y3/src/risc/datapath.sv}
+vlog -sv -work work +incdir+/home/min/devel/fpga/ucl_project_y3/src/risc {/home/min/devel/fpga/ucl_project_y3/src/risc/cpu.sv}
+vlog -sv -work work +incdir+/home/min/devel/fpga/ucl_project_y3/src/risc {/home/min/devel/fpga/ucl_project_y3/src/risc/controller.sv}
+
+vlog -sv -work work +incdir+/home/min/devel/fpga/ucl_project_y3/src {/home/min/devel/fpga/ucl_project_y3/src/project.sv}
+vlog -sv -work work +incdir+/home/min/devel/fpga/ucl_project_y3/src {/home/min/devel/fpga/ucl_project_y3/src/top.sv}
+

A diferenza do arquivo foi suprimida porque é demasiado grande
+ 53 - 0
simulation/modelsim/top_wave.do


+ 110 - 0
src/blocks/ram.sv

@@ -0,0 +1,110 @@
+
+module m9k_ram (
+	address,
+	clock,
+	data,
+	wren,
+	q);
+	
+	parameter PROGRAM = "";
+	parameter NAME="";
+	
+	input	[11:0]  address;
+	input	  clock;
+	input	[15:0]  data;
+	input	  wren;
+	output	[15:0]  q;
+`ifndef ALTERA_RESERVED_QIS
+// synopsys translate_off
+`endif
+	tri1	  clock;
+`ifndef ALTERA_RESERVED_QIS
+// synopsys translate_on
+`endif
+
+	wire [15:0] sub_wire0;
+	wire [15:0] q = sub_wire0[15:0];
+
+	initial $display({"Initialising RAM Memory: ", PROGRAM, ".mif"});
+
+	altsyncram	altsyncram_component (
+				.address_a (address),
+				.clock0 (clock),
+				.data_a (data),
+				.wren_a (wren),
+				.q_a (sub_wire0),
+				.aclr0 (1'b0),
+				.aclr1 (1'b0),
+				.address_b (1'b1),
+				.addressstall_a (1'b0),
+				.addressstall_b (1'b0),
+				.byteena_a (1'b1),
+				.byteena_b (1'b1),
+				.clock1 (1'b1),
+				.clocken0 (1'b1),
+				.clocken1 (1'b1),
+				.clocken2 (1'b1),
+				.clocken3 (1'b1),
+				.data_b (1'b1),
+				.eccstatus (),
+				.q_b (),
+				.rden_a (1'b1),
+				.rden_b (1'b1),
+				.wren_b (1'b0));
+	defparam
+		altsyncram_component.clock_enable_input_a = "BYPASS",
+		altsyncram_component.clock_enable_output_a = "BYPASS",
+		altsyncram_component.init_file = {PROGRAM, ".mif"},
+		altsyncram_component.intended_device_family = "Cyclone IV E",
+		altsyncram_component.lpm_hint = {"ENABLE_RUNTIME_MOD=YES,INSTANCE_NAME=", NAME},
+		altsyncram_component.lpm_type = "altsyncram",
+		altsyncram_component.numwords_a = 4096,
+		altsyncram_component.operation_mode = "SINGLE_PORT",
+		altsyncram_component.outdata_aclr_a = "NONE",
+		altsyncram_component.outdata_reg_a = "UNREGISTERED",
+		altsyncram_component.power_up_uninitialized = "FALSE",
+		altsyncram_component.ram_block_type = "M9K",
+		altsyncram_component.read_during_write_mode_port_a = "DONT_CARE",
+		altsyncram_component.widthad_a = 12,
+		altsyncram_component.width_a = 16,
+		altsyncram_component.width_byteena_a = 1;
+endmodule
+
+module pseudo_ram(addr, clk, data, wren, rden, q);
+	
+	input [11:0] addr;
+	input clk, wren, rden;
+	input [15:0] data;
+	output reg [15:0] q;
+	parameter PROGRAM = "";
+	
+	reg [15:0] memory [4095:0];
+	initial if(PROGRAM != "") begin
+			$readmemh({PROGRAM, ".mem"}, memory);
+			$display({"Initialising RAM Memory: ", PROGRAM, ".mem"});
+	end
+
+	always_ff@(posedge clk) begin
+		if(wren) memory[addr] <= data;
+		if (rden) q <= memory[addr];
+		else q <= 'x;
+	end
+	
+endmodule
+
+
+module ram(address, clk, data, wren, rden, q);
+
+	input [11:0] address;
+	input clk, wren, rden;
+	input [15:0] data;
+	output [15:0] q;
+	parameter PROGRAM = "";
+	
+	`ifdef SYNTHESIS
+		m9k_ram#(PROGRAM, "ram0") ram0(address, clk, data, wren, q);
+	`else
+		pseudo_ram#(PROGRAM) ram0(address, clk, data, wren, rden, q);
+	`endif
+
+endmodule

+ 2 - 2
src/blocks/reg_file.sv

@@ -17,8 +17,8 @@ module reg_file(clk, rst, rd_addr1, rd_addr2, rd_data1, rd_data2, wr_addr, wr_da
 		else if(wr_en) registry[wr_addr] <= wr_data;
 	end
 	
-	assign rd_data1 = registry[rd_addr1];
-	assign rd_data2 = registry[rd_addr2];
+	assign rd_data1 = ((rd_addr1 == wr_addr) & wr_en) ? wr_data : registry[rd_addr1];
+	assign rd_data2 = ((rd_addr2 == wr_addr) & wr_en) ? wr_data : registry[rd_addr2];
 	
 endmodule
 

+ 239 - 93
src/project.sv

@@ -38,25 +38,27 @@ module com_block(
 
 	/* UART */
 	reg [2:0] uart0_reg;
-	reg received;
+	reg uart0_recv;
 	reg uart0_transmit;
 	reg [7:0] tx_byte, rx_byte;
 	// Clock divide = 1e6 / (9600 * 4)
-	//uart#(.CLOCK_DIVIDE(26)) uart0(
-	uart#(.CLOCK_DIVIDE(1302)) uart0(
+	//uart#(.CLOCK_DIVIDE(1302)) uart0(
+	uart#(.CLOCK_DIVIDE(26)) uart0(
 			.clk(clk), 
-			.rst(rst), 
+			.rst(0), 
 			.rx(uart0_rx),
 			.tx(uart0_tx),
 			.tx_byte(tx_byte),
 			.rx_byte(rx_byte),
-			.received(received),
-			.is_receiving(uart0_reg[1]),
-			.is_transmitting(uart0_reg[2]),
+			.received(uart0_recv),
+			`ifdef SYNTHESIS
+			.is_receiving(uart0_reg[0]),
+			.is_transmitting(uart0_reg[1]),
+			`endif
 			.transmit(uart0_transmit)
 	);
 	
-	
+	initial uart0_reg[1:0] = 2'b00;
 	//reg [7:0] reset_str [7];
 	//reg [2:0] reset_seq;
 	//always_comb begin
@@ -72,34 +74,44 @@ module com_block(
 	always_ff@(posedge clk) begin
 		if(rst) begin 
 			//reset_seq <= 0;
+			uart0_reg[2] <= 0;
 			leds <= 'b0000_0000;
 		end
 		//else if(~uart0_reg[2] && reset_seq != 7) reset_seq <= reset_seq + 1;
-		else if(addr == 8'h06) leds <= in_data;
+		else begin 
+			case(addr)
+				8'h03: uart0_reg[2] <= in_data[2]; 
+				//8'h06: leds <= in_data;
+			endcase
+			leds <= {5'b0, uart0_reg};
+		end
 	end
 
 	always_comb begin
 		//tx_byte = 8'h23;
 		//uart0_transmit = 1;
-		uart0_transmit = (addr == 8'h05) || (received);
-		tx_byte = (received) ? rx_byte : in_data;
+		uart0_transmit = (addr == 8'h05) || (uart0_recv && uart0_reg[2]);
+		tx_byte = (uart0_recv && uart0_reg[2]) ? rx_byte : in_data;
 		//tx_byte = in_data;
 		case(addr)
-			8'h04: out_data = {6'b0, uart0_reg};
-			8'h05: out_data = {6'b0, uart0_reg};
-			8'h07: out_data = {4'b0, switches};
+			8'h03: out_data = in_data; 				// Set uart0 flags
+			8'h04: out_data = {5'b0, uart0_reg};  	// Read uart0 flags
+			8'h05: out_data = in_data;  			// Write to uart0
+			8'h07: out_data = leds;					// Read current LEDs
+			8'h08: out_data = {4'b0, switches};		// Read DIP
 			default: out_data = 0;
 		endcase
 	end
 endmodule
 
+
 module sdram_block(
-	input mclk, fclk, rst,
+	input mclk, fclk, rst_n,
 
 	// SDRAM Control
 	input [23:0]	ram_addr,
 	input [15:0] 	ram_wr_data,
-	output[15:0] 	ram_rd_data,
+	output reg [15:0] 	ram_rd_data,
 	input 			ram_wr_en,
 	input			ram_rd_en,
 	output			ram_busy,
@@ -122,79 +134,115 @@ module sdram_block(
 	/* SDRAM */
 
 	// 1 MHz side wires
-	wire [39:0] wr_fifo;// Address 24-bit and 16-bit Data
-	wire wr_enable;		// wr_enable ] <-> [ wr 	: wr_enable to push fifo
-	wire wr_full;		// wr_full   ] <-> [ full 	: signal that we are full
-	wire rd_enable;		// rd_enable - wr 			: rd_enable to push rd addr to fifo
-	wire rdaddr_full;	// rdaddr_full - full 		: signal we cannot read more
-	wire [15:0] rddo_fifo;
-	wire ctrl_rd_ready;	// wr - rd_ready 			: push data from dram to fifo
-
-	// 100MHz side wires
-	wire [39:0] wro_fifo;
-	wire ctrl_busy;       	// rd ] <-> [ busy 		: pop fifo when ctrl not busy
-	wire ctrl_wr_enable;  	// empty_n - wr_enable 	: signal ctrl data is ready
-	wire [23:0] rdao_fifo;
-	wire ctrl_rd_enable;	// empty_n - rd_enable 	: signal ctrl addr ready
-	wire [15:0] rddata_fifo;
-	wire rd_ready;   		// rd_ready - empty_n 	: signal interface data ready
-	wire rd_ack;     		// rd_ack - rd     		: pop fifo after data read
-
-	wire busy;				// RAM is busy because RW FIFO is full
-	assign busy = wr_full | rdaddr_full;
-
-
-	fifo #(.BUS_WIDTH(40)) dram_wr_fifo (
-	    .wr_clk        (mclk),
-	    .rd_clk        (fclk),
-	    .wr_data       (wr_fifo),
-	    .rd_data       (wro_fifo),
-	    .rd            (ctrl_busy),
-	    .wr            (wr_enable),
-	    .full          (wr_full),
-	    .empty_n       (ctrl_wr_enable),
-	    .rst_n         (rst)
-	);
-	
-	fifo #(.BUS_WIDTH(24)) dram_rd_addr_fifo (
-	    .wr_clk        (mclk),
-	    .rd_clk        (fclk),
-	    .wr_data       (wr_fifo[39:16]),
-	    .rd_data       (rdao_fifo),
-	    .rd            (ctrl_busy),
-	    .wr            (rd_enable),
-	    .full          (rdaddr_full),
-	    .empty_n       (ctrl_rd_enable),
-	    .rst_n         (rst)
-	);
+	//wire [39:0] wr_fifo;// Address 24-bit and 16-bit Data
+	//wire wr_enable;		// wr_enable ] <-> [ wr 	: wr_enable to push fifo
+	//wire wr_full;		// wr_full   ] <-> [ full 	: signal that we are full
+	//wire rd_enable;		// rd_enable - wr 			: rd_enable to push rd addr to fifo
+	//wire rdaddr_full;	// rdaddr_full - full 		: signal we cannot read more
+	//wire [15:0] rddo_fifo;
+	//wire ctrl_rd_ready;	// wr - rd_ready 			: push data from dram to fifo
+
+	//// 100MHz side wires
+	//wire [39:0] wro_fifo;
+	//wire ctrl_busy;       	// rd ] <-> [ busy 		: pop fifo when ctrl not busy
+	//wire ctrl_wr_enable;  	// empty_n - wr_enable 	: signal ctrl data is ready
+	//wire [23:0] rdao_fifo;
+	//wire ctrl_rd_enable;	// empty_n - rd_enable 	: signal ctrl addr ready
+	//wire [15:0] rddata_fifo;
+	//wire rd_ready;   		// rd_ready - empty_n 	: signal interface data ready
+	//wire rd_ack;     		// rd_ack - rd     		: pop fifo after data read
+
+	//wire busy;				// RAM is busy because RW FIFO is full
+	//assign busy = wr_full | rdaddr_full;
+
+
+	//fifo #(.BUS_WIDTH(40)) dram_wr_fifo (
+	//    .wr_clk        (mclk),
+	//    .rd_clk        (fclk),
+	//    .wr_data       (wr_fifo),
+	//    .rd_data       (wro_fifo),
+	//    .rd            (ctrl_busy),
+	//    .wr            (wr_enable),
+	//    .full          (wr_full),
+	//    .empty_n       (ctrl_wr_enable),
+	//    .rst_n         (rst_n)
+	//);
+	//
+	//fifo #(.BUS_WIDTH(24)) dram_rd_addr_fifo (
+	//    .wr_clk        (mclk),
+	//    .rd_clk        (fclk),
+	//    .wr_data       (wr_fifo[39:16]),
+	//    .rd_data       (rdao_fifo),
+	//    .rd            (ctrl_busy),
+	//    .wr            (rd_enable),
+	//    .full          (rdaddr_full),
+	//    .empty_n       (ctrl_rd_enable),
+	//    .rst_n         (rst_n)
+	//);
+	//
+	//fifo #(.BUS_WIDTH(16)) dram_rd_data_fifo (
+	//    .wr_clk        (fclk),
+	//    .rd_clk        (mclk),
+	//    .wr_data       (rddo_fifo),
+	//    .rd_data       (rddata_fifo),
+	//    .rd            (rd_ack),
+	//    .wr            (ctrl_rd_ready),
+	//    .empty_n       (rd_ready),
+	//    .rst_n         (rst_n)
+	//);
 	
-	fifo #(.BUS_WIDTH(16)) dram_rd_data_fifo (
-	    .wr_clk        (fclk),
-	    .rd_clk        (mclk),
-	    .wr_data       (rddo_fifo),
-	    .rd_data       (rddata_fifo),
-	    .rd            (rd_ack),
-	    .wr            (ctrl_rd_ready),
-	    .empty_n       (rd_ready),
-	    .rst_n         (rst)
-	);
+	reg busy, rd_ready, rd_en, wr_en;
+	reg [1:0] state;
+	reg [15:0] wr_data, rd_data, rd_data_reg;
+	always_ff@(posedge fclk) begin
+		if(~rst_n) begin
+			state <= 0;
+			wr_en <= 0;
+			rd_en <= 0;
+		end
+		else begin
+			if(rd_ready) ram_rd_data <= rd_data;
+			if(mclk & (state == 0)) state <= 1; 
+			//if(rd_ready) rd_data_reg <= rd_data;
+			else if(state == 1 && ~busy) begin
+				wr_data <= ram_wr_data;
+				wr_en <= ram_wr_en;
+				rd_en <= ram_rd_en;
+				state <= (ram_wr_en | ram_rd_en) ? 2 : 1;
+			end else if (state == 2) begin
+				wr_en <= 0;
+				rd_en <= 0;
+				state <= 3;
+			end
+			if(~mclk & (state == 3))  state <= 0;
+		end
+
+	end
 	
+	//always_ff@(posedge mclk) begin
+		//state <= 0;
+		//ram_rd_data <= rd_data_reg;
+	//end
+
+	//assign ram_rd_data = rd_data_reg;
+
 	// Setting SDRAM clock to 100MHz
 	assign DRAM_CLK = fclk;
-
+	
+	`ifdef SYNTHESIS
 	sdram_controller sdram_control0 (
 	    // HOST INTERFACE
-	    .wr_addr       (wro_fifo[39:16]),
-	    .wr_data       (wro_fifo[15:0]),
-	    .wr_enable     (ctrl_wr_enable), 
+	    .wr_addr       (ram_addr),
+	    .wr_data       (wr_data),
+	    .wr_enable     (wr_en), 
 	
-	    .rd_addr       (rdao_fifo), 
-	    .rd_data       (rddo_fifo),
-	    .rd_ready      (ctrl_rd_ready),
-	    .rd_enable     (ctrl_rd_enable),
+	    .rd_addr       (ram_addr), 
+	    .rd_data       (rd_data),
+	    .rd_ready      (rd_ready),
+	    .rd_enable     (rd_en),
 	    
-	    .busy          (ctrl_busy),
-	    .rst_n         (rst),
+	    .busy          (busy),
+	    .rst_n         (rst_n),
 	    .clk           (fclk),
 	
 	    // SDRAM SIDE
@@ -209,17 +257,115 @@ module sdram_block(
 		.data_mask_low (DRAM_DQM[0]),
 		.data_mask_high(DRAM_DQM[1])
 	);
-
-	// Assign inputs	
-	assign wr_fifo[39:16] 	= ram_addr;
-    assign wr_fifo[15:0] 	= ram_wr_data;
-	assign wr_enable 		= ram_wr_en;
-	assign rd_enable 		= ram_rd_en;
-	
-	// Assign outputs
-	assign ram_rd_data 		= rddata_fifo;
- 	assign ram_busy 		= busy;
-	assign ram_rd_ready 	= rd_ready;
-	assign ram_rd_ack 		= rd_ack;
+	`else
+	reg [15:0] rd_data0;
+	memory#(.WIDTH(16), .LENGTH(2**8)) mock_sdram0(
+		.clk(fclk),
+		.wr_en(wr_en),
+		.rd_en(rd_en),
+		.wd(wr_data),
+		.rd(rd_data0),
+		.addr(ram_addr[7:0])
+	);
+	always_ff@(posedge fclk) begin
+		if(~rst_n) busy <= 0;
+		else begin
+			rd_data <= rd_data0;
+			rd_ready <= rd_en;
+			busy <= rd_en | wr_en;
+		end
+	end
+	`endif
+	//// Assign inputs	
+	//assign wr_fifo[39:16] 	= ram_addr;
+    //assign wr_fifo[15:0] 	= ram_wr_data;
+	//assign wr_enable 		= ram_wr_en;
+	//assign rd_enable 		= ram_rd_en;
+	//
+	//// Assign outputs
+	//assign ram_rd_data 		= rddata_fifo;
+ 	//assign ram_busy 		= busy;
+	//assign ram_rd_ready 	= rd_ready;
+	//assign ram_rd_ack 		= rd_ack;
  		
 endmodule
+
+/**
+ * Testbench for sdram_controller modules, simulates:
+ *  - Iinit
+ *  - Write
+ *  - Read
+ */
+module sdram_controller_tb();
+
+    //vlog_tb_utils vlog_tb_utils0();
+
+    /* HOST CONTROLLS */
+    reg [23:0]  haddr;
+    reg [15:0]  data_input;
+    wire [15:0] data_output;
+    wire busy; 
+    reg rd_enable, wr_enable, rst_n, clk;
+
+    /* SDRAM SIDE */
+    wire [12:0] addr;
+    wire [1:0] bank_addr;
+    wire [15:0] data; 
+    wire clock_enable, cs_n, ras_n, cas_n, we_n, data_mask_low, data_mask_high;
+
+    reg [15:0] data_r;
+
+    assign data = data_r;
+
+
+    initial 
+    begin
+        haddr = 24'd0;
+        data_input = 16'd0;
+        rd_enable = 1'b0;
+        wr_enable = 1'b0;
+        rst_n = 1'b1;
+        clk = 1'b0;
+        data_r = 16'hzzzz;
+    end
+
+    always
+        #1 clk <= ~clk;
+      
+    initial
+    begin
+      #3 rst_n = 1'b0;
+      #3 rst_n = 1'b1;
+      
+      #120 haddr = 24'hfedbed;
+      data_input = 16'd3333;
+      
+      #3 wr_enable = 1'b1;
+      #6 wr_enable = 1'b0;
+      haddr = 24'd0;
+      data_input = 16'd0;  
+      
+      #120 haddr = 24'hbedfed;
+      #3 rd_enable = 1'b1;
+      #6 rd_enable = 1'b0;
+      haddr = 24'd0;
+      
+      #8 data_r = 16'hbbbb;
+      #2 data_r = 16'hzzzz;
+      
+      #1000 $finish;
+    end
+
+
+sdram_controller sdram_controlleri (
+    /* HOST INTERFACE */
+    .wr_addr(haddr), 
+    .wr_data(data_input),
+    .rd_data(data_output),
+    .busy(busy), .rd_enable(rd_enable), .wr_enable(wr_enable), .rst_n(rst_n), .clk(clk),
+
+    /* SDRAM SIDE */
+    .addr(addr), .bank_addr(bank_addr), .data(data), .clock_enable(clock_enable), .cs_n(cs_n), .ras_n(ras_n), .cas_n(cas_n), .we_n(we_n), .data_mask_low(data_mask_low), .data_mask_high(data_mask_high)
+);
+
+endmodule

+ 56 - 49
src/risc/controller.csv

@@ -1,49 +1,56 @@
-   instr, cdi.alu_op, cdi.selb, cdi.rw_en, cdi.selr, mem_rd, mem_wr, cdi.isize,cdi.selo ,cdi.stackop,cdi.pcop 
-    CPY0,   ALU_NONE,   SB_IMM,         1,   SR_IMM,      0,      0,         1,SO_MEML , ST_SKIP, PC_NONE 
-    CPY1,   ALU_NONE,   SB_IMM,         1,   SR_IMM,      0,      0,         1,SO_MEML , ST_SKIP, PC_NONE 
-    CPY2,   ALU_NONE,   SB_IMM,         1,   SR_IMM,      0,      0,         1,SO_MEML , ST_SKIP, PC_NONE 
-    CPY3,   ALU_NONE,   SB_IMM,         1,   SR_IMM,      0,      0,         1,SO_MEML , ST_SKIP, PC_NONE 
-    MOVE,   ALU_NONE,  SB_NONE,         1,   SR_REG,      0,      0,         0,SO_MEML , ST_SKIP, PC_NONE 
-     ADD,    ALU_ADD,   SB_REG,         1,  SR_ALUL,      0,      0,         0,SO_MEML , ST_SKIP, PC_NONE 
-     SUB,    ALU_SUB,   SB_REG,         1,  SR_ALUL,      0,      0,         0,SO_MEML , ST_SKIP, PC_NONE 
-     AND,    ALU_AND,   SB_REG,         1,  SR_ALUL,      0,      0,         0,SO_MEML , ST_SKIP, PC_NONE 
-      OR,     ALU_OR,   SB_REG,         1,  SR_ALUL,      0,      0,         0,SO_MEML , ST_SKIP, PC_NONE 
-     XOR,    ALU_XOR,   SB_REG,         1,  SR_ALUL,      0,      0,         0,SO_MEML , ST_SKIP, PC_NONE 
-     MUL,    ALU_MUL,   SB_REG,         1,  SR_ALUL,      0,      0,         0,SO_MEML , ST_SKIP, PC_NONE 
-     DIV,    ALU_DIV,   SB_REG,         1,  SR_ALUL,      0,      0,         0,SO_MEML , ST_SKIP, PC_NONE 
-      BR,   ALU_NONE,  SB_NONE,         0,  SR_NONE,      0,      0,         2,SO_MEML , ST_SKIP, PC_NONE 
-     SLL,     ALU_SL,   SB_REG,         1,  SR_ALUL,      0,      0,         0,SO_MEML , ST_SKIP, PC_NONE 
-     SRL,     ALU_SR,   SB_REG,         1,  SR_ALUL,      0,      0,         0,SO_MEML , ST_SKIP, PC_NONE 
-     SRA,     ALU_RA,   SB_REG,         1,  SR_ALUL,      0,      0,         0,SO_MEML , ST_SKIP, PC_NONE 
-    SRAS,    ALU_RAS,   SB_REG,         1,  SR_ALUL,      0,      0,         0,SO_MEML , ST_SKIP, PC_NONE 
-    LWHI,   ALU_NONE,  SB_NONE,         1,  SR_MEMH,      1,      0,         3,SO_MEML , ST_SKIP, PC_NONE 
-    SWHI,   ALU_NONE,  SB_NONE,         0,  SR_NONE,      0,      0,         0,SO_MEMH , ST_SKIP, PC_NONE 
-    LWLO,   ALU_NONE,  SB_NONE,         1,  SR_MEML,      1,      0,         3,SO_MEML , ST_SKIP, PC_NONE 
-    SWLO,   ALU_NONE,  SB_NONE,         0,  SR_NONE,      0,      1,         3,SO_MEML , ST_SKIP, PC_NONE 
-     INC,    ALU_ADD,     SB_1,         1,  SR_ALUL,      0,      0,         0,SO_MEML , ST_SKIP, PC_NONE 
-     DEC,    ALU_SUB,     SB_1,         1,  SR_ALUL,      0,      0,         0,SO_MEML , ST_SKIP, PC_NONE 
-   GETAH,   ALU_NONE,  SB_NONE,         1,  SR_ALUH,      0,      0,         0,SO_MEML , ST_SKIP, PC_NONE 
-   GETIF,   ALU_NONE,  SB_NONE,         1,  SR_INTR,      0,      0,         0,SO_MEML , ST_SKIP, PC_NONE 
-    PUSH,   ALU_NONE,  SB_NONE,         0,  SR_NONE,      0,      1,         0,SO_MEML ,  ST_SUB, PC_NONE 
-     POP,   ALU_NONE,  SB_NONE,         1,  SR_MEML,      1,      0,         0,SO_MEML ,  ST_ADD, PC_NONE 
-     COM,   ALU_NONE,  SB_NONE,         1,   SR_COM,      0,      0,         1, SO_COM , ST_SKIP, PC_NONE 
-    SETI,   ALU_NONE,  SB_NONE,         0,  SR_NONE,      0,      0,         0,SO_MEML , ST_SKIP, PC_NONE 
-     BEQ,   ALU_NONE,   SB_IMM,         0,  SR_NONE,      0,      0,(cdi.alu_comp[2:1] == 'b10)?1:3,SO_MEML , ST_SKIP,(cdi.alu_comp[2:1] == 'b10)?PC_IMM2:PC_NONE
-     BGT,   ALU_NONE,   SB_IMM,         0,  SR_NONE,      0,      0,(cdi.alu_comp[2:1] == 'b01)?1:3,SO_MEML , ST_SKIP,(cdi.alu_comp[2:1] == 'b01)?PC_IMM2:PC_NONE
-     BGE,   ALU_NONE,   SB_IMM,         0,  SR_NONE,      0,      0,(cdi.alu_comp[2]|cdi.alu_comp[1])?1:3,SO_MEML , ST_SKIP,(cdi.alu_comp[2]|cdi.alu_comp[1])?PC_IMM2:PC_NONE
-      BZ,   ALU_NONE,  SB_NONE,         0,  SR_NONE,      0,      0,         0,SO_MEML , ST_SKIP, PC_NONE 
-    CALL,   ALU_NONE,  SB_NONE,         0,  SR_NONE,      0,      1,         2,SO_MEML ,  ST_SUB,  PC_IMM 
-     RET,   ALU_NONE,  SB_NONE,         0,  SR_NONE,      1,      0,         2,SO_MEML ,  ST_ADD,  PC_MEM 
-    JUMP,   ALU_NONE,  SB_NONE,         0,  SR_NONE,      0,      0,         2,SO_MEML , ST_NONE,  PC_IMM
-    RETI,   ALU_NONE,  SB_NONE,         0,  SR_NONE,      1,      0,         2,SO_MEML ,  ST_SUB,  PC_MEM 
-     CLC,   ALU_NONE,  SB_NONE,         0,  SR_NONE,      0,      0,         0,SO_MEML , ST_SKIP, PC_NONE 
-    SETC,   ALU_NONE,  SB_NONE,         0,  SR_NONE,      0,      0,         0,SO_MEML , ST_SKIP, PC_NONE 
-     CLS,   ALU_NONE,  SB_NONE,         0,  SR_NONE,      0,      0,         0,SO_MEML , ST_SKIP, PC_NONE 
-    SETS,   ALU_NONE,  SB_NONE,         0,  SR_NONE,      0,      0,         0,SO_MEML , ST_SKIP, PC_NONE 
-   SSETS,   ALU_NONE,  SB_NONE,         0,  SR_NONE,      0,      0,         0,SO_MEML , ST_SKIP, PC_NONE 
-     CLN,   ALU_NONE,  SB_NONE,         0,  SR_NONE,      0,      0,         0,SO_MEML , ST_SKIP, PC_NONE 
-    SETN,   ALU_NONE,  SB_NONE,         0,  SR_NONE,      0,      0,         0,SO_MEML , ST_SKIP, PC_NONE 
-   SSETN,   ALU_NONE,  SB_NONE,         0,  SR_NONE,      0,      0,         0,SO_MEML , ST_SKIP, PC_NONE 
-   RJUMP,   ALU_NONE,  SB_NONE,         0,  SR_NONE,      0,      0,         2,SO_MEML , ST_SKIP, PC_NONE 
-    RBWI,   ALU_NONE,  SB_NONE,         0,  SR_NONE,      0,      0,         1,SO_MEML , ST_SKIP, PC_NONE 
- default,   ALU_NONE,  SB_NONE,         0,  SR_NONE,      0,      0,         0,SO_MEML , ST_SKIP, PC_NONE 
+   instr, cdi.alu_op, cdi.selb, cdi.rw_en, cdi.selr, mem_rd, mem_wr, cdi.isize,cdi.selo ,cdi.stackop,cdi.pcop ,cdi.imoctl,cdi.aluf 
+    CPY0,   ALU_NONE,   SB_IMM,         1,   SR_IMM,      0,      0,         1,SO_MEML , ST_SKIP, PC_NONE ,IMO_NONE,2'b00 
+    CPY1,   ALU_NONE,   SB_IMM,         1,   SR_IMM,      0,      0,         1,SO_MEML , ST_SKIP, PC_NONE ,IMO_NONE,2'b00  
+    CPY2,   ALU_NONE,   SB_IMM,         1,   SR_IMM,      0,      0,         1,SO_MEML , ST_SKIP, PC_NONE ,IMO_NONE,2'b00  
+    CPY3,   ALU_NONE,   SB_IMM,         1,   SR_IMM,      0,      0,         1,SO_MEML , ST_SKIP, PC_NONE ,IMO_NONE,2'b00  
+    MOVE,   ALU_NONE,  SB_NONE,         1,   SR_REG,      0,      0,         0,SO_MEML , ST_SKIP, PC_NONE ,IMO_NONE,2'b00  
+     ADD,    ALU_ADD,   SB_REG,         1,  SR_ALUL,      0,      0,         0,SO_MEML , ST_SKIP, PC_NONE ,IMO_NONE,2'b00  
+     SUB,    ALU_SUB,   SB_REG,         1,  SR_ALUL,      0,      0,         0,SO_MEML , ST_SKIP, PC_NONE ,IMO_NONE,2'b00  
+     AND,    ALU_AND,   SB_REG,         1,  SR_ALUL,      0,      0,         0,SO_MEML , ST_SKIP, PC_NONE ,IMO_NONE,2'b00  
+      OR,     ALU_OR,   SB_REG,         1,  SR_ALUL,      0,      0,         0,SO_MEML , ST_SKIP, PC_NONE ,IMO_NONE,2'b00  
+     XOR,    ALU_XOR,   SB_REG,         1,  SR_ALUL,      0,      0,         0,SO_MEML , ST_SKIP, PC_NONE ,IMO_NONE,2'b00  
+    ADDI,    ALU_ADD,   SB_IMM,         1,  SR_ALUL,      0,      0,         1,SO_MEML , ST_SKIP, PC_NONE ,IMO_NONE,2'b00  
+    SUBI,    ALU_SUB,   SB_IMM,         1,  SR_ALUL,      0,      0,         1,SO_MEML , ST_SKIP, PC_NONE ,IMO_NONE,2'b00  
+    ANDI,    ALU_AND,   SB_IMM,         1,  SR_ALUL,      0,      0,         1,SO_MEML , ST_SKIP, PC_NONE ,IMO_NONE,2'b00  
+     ORI,     ALU_OR,   SB_IMM,         1,  SR_ALUL,      0,      0,         1,SO_MEML , ST_SKIP, PC_NONE ,IMO_NONE,2'b00  
+    XORI,    ALU_XOR,   SB_IMM,         1,  SR_ALUL,      0,      0,         1,SO_MEML , ST_SKIP, PC_NONE ,IMO_NONE,2'b00  
+     MUL,    ALU_MUL,   SB_REG,         1,  SR_ALUL,      0,      0,         0,SO_MEML , ST_SKIP, PC_NONE ,IMO_NONE,2'b00  
+     DIV,    ALU_DIV,   SB_REG,         1,  SR_ALUL,      0,      0,         0,SO_MEML , ST_SKIP, PC_NONE ,IMO_NONE,2'b00  
+     CI0,   ALU_NONE,  SB_NONE,         0,  SR_NONE,      0,      0,         0,SO_MEML , ST_SKIP, PC_NONE ,IMO_0,2'b00  
+     CI1,   ALU_NONE,  SB_NONE,         0,  SR_NONE,      0,      0,         0,SO_MEML , ST_SKIP, PC_NONE ,IMO_1,2'b00  
+     CI2,   ALU_NONE,  SB_NONE,         0,  SR_NONE,      0,      0,         0,SO_MEML , ST_SKIP, PC_NONE ,IMO_2,2'b00  
+    ADDC,    ALU_ADD,     SB_0,         1,  SR_ALUL,      0,      0,         0,SO_MEML , ST_SKIP, PC_NONE ,IMO_NONE,2'b01 
+    SUBC,    ALU_SUB,     SB_0,         1,  SR_ALUL,      0,      0,         0,SO_MEML , ST_SKIP, PC_NONE ,IMO_NONE,2'b01 
+     SLL,     ALU_SL,   SB_REG,         1,  SR_ALUL,      0,      0,         0,SO_MEML , ST_SKIP, PC_NONE ,IMO_NONE,2'b00  
+     SRL,     ALU_SR,   SB_REG,         1,  SR_ALUL,      0,      0,         0,SO_MEML , ST_SKIP, PC_NONE ,IMO_NONE,2'b00  
+     SRA,     ALU_RA,   SB_REG,         1,  SR_ALUL,      0,      0,         0,SO_MEML , ST_SKIP, PC_NONE ,IMO_NONE,2'b00  
+    LWHI,   ALU_NONE,  SB_NONE,         1,  SR_MEMH,      1,      0,         3,SO_MEML , ST_SKIP, PC_NONE ,IMO_NONE,2'b00  
+    SWHI,   ALU_NONE,  SB_NONE,         0,  SR_NONE,      0,      0,         0,SO_MEMH , ST_SKIP, PC_NONE ,IMO_NONE,2'b00  
+    LWLO,   ALU_NONE,  SB_NONE,         1,  SR_MEML,      1,      0,         3,SO_MEML , ST_SKIP, PC_NONE ,IMO_NONE,2'b00  
+    SWLO,   ALU_NONE,  SB_NONE,         0,  SR_NONE,      0,      1,         3,SO_MEML , ST_SKIP, PC_NONE ,IMO_NONE,2'b00  
+     INC,    ALU_ADD,     SB_1,         1,  SR_ALUL,      0,      0,         0,SO_MEML , ST_SKIP, PC_NONE ,IMO_NONE,2'b00  
+     DEC,    ALU_SUB,     SB_1,         1,  SR_ALUL,      0,      0,         0,SO_MEML , ST_SKIP, PC_NONE ,IMO_NONE,2'b00  
+   GETAH,   ALU_NONE,  SB_NONE,         1,  SR_ALUH,      0,      0,         0,SO_MEML , ST_SKIP, PC_NONE ,IMO_NONE,2'b00  
+   GETIF,   ALU_NONE,  SB_NONE,         1,  SR_INTR,      0,      0,         0,SO_MEML , ST_SKIP, PC_NONE ,IMO_NONE,2'b00  
+    PUSH,   ALU_NONE,  SB_NONE,         0,  SR_NONE,      0,      1,         0,SO_MEML ,  ST_SUB, PC_NONE ,IMO_NONE,2'b00  
+     POP,   ALU_NONE,  SB_NONE,         1,  SR_MEML,      1,      0,         0,SO_MEML ,  ST_ADD, PC_NONE ,IMO_NONE,2'b00  
+     COM,   ALU_NONE,  SB_NONE,         1,   SR_COM,      0,      0,         1, SO_COM , ST_SKIP, PC_NONE ,IMO_NONE,2'b00  
+     BEQ,   ALU_NONE,   SB_IMM,         0,  SR_NONE,      0,      0,(cdi.alu_comp[2:1] == 'b10)?1:3,SO_MEML , ST_SKIP,(cdi.alu_comp[2:1] == 'b10)?PC_IMM2:PC_NONE,IMO_NONE,2'b00  
+     BGT,   ALU_NONE,   SB_IMM,         0,  SR_NONE,      0,      0,(cdi.alu_comp[2:1] == 'b01)?1:3,SO_MEML , ST_SKIP,(cdi.alu_comp[2:1] == 'b01)?PC_IMM2:PC_NONE,IMO_NONE,2'b00  
+     BGE,   ALU_NONE,   SB_IMM,         0,  SR_NONE,      0,      0,(cdi.alu_comp[2]|cdi.alu_comp[1])?1:3,SO_MEML , ST_SKIP,(cdi.alu_comp[2]|cdi.alu_comp[1])?PC_IMM2:PC_NONE,IMO_NONE,2'b00  
+      BZ,     ALU_OR,     SB_0,         0,  SR_NONE,      0,      0,(cdi.alu_comp[0])?1:2,SO_MEML , ST_SKIP,(cdi.alu_comp[0])?PC_IMM:PC_NONE,IMO_NONE,2'b00  
+    CALL,   ALU_NONE,  SB_NONE,         0,  SR_NONE,      0,      1,         0,SO_MEML ,  ST_SUB,  PC_IMM ,IMO_NONE,2'b00  
+     RET,   ALU_NONE,  SB_NONE,         0,  SR_NONE,      1,      0,         2,SO_MEML ,  ST_ADD,  PC_MEM ,IMO_NONE,2'b00  
+    JUMP,   ALU_NONE,  SB_NONE,         0,  SR_NONE,      0,      0,         2,SO_MEML , ST_NONE,  PC_IMM,IMO_NONE,2'b00  
+    RETI,   ALU_NONE,  SB_NONE,         0,  SR_NONE,      1,      0,         2,SO_MEML ,  ST_SUB,  PC_MEM ,IMO_NONE,2'b00  
+     CLC,   ALU_NONE,  SB_NONE,         0,  SR_NONE,      0,      0,         0,SO_MEML , ST_SKIP, PC_NONE ,IMO_NONE,2'b00  
+    SETC,   ALU_NONE,  SB_NONE,         0,  SR_NONE,      0,      0,         0,SO_MEML , ST_SKIP, PC_NONE ,IMO_NONE,2'b00  
+     CLS,   ALU_NONE,  SB_NONE,         0,  SR_NONE,      0,      0,         0,SO_MEML , ST_SKIP, PC_NONE ,IMO_NONE,2'b00  
+    SETS,   ALU_NONE,  SB_NONE,         0,  SR_NONE,      0,      0,         0,SO_MEML , ST_SKIP, PC_NONE ,IMO_NONE,2'b00  
+   SSETS,   ALU_NONE,  SB_NONE,         0,  SR_NONE,      0,      0,         0,SO_MEML , ST_SKIP, PC_NONE ,IMO_NONE,2'b00  
+     CLN,   ALU_NONE,  SB_NONE,         0,  SR_NONE,      0,      0,         0,SO_MEML , ST_SKIP, PC_NONE ,IMO_NONE,2'b00  
+    SETN,   ALU_NONE,  SB_NONE,         0,  SR_NONE,      0,      0,         0,SO_MEML , ST_SKIP, PC_NONE ,IMO_NONE,2'b00  
+   SSETN,   ALU_NONE,  SB_NONE,         0,  SR_NONE,      0,      0,         0,SO_MEML , ST_SKIP, PC_NONE ,IMO_NONE,2'b00  
+   RJUMP,   ALU_NONE,  SB_NONE,         0,  SR_NONE,      0,      0,         2,SO_MEML , ST_SKIP, PC_NONE ,IMO_NONE,2'b00  
+    RBWI,   ALU_NONE,  SB_NONE,         0,  SR_NONE,      0,      0,         1,SO_MEML , ST_SKIP, PC_NONE ,IMO_NONE,2'b00  
+ default,   ALU_NONE,  SB_NONE,         0,  SR_NONE,      0,      0,         0,SO_MEML , ST_SKIP, PC_NONE ,IMO_NONE,2'b00  

+ 252 - 37
src/risc/controller.sv

@@ -35,6 +35,8 @@ module controller8(
             cdi.selo    = SO_MEML;
             cdi.stackop = ST_SKIP;
             cdi.pcop    = PC_NONE;
+            cdi.imoctl  = IMO_NONE;
+            cdi.aluf    = 2'b00;
             `ifdef ADDOP
             op = CPY0;
             `endif
@@ -50,6 +52,8 @@ module controller8(
             cdi.selo    = SO_MEML;
             cdi.stackop = ST_SKIP;
             cdi.pcop    = PC_NONE;
+            cdi.imoctl  = IMO_NONE;
+            cdi.aluf    = 2'b00;
             `ifdef ADDOP
             op = CPY1;
             `endif
@@ -65,6 +69,8 @@ module controller8(
             cdi.selo    = SO_MEML;
             cdi.stackop = ST_SKIP;
             cdi.pcop    = PC_NONE;
+            cdi.imoctl  = IMO_NONE;
+            cdi.aluf    = 2'b00;
             `ifdef ADDOP
             op = CPY2;
             `endif
@@ -80,6 +86,8 @@ module controller8(
             cdi.selo    = SO_MEML;
             cdi.stackop = ST_SKIP;
             cdi.pcop    = PC_NONE;
+            cdi.imoctl  = IMO_NONE;
+            cdi.aluf    = 2'b00;
             `ifdef ADDOP
             op = CPY3;
             `endif
@@ -95,6 +103,8 @@ module controller8(
             cdi.selo    = SO_MEML;
             cdi.stackop = ST_SKIP;
             cdi.pcop    = PC_NONE;
+            cdi.imoctl  = IMO_NONE;
+            cdi.aluf    = 2'b00;
             `ifdef ADDOP
             op = MOVE;
             `endif
@@ -110,6 +120,8 @@ module controller8(
             cdi.selo    = SO_MEML;
             cdi.stackop = ST_SKIP;
             cdi.pcop    = PC_NONE;
+            cdi.imoctl  = IMO_NONE;
+            cdi.aluf    = 2'b00;
             `ifdef ADDOP
             op = ADD;
             `endif
@@ -125,6 +137,8 @@ module controller8(
             cdi.selo    = SO_MEML;
             cdi.stackop = ST_SKIP;
             cdi.pcop    = PC_NONE;
+            cdi.imoctl  = IMO_NONE;
+            cdi.aluf    = 2'b00;
             `ifdef ADDOP
             op = SUB;
             `endif
@@ -140,6 +154,8 @@ module controller8(
             cdi.selo    = SO_MEML;
             cdi.stackop = ST_SKIP;
             cdi.pcop    = PC_NONE;
+            cdi.imoctl  = IMO_NONE;
+            cdi.aluf    = 2'b00;
             `ifdef ADDOP
             op = AND;
             `endif
@@ -155,6 +171,8 @@ module controller8(
             cdi.selo    = SO_MEML;
             cdi.stackop = ST_SKIP;
             cdi.pcop    = PC_NONE;
+            cdi.imoctl  = IMO_NONE;
+            cdi.aluf    = 2'b00;
             `ifdef ADDOP
             op = OR;
             `endif
@@ -170,10 +188,97 @@ module controller8(
             cdi.selo    = SO_MEML;
             cdi.stackop = ST_SKIP;
             cdi.pcop    = PC_NONE;
+            cdi.imoctl  = IMO_NONE;
+            cdi.aluf    = 2'b00;
             `ifdef ADDOP
             op = XOR;
             `endif
         end
+        ADDI   : begin
+            cdi.alu_op  = ALU_ADD;
+            cdi.selb    = SB_IMM;
+            cdi.rw_en   = 1;
+            cdi.selr    = SR_ALUL;
+            mem_rd      = 0;
+            mem_wr      = 0;
+            cdi.isize   = 1;
+            cdi.selo    = SO_MEML;
+            cdi.stackop = ST_SKIP;
+            cdi.pcop    = PC_NONE;
+            cdi.imoctl  = IMO_NONE;
+            cdi.aluf    = 2'b00;
+            `ifdef ADDOP
+            op = ADDI;
+            `endif
+        end
+        SUBI   : begin
+            cdi.alu_op  = ALU_SUB;
+            cdi.selb    = SB_IMM;
+            cdi.rw_en   = 1;
+            cdi.selr    = SR_ALUL;
+            mem_rd      = 0;
+            mem_wr      = 0;
+            cdi.isize   = 1;
+            cdi.selo    = SO_MEML;
+            cdi.stackop = ST_SKIP;
+            cdi.pcop    = PC_NONE;
+            cdi.imoctl  = IMO_NONE;
+            cdi.aluf    = 2'b00;
+            `ifdef ADDOP
+            op = SUBI;
+            `endif
+        end
+        ANDI   : begin
+            cdi.alu_op  = ALU_AND;
+            cdi.selb    = SB_IMM;
+            cdi.rw_en   = 1;
+            cdi.selr    = SR_ALUL;
+            mem_rd      = 0;
+            mem_wr      = 0;
+            cdi.isize   = 1;
+            cdi.selo    = SO_MEML;
+            cdi.stackop = ST_SKIP;
+            cdi.pcop    = PC_NONE;
+            cdi.imoctl  = IMO_NONE;
+            cdi.aluf    = 2'b00;
+            `ifdef ADDOP
+            op = ANDI;
+            `endif
+        end
+        ORI    : begin
+            cdi.alu_op  = ALU_OR;
+            cdi.selb    = SB_IMM;
+            cdi.rw_en   = 1;
+            cdi.selr    = SR_ALUL;
+            mem_rd      = 0;
+            mem_wr      = 0;
+            cdi.isize   = 1;
+            cdi.selo    = SO_MEML;
+            cdi.stackop = ST_SKIP;
+            cdi.pcop    = PC_NONE;
+            cdi.imoctl  = IMO_NONE;
+            cdi.aluf    = 2'b00;
+            `ifdef ADDOP
+            op = ORI;
+            `endif
+        end
+        XORI   : begin
+            cdi.alu_op  = ALU_XOR;
+            cdi.selb    = SB_IMM;
+            cdi.rw_en   = 1;
+            cdi.selr    = SR_ALUL;
+            mem_rd      = 0;
+            mem_wr      = 0;
+            cdi.isize   = 1;
+            cdi.selo    = SO_MEML;
+            cdi.stackop = ST_SKIP;
+            cdi.pcop    = PC_NONE;
+            cdi.imoctl  = IMO_NONE;
+            cdi.aluf    = 2'b00;
+            `ifdef ADDOP
+            op = XORI;
+            `endif
+        end
         MUL    : begin
             cdi.alu_op  = ALU_MUL;
             cdi.selb    = SB_REG;
@@ -185,6 +290,8 @@ module controller8(
             cdi.selo    = SO_MEML;
             cdi.stackop = ST_SKIP;
             cdi.pcop    = PC_NONE;
+            cdi.imoctl  = IMO_NONE;
+            cdi.aluf    = 2'b00;
             `ifdef ADDOP
             op = MUL;
             `endif
@@ -200,28 +307,66 @@ module controller8(
             cdi.selo    = SO_MEML;
             cdi.stackop = ST_SKIP;
             cdi.pcop    = PC_NONE;
+            cdi.imoctl  = IMO_NONE;
+            cdi.aluf    = 2'b00;
             `ifdef ADDOP
             op = DIV;
             `endif
         end
-        BR     : begin
+        CI0    : begin
             cdi.alu_op  = ALU_NONE;
             cdi.selb    = SB_NONE;
             cdi.rw_en   = 0;
             cdi.selr    = SR_NONE;
             mem_rd      = 0;
             mem_wr      = 0;
-            cdi.isize   = 2;
+            cdi.isize   = 0;
             cdi.selo    = SO_MEML;
             cdi.stackop = ST_SKIP;
             cdi.pcop    = PC_NONE;
+            cdi.imoctl  = IMO_0;
+            cdi.aluf    = 2'b00;
             `ifdef ADDOP
-            op = BR;
+            op = CI0;
             `endif
         end
-        SLL    : begin
-            cdi.alu_op  = ALU_SL;
-            cdi.selb    = SB_REG;
+        CI1    : begin
+            cdi.alu_op  = ALU_NONE;
+            cdi.selb    = SB_NONE;
+            cdi.rw_en   = 0;
+            cdi.selr    = SR_NONE;
+            mem_rd      = 0;
+            mem_wr      = 0;
+            cdi.isize   = 0;
+            cdi.selo    = SO_MEML;
+            cdi.stackop = ST_SKIP;
+            cdi.pcop    = PC_NONE;
+            cdi.imoctl  = IMO_1;
+            cdi.aluf    = 2'b00;
+            `ifdef ADDOP
+            op = CI1;
+            `endif
+        end
+        CI2    : begin
+            cdi.alu_op  = ALU_NONE;
+            cdi.selb    = SB_NONE;
+            cdi.rw_en   = 0;
+            cdi.selr    = SR_NONE;
+            mem_rd      = 0;
+            mem_wr      = 0;
+            cdi.isize   = 0;
+            cdi.selo    = SO_MEML;
+            cdi.stackop = ST_SKIP;
+            cdi.pcop    = PC_NONE;
+            cdi.imoctl  = IMO_2;
+            cdi.aluf    = 2'b00;
+            `ifdef ADDOP
+            op = CI2;
+            `endif
+        end
+        ADDC   : begin
+            cdi.alu_op  = ALU_ADD;
+            cdi.selb    = SB_0;
             cdi.rw_en   = 1;
             cdi.selr    = SR_ALUL;
             mem_rd      = 0;
@@ -230,12 +375,31 @@ module controller8(
             cdi.selo    = SO_MEML;
             cdi.stackop = ST_SKIP;
             cdi.pcop    = PC_NONE;
+            cdi.imoctl  = IMO_NONE;
+            cdi.aluf    = 2'b01;
             `ifdef ADDOP
-            op = SLL;
+            op = ADDC;
             `endif
         end
-        SRL    : begin
-            cdi.alu_op  = ALU_SR;
+        SUBC   : begin
+            cdi.alu_op  = ALU_SUB;
+            cdi.selb    = SB_0;
+            cdi.rw_en   = 1;
+            cdi.selr    = SR_ALUL;
+            mem_rd      = 0;
+            mem_wr      = 0;
+            cdi.isize   = 0;
+            cdi.selo    = SO_MEML;
+            cdi.stackop = ST_SKIP;
+            cdi.pcop    = PC_NONE;
+            cdi.imoctl  = IMO_NONE;
+            cdi.aluf    = 2'b01;
+            `ifdef ADDOP
+            op = SUBC;
+            `endif
+        end
+        SLL    : begin
+            cdi.alu_op  = ALU_SL;
             cdi.selb    = SB_REG;
             cdi.rw_en   = 1;
             cdi.selr    = SR_ALUL;
@@ -245,12 +409,14 @@ module controller8(
             cdi.selo    = SO_MEML;
             cdi.stackop = ST_SKIP;
             cdi.pcop    = PC_NONE;
+            cdi.imoctl  = IMO_NONE;
+            cdi.aluf    = 2'b00;
             `ifdef ADDOP
-            op = SRL;
+            op = SLL;
             `endif
         end
-        SRA    : begin
-            cdi.alu_op  = ALU_RA;
+        SRL    : begin
+            cdi.alu_op  = ALU_SR;
             cdi.selb    = SB_REG;
             cdi.rw_en   = 1;
             cdi.selr    = SR_ALUL;
@@ -260,12 +426,14 @@ module controller8(
             cdi.selo    = SO_MEML;
             cdi.stackop = ST_SKIP;
             cdi.pcop    = PC_NONE;
+            cdi.imoctl  = IMO_NONE;
+            cdi.aluf    = 2'b00;
             `ifdef ADDOP
-            op = SRA;
+            op = SRL;
             `endif
         end
-        SRAS   : begin
-            cdi.alu_op  = ALU_RAS;
+        SRA    : begin
+            cdi.alu_op  = ALU_RA;
             cdi.selb    = SB_REG;
             cdi.rw_en   = 1;
             cdi.selr    = SR_ALUL;
@@ -275,8 +443,10 @@ module controller8(
             cdi.selo    = SO_MEML;
             cdi.stackop = ST_SKIP;
             cdi.pcop    = PC_NONE;
+            cdi.imoctl  = IMO_NONE;
+            cdi.aluf    = 2'b00;
             `ifdef ADDOP
-            op = SRAS;
+            op = SRA;
             `endif
         end
         LWHI   : begin
@@ -290,6 +460,8 @@ module controller8(
             cdi.selo    = SO_MEML;
             cdi.stackop = ST_SKIP;
             cdi.pcop    = PC_NONE;
+            cdi.imoctl  = IMO_NONE;
+            cdi.aluf    = 2'b00;
             `ifdef ADDOP
             op = LWHI;
             `endif
@@ -305,6 +477,8 @@ module controller8(
             cdi.selo    = SO_MEMH;
             cdi.stackop = ST_SKIP;
             cdi.pcop    = PC_NONE;
+            cdi.imoctl  = IMO_NONE;
+            cdi.aluf    = 2'b00;
             `ifdef ADDOP
             op = SWHI;
             `endif
@@ -320,6 +494,8 @@ module controller8(
             cdi.selo    = SO_MEML;
             cdi.stackop = ST_SKIP;
             cdi.pcop    = PC_NONE;
+            cdi.imoctl  = IMO_NONE;
+            cdi.aluf    = 2'b00;
             `ifdef ADDOP
             op = LWLO;
             `endif
@@ -335,6 +511,8 @@ module controller8(
             cdi.selo    = SO_MEML;
             cdi.stackop = ST_SKIP;
             cdi.pcop    = PC_NONE;
+            cdi.imoctl  = IMO_NONE;
+            cdi.aluf    = 2'b00;
             `ifdef ADDOP
             op = SWLO;
             `endif
@@ -350,6 +528,8 @@ module controller8(
             cdi.selo    = SO_MEML;
             cdi.stackop = ST_SKIP;
             cdi.pcop    = PC_NONE;
+            cdi.imoctl  = IMO_NONE;
+            cdi.aluf    = 2'b00;
             `ifdef ADDOP
             op = INC;
             `endif
@@ -365,6 +545,8 @@ module controller8(
             cdi.selo    = SO_MEML;
             cdi.stackop = ST_SKIP;
             cdi.pcop    = PC_NONE;
+            cdi.imoctl  = IMO_NONE;
+            cdi.aluf    = 2'b00;
             `ifdef ADDOP
             op = DEC;
             `endif
@@ -380,6 +562,8 @@ module controller8(
             cdi.selo    = SO_MEML;
             cdi.stackop = ST_SKIP;
             cdi.pcop    = PC_NONE;
+            cdi.imoctl  = IMO_NONE;
+            cdi.aluf    = 2'b00;
             `ifdef ADDOP
             op = GETAH;
             `endif
@@ -395,6 +579,8 @@ module controller8(
             cdi.selo    = SO_MEML;
             cdi.stackop = ST_SKIP;
             cdi.pcop    = PC_NONE;
+            cdi.imoctl  = IMO_NONE;
+            cdi.aluf    = 2'b00;
             `ifdef ADDOP
             op = GETIF;
             `endif
@@ -410,6 +596,8 @@ module controller8(
             cdi.selo    = SO_MEML;
             cdi.stackop = ST_SUB;
             cdi.pcop    = PC_NONE;
+            cdi.imoctl  = IMO_NONE;
+            cdi.aluf    = 2'b00;
             `ifdef ADDOP
             op = PUSH;
             `endif
@@ -425,6 +613,8 @@ module controller8(
             cdi.selo    = SO_MEML;
             cdi.stackop = ST_ADD;
             cdi.pcop    = PC_NONE;
+            cdi.imoctl  = IMO_NONE;
+            cdi.aluf    = 2'b00;
             `ifdef ADDOP
             op = POP;
             `endif
@@ -440,25 +630,12 @@ module controller8(
             cdi.selo    = SO_COM;
             cdi.stackop = ST_SKIP;
             cdi.pcop    = PC_NONE;
+            cdi.imoctl  = IMO_NONE;
+            cdi.aluf    = 2'b00;
             `ifdef ADDOP
             op = COM;
             `endif
         end
-        SETI   : begin
-            cdi.alu_op  = ALU_NONE;
-            cdi.selb    = SB_NONE;
-            cdi.rw_en   = 0;
-            cdi.selr    = SR_NONE;
-            mem_rd      = 0;
-            mem_wr      = 0;
-            cdi.isize   = 0;
-            cdi.selo    = SO_MEML;
-            cdi.stackop = ST_SKIP;
-            cdi.pcop    = PC_NONE;
-            `ifdef ADDOP
-            op = SETI;
-            `endif
-        end
         BEQ    : begin
             cdi.alu_op  = ALU_NONE;
             cdi.selb    = SB_IMM;
@@ -470,6 +647,8 @@ module controller8(
             cdi.selo    = SO_MEML;
             cdi.stackop = ST_SKIP;
             cdi.pcop    = (cdi.alu_comp[2:1] == 'b10)?PC_IMM2:PC_NONE;
+            cdi.imoctl  = IMO_NONE;
+            cdi.aluf    = 2'b00;
             `ifdef ADDOP
             op = BEQ;
             `endif
@@ -485,6 +664,8 @@ module controller8(
             cdi.selo    = SO_MEML;
             cdi.stackop = ST_SKIP;
             cdi.pcop    = (cdi.alu_comp[2:1] == 'b01)?PC_IMM2:PC_NONE;
+            cdi.imoctl  = IMO_NONE;
+            cdi.aluf    = 2'b00;
             `ifdef ADDOP
             op = BGT;
             `endif
@@ -500,21 +681,25 @@ module controller8(
             cdi.selo    = SO_MEML;
             cdi.stackop = ST_SKIP;
             cdi.pcop    = (cdi.alu_comp[2]|cdi.alu_comp[1])?PC_IMM2:PC_NONE;
+            cdi.imoctl  = IMO_NONE;
+            cdi.aluf    = 2'b00;
             `ifdef ADDOP
             op = BGE;
             `endif
         end
         BZ     : begin
-            cdi.alu_op  = ALU_NONE;
-            cdi.selb    = SB_NONE;
+            cdi.alu_op  = ALU_OR;
+            cdi.selb    = SB_0;
             cdi.rw_en   = 0;
             cdi.selr    = SR_NONE;
             mem_rd      = 0;
             mem_wr      = 0;
-            cdi.isize   = 0;
+            cdi.isize   = (cdi.alu_comp[0])?1:2;
             cdi.selo    = SO_MEML;
             cdi.stackop = ST_SKIP;
-            cdi.pcop    = PC_NONE;
+            cdi.pcop    = (cdi.alu_comp[0])?PC_IMM:PC_NONE;
+            cdi.imoctl  = IMO_NONE;
+            cdi.aluf    = 2'b00;
             `ifdef ADDOP
             op = BZ;
             `endif
@@ -526,10 +711,12 @@ module controller8(
             cdi.selr    = SR_NONE;
             mem_rd      = 0;
             mem_wr      = 1;
-            cdi.isize   = 2;
+            cdi.isize   = 0;
             cdi.selo    = SO_MEML;
             cdi.stackop = ST_SUB;
             cdi.pcop    = PC_IMM;
+            cdi.imoctl  = IMO_NONE;
+            cdi.aluf    = 2'b00;
             `ifdef ADDOP
             op = CALL;
             `endif
@@ -545,6 +732,8 @@ module controller8(
             cdi.selo    = SO_MEML;
             cdi.stackop = ST_ADD;
             cdi.pcop    = PC_MEM;
+            cdi.imoctl  = IMO_NONE;
+            cdi.aluf    = 2'b00;
             `ifdef ADDOP
             op = RET;
             `endif
@@ -556,10 +745,12 @@ module controller8(
             cdi.selr    = SR_NONE;
             mem_rd      = 0;
             mem_wr      = 0;
-            cdi.isize   = 3;
+            cdi.isize   = 2;
             cdi.selo    = SO_MEML;
             cdi.stackop = ST_NONE;
             cdi.pcop    = PC_IMM;
+            cdi.imoctl  = IMO_NONE;
+            cdi.aluf    = 2'b00;
             `ifdef ADDOP
             op = JUMP;
             `endif
@@ -575,6 +766,8 @@ module controller8(
             cdi.selo    = SO_MEML;
             cdi.stackop = ST_SUB;
             cdi.pcop    = PC_MEM;
+            cdi.imoctl  = IMO_NONE;
+            cdi.aluf    = 2'b00;
             `ifdef ADDOP
             op = RETI;
             `endif
@@ -590,6 +783,8 @@ module controller8(
             cdi.selo    = SO_MEML;
             cdi.stackop = ST_SKIP;
             cdi.pcop    = PC_NONE;
+            cdi.imoctl  = IMO_NONE;
+            cdi.aluf    = 2'b00;
             `ifdef ADDOP
             op = CLC;
             `endif
@@ -605,6 +800,8 @@ module controller8(
             cdi.selo    = SO_MEML;
             cdi.stackop = ST_SKIP;
             cdi.pcop    = PC_NONE;
+            cdi.imoctl  = IMO_NONE;
+            cdi.aluf    = 2'b00;
             `ifdef ADDOP
             op = SETC;
             `endif
@@ -620,6 +817,8 @@ module controller8(
             cdi.selo    = SO_MEML;
             cdi.stackop = ST_SKIP;
             cdi.pcop    = PC_NONE;
+            cdi.imoctl  = IMO_NONE;
+            cdi.aluf    = 2'b00;
             `ifdef ADDOP
             op = CLS;
             `endif
@@ -635,6 +834,8 @@ module controller8(
             cdi.selo    = SO_MEML;
             cdi.stackop = ST_SKIP;
             cdi.pcop    = PC_NONE;
+            cdi.imoctl  = IMO_NONE;
+            cdi.aluf    = 2'b00;
             `ifdef ADDOP
             op = SETS;
             `endif
@@ -650,6 +851,8 @@ module controller8(
             cdi.selo    = SO_MEML;
             cdi.stackop = ST_SKIP;
             cdi.pcop    = PC_NONE;
+            cdi.imoctl  = IMO_NONE;
+            cdi.aluf    = 2'b00;
             `ifdef ADDOP
             op = SSETS;
             `endif
@@ -665,6 +868,8 @@ module controller8(
             cdi.selo    = SO_MEML;
             cdi.stackop = ST_SKIP;
             cdi.pcop    = PC_NONE;
+            cdi.imoctl  = IMO_NONE;
+            cdi.aluf    = 2'b00;
             `ifdef ADDOP
             op = CLN;
             `endif
@@ -680,6 +885,8 @@ module controller8(
             cdi.selo    = SO_MEML;
             cdi.stackop = ST_SKIP;
             cdi.pcop    = PC_NONE;
+            cdi.imoctl  = IMO_NONE;
+            cdi.aluf    = 2'b00;
             `ifdef ADDOP
             op = SETN;
             `endif
@@ -695,6 +902,8 @@ module controller8(
             cdi.selo    = SO_MEML;
             cdi.stackop = ST_SKIP;
             cdi.pcop    = PC_NONE;
+            cdi.imoctl  = IMO_NONE;
+            cdi.aluf    = 2'b00;
             `ifdef ADDOP
             op = SSETN;
             `endif
@@ -710,6 +919,8 @@ module controller8(
             cdi.selo    = SO_MEML;
             cdi.stackop = ST_SKIP;
             cdi.pcop    = PC_NONE;
+            cdi.imoctl  = IMO_NONE;
+            cdi.aluf    = 2'b00;
             `ifdef ADDOP
             op = RJUMP;
             `endif
@@ -725,6 +936,8 @@ module controller8(
             cdi.selo    = SO_MEML;
             cdi.stackop = ST_SKIP;
             cdi.pcop    = PC_NONE;
+            cdi.imoctl  = IMO_NONE;
+            cdi.aluf    = 2'b00;
             `ifdef ADDOP
             op = RBWI;
             `endif
@@ -740,6 +953,8 @@ module controller8(
             cdi.selo    = SO_MEML;
             cdi.stackop = ST_SKIP;
             cdi.pcop    = PC_NONE;
+            cdi.imoctl  = IMO_NONE;
+            cdi.aluf    = 2'b00;
         end
     endcase
     end

+ 2 - 2
src/risc/cpu.sv

@@ -19,7 +19,7 @@ module risc8_cpu(processor_port port);
 	reg [31:0] instr; // Fetching 4x8bit instruction
 	reg [15:0] pc; // Instruction memory is 16bit in length
 	
-	rom#("../../memory/risc8") rom_block0(pc[11:0],  port.clk, instr);	
+	rom#("../../memory/risc8.text") rom_block0(pc[11:0],  port.clk, instr);	
 
 	risc8_cdi cdi0();
 	controller8 ctrl0(
@@ -32,7 +32,7 @@ module risc8_cpu(processor_port port);
 			.clk(port.clk),
 			.rst(port.rst),
 			.cdi(cdi0),
-			.imm(instr[31:8]),
+			.immr(instr[31:8]),
 			.mem_rd(port.ram_rd_data),
 			.mem_wr(port.ram_wr_data),
 			.mem_addr(port.ram_addr),

+ 117 - 141
src/risc/datapath.sv

@@ -6,38 +6,67 @@ module datapath8(
 		input logic clk, rst, interrupt,
 		risc8_cdi.datapath cdi,
 		input  word com_rd,
-		input  wire [23:0] imm,
+		input  wire [23:0] immr,
 		output word com_wr, com_addr,
 		input  [15:0] mem_rd,
 		output [15:0] mem_wr,
 		output reg [15:0] pc,
 		output reg [23:0] mem_addr
-);
+);	
+	// regiser file outputs
+	word r1, r2;
 	
-	word r1, r2, reg_wr;
+	// immidate overrride
+	word imo0, imo1, imo2;
+	reg imo0_en, imo1_en, imo2_en, imo_en;
+	
+	reg [23:0] imm;
+	always_comb begin
+		imm[7:0] = (imo_en & imo2_en) ? imo2 : immr[7:0];
+		imm[15:8] = (imo_en & imo1_en) ? imo1 : immr[15:8];
+		imm[23:16] = (imo_en & imo0_en) ? imo0 : immr[23:16];
+	end
 
-	reg_file reg0(.clk(clk), .rst(rst), 
-			.rd_addr1(cdi.a1),
-			.rd_addr2(cdi.a2),
-			.rd_data1(r1),
-			.rd_data2(r2),
-			.wr_addr(cdi.a3),
-			.wr_data(reg_wr),
-			.wr_en(cdi.rw_en)
-	);
+	always_ff@(posedge clk) begin
+		if(imo_en | rst) begin
+			imo0_en <= 0;
+			imo1_en <= 0;
+			imo2_en <= 0;
+			imo_en <= 0;
+		end else case(cdi.imoctl)
+			IMO_0: begin
+				imo0 <= r1;
+				imo0_en <= 1;
+				imo_en <= 1;
+			end
+			IMO_1: begin
+				imo1 <= r1;
+				imo1_en <= 1;
+			end
+			IMO_2: begin
+				imo2 <= r1;
+				imo2_en <= 1;
+			end
+		endcase
+	end
+
+	// ======================== //
+	// 			ALU			 	//
+	// ======================== //
 
 	word srcA, srcB, alu_rlo, alu_rhi, alu_rhit;
-	logic cout, cin, alu_eq, alu_gt, alu_zero, alu_sign;
+	logic cout, cinr, cin, alu_eq, alu_gt, alu_zero, alu_sign;
 	assign cdi.alu_comp = {alu_eq, alu_gt, alu_zero};
 	assign alu_sign = 0;
+	assign cin = (cdi.aluf[0]) ? cinr : 0;  // Enable carry in
 	always_ff@(posedge clk) begin
 			if(rst) begin
-					cin <= '0;
+					cinr <= '0;
 					alu_rhi <= '0;
 			end else begin
 
 			if((cdi.alu_op == ALU_ADD)||(cdi.alu_op == ALU_SUB))
-					cin <= cout;
+					cinr <= cout;
 			if((cdi.alu_op == ALU_MUL)||(cdi.alu_op == ALU_DIV))
 					alu_rhi <= alu_rhit;
 			end
@@ -61,14 +90,23 @@ module datapath8(
 	// 		Program Counter 	//
 	// ======================== //
 
-	logic bconst; // Use immediate to branch
+	logic bconst, pc_halted, pchf; // Use immediate to branch
 	word pc_off; // Program counter offset
-	reg [15:0] pcn, pca, pcx; // Program Counter Previous, to add
+	reg [15:0] pcn, pca, pcx, pch, pcp, pcn0; // Program Counter Previous, to add
+	assign pchf = (cdi.pcop == PC_MEM) & ~pc_halted;
 	always_ff@(posedge clk) begin
-			if(rst) pcx <= 0; 
-			else pcx <= pcn;
+			if(rst) begin 
+				pcx <= 0;
+				pc_halted <= 0;
+			end else begin
+				pcx <= pcn;
+				pch <= pcn;
+				if (pchf) pc_halted <= 1;
+				else pc_halted <= 0;
+			end
 	end
-	assign pc = (rst) ? 0 : pcn;
+	assign pcp = (pchf) ? pch : pcn;
+	assign pc = (rst) ? 0 : pcp;
 	
 	always_comb begin
 		bconst = 0;  // FIXME: temporary
@@ -79,16 +117,21 @@ module datapath8(
 			(~cdi.isize[1]&~cdi.isize[0])|(cdi.isize[1]&~cdi.isize[0])
 		}; // Adding 1 to 2bit value.
 		case(cdi.pcop)
-			PC_NONE: pcn = pcx + pc_off;
-			PC_MEM : pcn = mem_rd;
-			PC_IMM : pcn = {imm[7:0], imm[15:8]};
-			PC_IMM2: pcn = {imm[15:8], imm[23:16]};
-			default: pcn = pcx;
+			PC_NONE: pcn0 = pcx;
+			PC_MEM : pcn0 = mem_rd;
+			PC_IMM : pcn0 = {imm[7:0], imm[15:8]};
+			PC_IMM2: pcn0 = {imm[15:8], imm[23:16]};
+			default: pcn0 = pcx;
 		endcase
+		pcn = (cdi.pcop == PC_IMM | cdi.pcop == PC_IMM2) ? pcn0 : pcn0 + pc_off;
 		//pca = (bconst) ? {imm[7:0], imm[15:8]} : pc;
 		//pcn = pca + pc_off;
 	end
 	
+	// ======================== //
+	// 		  Interrupt	 		//
+	// ======================== //
+
 	word interrupt_flag;
 	always_ff@(posedge clk) begin
 		if(rst) interrupt_flag <= 0;
@@ -104,11 +147,11 @@ module datapath8(
 	word st_reg, st_rd;  // Stack data low byte reg
 	logic [23:0] sp_addr;
 	always_comb begin
-		sp_add = (cdi.stackop == ST_ADD) ? 'h0002 : 'hfffe;
+		sp_add = (cdi.stackop == ST_ADD) ? 'h0001 : 'hffff;
 		sp_next = sp + sp_add;
-		sp_addr = {9'b1111_1111_1, (cdi.stackop == ST_ADD) ? sp_next[15:1] : sp[15:1]};
+		sp_addr = {9'b1111_1111_1, (cdi.stackop == ST_ADD) ? sp_next[15:0] : sp[15:0]};
 		st_rd = {mem_rd[7:0]};
-		st_wr = (cdi.pcop == PC_IMM) ? pc : {8'h00, r1};
+		st_wr = (cdi.pcop == PC_IMM) ? pcx : {8'h00, r1};
 		//if(sp[0]) begin
 			//st_wr = {'h00, r1};
 			//st_rd = {mem_rd[7:0]};
@@ -119,9 +162,9 @@ module datapath8(
 	end
 	
 	always_ff@(posedge clk) begin
-			if(rst)	sp <= 'hffff;
+			if(rst)	sp <= 'h0fff;  // Highest memory address
 			else begin
-				if(cdi.stackop != ST_SKIP) sp <= sp_next;
+				if(cdi.stackop != ST_SKIP & ~pc_halted) sp <= sp_next;
 				if(sp[0]) st_reg <= r1; 
 			end
 	end
@@ -155,10 +198,34 @@ module datapath8(
 			default: srcB = r2;
 		endcase
 
+	end
+
+	// ======================== //
+	// 		Register File 	 	//
+	// ======================== //
+	
+	word reg_wr, reg_wr1, reg_wr2, reg_wra;
+	reg reg_wr_en1; 
+	reg [1:0]reg_wr_mem;
+	
+	always_ff@(posedge clk) begin
+		if(rst) begin
+			reg_wr1 	<= 0;
+			reg_wr_en1 	<= 0;
+			reg_wr_mem 	<= 0;
+		end else begin
+			reg_wr1 	<= reg_wr;
+			reg_wr_en1 	<= cdi.rw_en;
+			reg_wra 	<= cdi.a3;
+			reg_wr_mem 	<= {cdi.selr == SR_MEML, cdi.selr == SR_MEMH};
+		end
+	end	
+
+	always_comb begin
 		case(cdi.selr)
 			SR_REG : reg_wr = r2;
-			SR_MEML: reg_wr = (cdi.stackop == ST_ADD) ? st_rd : mem_rd[7:0];
-			SR_MEMH: reg_wr = mem_rd[15:8];
+			//SR_MEML: reg_wr = (cdi.stackop == ST_ADD) ? st_rd : mem_rd[7:0];
+			//SR_MEMH: reg_wr = mem_rd[15:8];
 			SR_ALUL: reg_wr = alu_rlo;
 			SR_ALUH: reg_wr = alu_rhi;
 			SR_IMM : reg_wr = imm[7:0];
@@ -167,115 +234,24 @@ module datapath8(
 			default: reg_wr = alu_rlo;
 		endcase
 	end
+	
+	always_comb begin
+		case(reg_wr_mem)
+			2'b10: 		reg_wr2 = mem_rd[7:0];
+			2'b01: 		reg_wr2 = mem_rd[15:8];
+			default: 	reg_wr2 = reg_wr1;
+		endcase
+	end
+
+	reg_file reg0(.clk(clk), .rst(rst), 
+			.rd_addr1(cdi.a1),
+			.rd_addr2(cdi.a2),
+			.rd_data1(r1),
+			.rd_data2(r2),
+			.wr_addr(reg_wra),
+			.wr_data(reg_wr2),
+			.wr_en(reg_wr_en1)
+	);
 
 endmodule
 
-//module datapath(clk, rst, rd, rs, imm, alu_op, alu_ex, reg_wr, pc_src, 
-//		rimm, alu_src, mem_to_reg, pc, alu_out, mem_data, alu_zero, 
-//		mem_wr_data, sp_wr, mem_sp);
-//
-//
-//	input logic clk, rst, reg_wr, pc_src, rimm, mem_to_reg, alu_src;
-//	input e_reg rd, rs;
-//	input e_alu_op alu_op;
-//	input e_alu_ext_op alu_ex;
-//	input word imm, mem_data;
-//	input logic sp_wr, mem_sp;
-//	output word pc, alu_out, mem_wr_data;
-//	output logic alu_zero;
-//	
-//	word sp, sp_next;
-//	// Reg File
-//	word reg_rd_d1, reg_rd_d2, reg_wr_d;
-//	e_reg reg_rd_a1, reg_rd_a2, reg_wr_a;
-//	assign reg_rd_a1 = rd;
-//	assign reg_rd_a2 = rs;
-//	assign reg_wr_a = rd;
-//	assign reg_wr_d = (mem_to_reg) ? mem_data : alu_out;
-//	reg_file RFILE(clk, rst, reg_rd_a1, reg_rd_a2, reg_rd_d1, reg_rd_d2, reg_wr_a, reg_wr_d, reg_wr);
-//
-//	// Mem output data
-//	assign mem_wr_data = reg_rd_d1;
-//
-//	// ALU
-//	word alu_srcA, alu_srcB;
-//	word alu_result;
-//	assign alu_srcA = reg_rd_d1;
-//	assign alu_srcB = alu_src ? imm : reg_rd_d2;
-//	word sp_sel;
-//	assign sp_sel = (mem_sp) ? sp_next : sp;
-//	assign alu_out = (sp_wr) ? sp_sel : alu_result;
-//	alu#(.WORD(8)) alu0(
-//		.a(alu_srcA),
-//		.b(alu_srcB),
-//		.op(alu_op),
-//		.r(alu_result),
-//		.zero(alu_zero)
-//	);
-//	
-//	// Program counter
-//	word pcn; 	// PC next
-//	word pcj;   // PC jump, +2 if imm used otherwise +1
-//	logic [0:1]pcadd;
-//	assign pcadd = (rimm) ? 2 : 1;
-//	assign pcj =  pc + pcadd;
-//	//assign pcj = pc + 1;
-//	assign pcn = (pc_src) ? imm : pcj;
-//	always_ff@(posedge clk) begin
-//	  	if (rst) pc <= 0;
-//		else pc <= pcn;
-//	end
-//	
-//	always_ff@(posedge clk) begin
-//		if (rst) sp <= 8'hff;
-//		if (sp_wr) sp <= sp_next;
-//	end
-//	// Optimise this
-//	assign sp_next = (mem_sp) ? sp + 1 : sp - 1;
-//endmodule
-//
-//module datapath_tb;
-//	logic clk, rst, reg_wr, pc_src, rimm, mem_to_reg, alu_zero;
-//	e_reg rs, rt;
-//	e_alu_op alu_op;
-//	word imm, mem_data, pc, alu_out;
-//	datapath DPATH(clk, rst, rs, rt, imm, alu_op, reg_wr, pc_src, rimm, mem_to_reg, pc, alu_out, mem_data, alu_zero);
-//
-//	initial begin
-//		clk = 0;
-//		forever #5ns clk = ~clk;
-//	end
-//
-//	initial begin
-//		rst = 1;
-//		reg_wr = 0;
-//		pc_src = 0;
-//		rimm = 0;
-//		mem_to_reg = 0;
-//		rs = ra;
-//		rt = ra;
-//		//alu_op = ALU_CPY;
-//		imm = 8'h00;
-//		mem_data = 8'h00;
-//		#10ns;
-//		rst = 0;
-//		reg_wr = 1;
-//		mem_to_reg = 1;
-//		mem_data = 8'h7A;
-//		#10ns;
-//		rs = rb;
-//		mem_data = 8'h8A;
-//		#10ns;
-//		rs = rc;
-//		mem_data = 8'h9A;
-//		#10ns;
-//		rs = re;
-//		mem_data = 8'hFD;
-//		#10ns;
-//		rs = ra;
-//		#10ns;
-//		$stop;
-//	end
-//
-//
-//endmodule

+ 38 - 19
src/risc/general.sv

@@ -11,25 +11,29 @@ package risc8_pkg;
 		// [ xxxx xx xx ] => [ inst rd rs ]
 		// mp: Memory page
 		// cp: Co-processor, 0x00 = RAM, 0x01 = ROM, 0x02 = FPU, 0x03 = GPIO
-		MOVE =8'b0000_????,  // &rd = &rs
-		CPY0 =8'b0000_0000,  // &rd = imm
-		CPY1 =8'b0000_0101,  // &rd = imm
-		CPY2 =8'b0000_1010,  // &rd = imm
-		CPY3 =8'b0000_1111,  // &rd = imm
+		MOVE =8'b0000_????,  // i0 &rd = &rs
+		CPY0 =8'b0000_0000,  // i0 &rd = imm
+		CPY1 =8'b0000_0101,  // i0 &rd = imm
+		CPY2 =8'b0000_1010,  // i0 &rd = imm
+		CPY3 =8'b0000_1111,  // i0 &rd = imm
 
-		ADD  =8'b0001_????,  // &rd = &rd + &rs
-		SUB  =8'b0010_????,  // &rd = &rd - &rs
-		AND  =8'b0011_????,  // &rd = &rd & &rsgt
-		OR   =8'b0100_????,  // &rd = &rd | &rs
-		XOR  =8'b0101_????,  // &rd = &rd ^ &rs
-		MUL  =8'b0110_????,  // {&ah,  &rd} = &rd * &rs
-		DIV  =8'b0111_????,  // &rd = &rd / &rs, &ah = &rd % &rs 
-		BR   =8'b1000_????,  // FIXME: Conditional branch
+		ADD  =8'b0001_????,  // i1 &rd = &rd + &rs
+		SUB  =8'b0010_????,  // i2 &rd = &rd - &rs
+		AND  =8'b0011_????,  // i3 &rd = &rd & &rsgt
+		OR   =8'b0100_????,  // i4 &rd = &rd | &rs
+		XOR  =8'b0101_????,  // i5 &rd = &rd ^ &rs
+		MUL  =8'b0110_????,  // i6 {&ah,  &rd} = &rd * &rs
+		DIV  =8'b0111_????,  // i7 &rd = &rd / &rs, &ah = &rd % &rs
+
+		CI0  =8'b1000_??00,  // i8-0
+		CI1  =8'b1000_??01,  // i8-1
+		CI2  =8'b1000_??10,  // i8-2
+		ADDC =8'b1000_??11,  // i8-3 
 		
 		SLL  =8'b1001_??00,  // i9-0 shift left logical
 		SRL  =8'b1001_??01,  // i9-1 shift right logical
 		SRA  =8'b1001_??10,  // i9-2 shift right arithmetic
-		SRAS =8'b1001_??11,  // i9-3 shift rigth arithmetic signed
+		SUBC =8'b1001_??11,  // i9-3 Low value from instruction mem
 
 		LWHI =8'b1010_??00,  // i10-0 
 		SWHI =8'b1010_??01,  // i10-1 
@@ -44,13 +48,18 @@ package risc8_pkg;
 		PUSH =8'b1100_??00,  // i12-0
         POP  =8'b1100_??01,  // i12-1 
         COM  =8'b1100_??10,  // i12-2
-		SETI =8'b1100_??11,  // i12-3 Set next immidate
+		XORI =8'b1100_??11,  // i12-3 Set next immidate
 		
 		BEQ  =8'b1101_??00,  // i13-0 Branch to imm[24:8] if imm[7:0] == rd
 		BGT  =8'b1101_??01,  // i13-1 Branch greater than
 		BGE  =8'b1101_??10,  // i13-2 Branch greater equal than
-		BZ   =8'b1101_0011,  // i13-3 Branch to imm[15:0] if rd == zero
+		BZ   =8'b1101_??11,  // i13-3 Branch to imm[15:0] if rd == zero
 
+		ADDI =8'b1110_??00,  // i14-0 
+		SUBI =8'b1110_??01,  // i14-1 
+		ANDI =8'b1110_??10,  // i14-2 
+		ORI  =8'b1110_0011,  // i14-3 
+		
 		CALL =8'b1111_0000,  // i15-0
         RET  =8'b1111_0001,  // i15-1
         JUMP =8'b1111_0010,  // i15-2
@@ -121,6 +130,14 @@ package risc8_pkg;
 		PC_MEMI= 3'b100   // TODO: Maybe Memory + interrupt flag?
 
 	} e_pcop;
+	
+	typedef enum logic [1:0] {
+		IMO_NONE = 2'b00,
+		IMO_0  	 = 2'b01,
+		IMO_1  	 = 2'b10,
+		IMO_2 	 = 2'b11
+	} e_imo_ctl;
+
 
 endpackage
 
@@ -136,23 +153,25 @@ interface risc8_cdi;  // Control Datapath interface
 	e_stackop stackop;
 	e_pcop pcop;
 	logic [2:0] alu_comp;
+	logic [1:0] aluf;
 	
 	// Register
 	reg_addr a1, a2, a3;
-	logic rw_en, mem_h;
+	e_imo_ctl imoctl;
+	logic rw_en, mem_h, pc_halt;
 	e_selr selr;
 	logic [1:0] isize; // instruction size between 1 and 4
 	
 	modport datapath(
 		input alu_op, selb, sign, alu_not, selo, stackop, pcop,
 		output alu_comp,
-		input a1, a2, a3, rw_en, selr, mem_h, isize
+		input a1, a2, a3, rw_en, selr, mem_h, isize, pc_halt, imoctl, aluf
 	);
 	
 	modport control(
 		output alu_op, selb, sign, alu_not, selo, stackop, pcop,
 		input alu_comp,
-		output a1, a2, a3, rw_en, selr, mem_h, isize
+		output a1, a2, a3, rw_en, selr, mem_h, isize, pc_halt, imoctl, aluf
 	);
 
 endinterface

+ 31 - 25
src/top.sv

@@ -41,13 +41,14 @@ module top(
 	wire fclk; // Fast clock 		100MHz 		(for sdram)
 	wire aclk; // Auxiliary clock 	32,768kHz 	(for timers)
 	
-	pll_clk pll_clk0 (
+	pll_clkpll_clk0 (
 			.inclk0(CLK50),
 			.areset(0),
 			.c0(fclk),
 			.c1(mclk),
 			.c2(aclk)
 	);
+
 	//clk_dive#(28'd50) clk_div_mclk(CLK50, mclk);
 	//assign mclk = ~KEY[1];	
 	//assign mclk = CLK50;	
@@ -61,29 +62,31 @@ module top(
 	wire  		ram_rd_ready;
 	wire  		ram_rd_ack;
 	
-	sdram_block sdram0(
-		.mclk(mclk), 
-		.fclk(fclk), 
-		.rst(rst), 
-		.ram_addr(ram_addr),
-		.ram_wr_data(ram_wr_data),
-		.ram_rd_data(ram_rd_data),
-		.ram_wr_en(ram_wr_en),
-		.ram_rd_en(ram_rd_en),
-		.ram_busy(ram_busy),
-		.ram_rd_ready(ram_rd_ready),
-		.ram_rd_ack(ram_rd_ack),
-		.DRAM_DQ(DRAM_DQ),	
-		.DRAM_ADDR(DRAM_ADDR),	
-		.DRAM_DQM(DRAM_DQM),	
-		.DRAM_CLK(DRAM_CLK),	
-		.DRAM_CKE(DRAM_CKE),	
-		.DRAM_WE_N(DRAM_WE_N),	
-		.DRAM_CAS_N(DRAM_CAS_N),
-		.DRAM_RAS_N(DRAM_RAS_N),
-		.DRAM_CS_N(DRAM_CS_N),	
-		.DRAM_BA(DRAM_BA)	
-	);
+	ram#("../../memory/risc8.data") ram_block0(ram_addr[11:0], mclk, ram_wr_data, ram_wr_en, ram_rd_en, ram_rd_data);
+	
+	//sdram_block sdram0(
+	//	.mclk(mclk), 
+	//	.fclk(fclk), 
+	//	.rst_n(~rst), 
+	//	.ram_addr(racm_addr),
+	//	.ram_wr_data(ram_wr_data),
+	//	.ram_rd_data(ram_rd_data),
+	//	.ram_wr_en(ram_wr_en),
+	//	.ram_rd_en(ram_rd_en),
+	//	.ram_busy(ram_busy),
+	//	.ram_rd_ready(ram_rd_ready),
+	//	.ram_rd_ack(ram_rd_ack),
+	//	.DRAM_DQ(DRAM_DQ),	
+	//	.DRAM_ADDR(DRAM_ADDR),	
+	//	.DRAM_DQM(DRAM_DQM),	
+	//	.DRAM_CLK(DRAM_CLK),	
+	//	.DRAM_CKE(DRAM_CKE),	
+	//	.DRAM_WE_N(DRAM_WE_N),	
+	//	.DRAM_CAS_N(DRAM_CAS_N),
+	//	.DRAM_RAS_N(DRAM_RAS_N),
+	//	.DRAM_CS_N(DRAM_CS_N),	
+	//	.DRAM_BA(DRAM_BA)	
+	//);
 
 	//Communication block
 	wire [7:0] com0_addr, com0_wr, com0_rd;
@@ -179,6 +182,9 @@ module top_tb;
 				DRAM_BA	
 				);
 
+	initial if(top0.com0_addr == 8'h05) $display("%t UART0 send: %s", $time, top0.com0_wr); 
+
+
 	initial begin
 			CLK50 = 0;
 			KEY[0] = 0;
@@ -188,7 +194,7 @@ module top_tb;
 
 			#1100ns;
 			KEY[0] = 1;
-			#10us;
+			#300us;
 			$stop;
 	end
 	initial forever #10ns CLK50 = ~CLK50;

+ 263 - 214
tools/asm_compiler.py

@@ -3,76 +3,25 @@
 import re
 import math
 import traceback
+from typing import Dict, List
 
-label_re = re.compile(r"^[\w\$\#\@\~\.\?]+$", re.IGNORECASE)
+label_re = re.compile(r"^[\w$#@~.?]+$", re.IGNORECASE)
 hex_re = re.compile(r"^[0-9a-f]+$", re.IGNORECASE)
 bin_re = re.compile(r"^[0-1_]+$", re.IGNORECASE)
 oct_re = re.compile(r"^[0-8]+$", re.IGNORECASE)
+args_re = re.compile("(?:^|,)(?=[^\"]|(\")?)\"?((?(1)[^\"]*|[^,\"]*))\"?(?=,|$)", re.IGNORECASE)
+func_re = re.compile("^([\w$#@~.?]+)\s*([|^<>+\-*/%@]{1,2})\s*([\w$#@~.?]+)$", re.IGNORECASE)
+secs_re = re.compile("^([\d]+)x([\d]+)x([\d]+)$", re.IGNORECASE)
+
+def args2operands(args):
+    operands = ['"' + a[1] + '"' if a[0] == '"' else a[1] for a in args_re.findall(args or '') if a[1]]
+    return operands
 
 
 def match(regex, s):
     return regex.match(s) is not None
 
 
-def decode_bytes(val: str):
-    try:
-        if val.endswith('h'):
-            return [int(val[i:i + 2], 16) for i in range(0, len(val) - 1, 2)]
-        if val.startswith('0x'):
-            return [int(val[i:i + 2], 16) for i in range(2, len(val), 2)]
-        if val.startswith('b'):
-            val = val.replace('_', '')[1:]
-            return [int(val[i:i + 8], 2) for i in range(0, len(val), 8)]
-    except ValueError:
-        raise ValueError(f"Invalid binary '{val}'")
-    if val.isdigit():
-        i = int(val)
-        if i > 255 or i < 0:
-            raise ValueError(f"Invalid binary '{val}', unsigned int out of bounds")
-        return [i]
-    if (val.startswith('+') or val.startswith('-')) and val[1:].isdigit():
-        i = int(val)
-        if i > 127 or i < -128:
-            raise ValueError(f"Invalid binary '{val}', signed int out of bounds")
-        if i < 0:  # convert to unsigned
-            i += 2 ** 8
-        return [i]
-    if len(val) == 3 and ((val[0] == "'" and val[2] == "'") or (val[0] == '"' and val[2] == '"')):
-        return [ord(val[1])]
-    raise ValueError(f"Invalid binary '{val}'")
-
-
-def is_reg(r):
-    if r.startswith('$'):
-        r = r[1:]
-        if r.isnumeric() and 0 <= int(r) <= 3:
-            return True
-    elif len(r) == 2 and r[0] == 'r' and r[1] in {'0', '1', '2', '3', 'a', 'b', 'c', 'e'}:
-        return True
-    return False
-
-
-def decode_reg(r):
-    if r.startswith('$') and r[1:].isnumeric():
-        r = int(r[1:])
-    if isinstance(r, int):
-        if 0 <= r <= 3:
-            return r
-        raise ValueError(f"Invalid register value {r}")
-    rl = r.lower()
-    if rl.startswith('$'):
-        rl = rl[1:]
-    if rl == 'ra' or rl == 'r0':
-        return 0
-    if rl == 'rb' or rl == 'r1':
-        return 1
-    if rl == 'rc' or rl == 'r2':
-        return 2
-    if rl == 're' or rl == 'r3':
-        return 3
-    raise ValueError(f"Invalid register name '{r}'")
-
-
 class CompilingError(Exception):
     def __init__(self, message):
         self.message = message
@@ -90,13 +39,18 @@ class Instruction:
             raise InstructionError(f"Invalid instruction name '{name}'")
         self.name = name.strip()
         self.alias = alias or []
-        self.opcode = decode_bytes(opcode.replace('?', '0'))[0]
+
         self.reg_operands = 0
-        if len(opcode) == 10:
-            if opcode[6:8] == '??':
+        opcode = opcode.replace('_', '')
+        if len(opcode) == 8:
+            if opcode[4:6] == '??':
                 self.reg_operands += 1
-            if opcode[8:10] == '??':
+            if opcode[6:8] == '??':
                 self.reg_operands += 1
+        else:
+            raise CompilingError("Invalid opcode: " + opcode)
+
+        self.opcode = int(opcode.replace('?', '0'), 2)
         self.imm_operands = operands
         self.compiler = None
 
@@ -107,22 +61,10 @@ class Instruction:
     def __len__(self):
         return self.length
 
-    def _gen_instr(self, regs, imm):
+    def _gen_instr(self, regs):
         instr = self.opcode
         if len(regs) != self.reg_operands:
             raise CompilingError(f"Invalid number of registers: set {len(regs)}, required: {self.reg_operands}")
-        limm = 0
-        for i in imm:
-            if isinstance(i, str):
-                if i in self.compiler.labels:
-                    d = self.compiler.labels[i]
-                    limm += len(d)
-                else:
-                    limm += self.compiler.address_size
-            else:
-                limm += len(i)
-        if limm != self.imm_operands:
-            raise CompilingError(f"Invalid number of immediate: set {limm}, required: {self.reg_operands}")
         if len(regs) == 2:
             if regs[1] is None:
                 raise CompilingError(f"Unable to decode register name {regs[1]}")
@@ -133,43 +75,36 @@ class Instruction:
             if regs[0] is None:
                 raise CompilingError(f"Unable to decode register name {regs[0]}")
             instr |= int(regs[0]) << 2
-        return instr
+        return instr.to_bytes(1, 'little')  # Order does not matter with 1 byte
 
-    def compile(self, operands):
+    def compile(self, operands, scope):
         regs = []
-        imm = []
-        for i, arg in enumerate(operands):
-            if self.reg_operands > i:
-                regs.append(self.compiler.decode_reg(arg))
-            else:
-                imm.append(self.compiler.decode_bytes(arg))
+        for reg in operands[:self.reg_operands]:
+            regs.append(self.compiler.decode_reg(reg))
 
-        instr = self._gen_instr(regs, imm)
-        return [instr] + imm
+        imm = self.compiler.decode_with_labels(operands[self.reg_operands:], scope)
+        if len(imm) != self.imm_operands:
+            raise CompilingError(f"Instruction {self.name} has invalid argument size {len(imm)} != {self.imm_operands},"
+                                 f" supplied args: 0x{imm.hex()}")
+        instr = self._gen_instr(regs)
 
+        return instr + imm
 
-class CompObject:
-    def __init__(self, instr, operands, line_num):
-        self.instr = instr
-        self.operands = operands
-        self.line_num = line_num
-        self.code = []
-        self.code_ref = 0
-        self.code = self.instr.compile(self.operands)
 
-    def instr_len(self):
-        if hasattr(self.instr, 'get_imm_operands'):
-            o = getattr(self.instr, 'get_imm_operands')
-            return o(self.operands)
-        else:
-            return self.instr.length
+class Section:
+    def __init__(self):
+        self.instr = []
+        self.data = b''
+        self.count = 0
+        self.width = 1
+        self.length = 1
+        self.size = 2**8
 
 
 class Compiler:
     def __init__(self, address_size=2, byte_order='little'):
-        self.instr_db = {}
+        self.instr_db: Dict[str, Instruction] = {}
         self.data = []
-        self.caddress = 0
         self.labels = {}
         self.order = byte_order
         self.regnames = {}
@@ -177,21 +112,9 @@ class Compiler:
 
     def decode_reg(self, s: str):
         s = s.strip()
-        # if s in self.labels:
-        #     b = self.labels[s]
         if s in self.regnames:
-            b = self.regnames[s]
-        else:
-            b = self.decode_bytes(s)
-        if isinstance(b, bytes):
-            i = int.from_bytes(b, byteorder=self.order)
-        elif isinstance(b, int):
-            i = b
-        else:
-            raise CompilingError(f"Unrecognised register name: {s}")
-        if i not in self.regnames.values():
-            raise CompilingError(f"Invalid register: {s}")
-        return i
+            return self.regnames[s]
+        raise CompilingError(f"Unrecognised register name: {s}")
 
     def decode_bytes(self, s: str):
         s = s.strip()
@@ -236,6 +159,10 @@ class Compiler:
             s = ord(s[1:-1]).to_bytes(1, self.order)
             typ = 'ascii'
 
+        elif (s.startswith("'") and s.endswith("'")) or (s.startswith('"') and s.endswith('"')):
+            s = s[1:-1].encode('utf-8').decode("unicode_escape").encode('utf-8')
+            typ = 'string'
+
         # Convert with limits
         if typ == 'int':
             numb = int(s)
@@ -259,9 +186,31 @@ class Compiler:
         else:
             return s
 
-    @staticmethod
-    def _hash_instr(name, operands):
-        return hash(name) + hash(operands)
+    def _decode_labels(self, arg, scope):
+        immx = self.decode_bytes(arg)
+        if isinstance(immx, str):
+            if immx.startswith('.'):
+                immx = scope + immx
+            if immx in self.labels:
+                return self.labels[immx]
+            else:
+                raise CompilingError(f"Unknown label: {immx}")
+        elif isinstance(immx, bytes):
+            return immx
+
+    def decode_with_labels(self, args, scope):
+        data = b''
+        for arg in args:
+            if isinstance(arg, str):
+                funcm = func_re.match(arg)
+                if funcm is not None:
+                    g = funcm.groups()
+                    left = self._decode_labels(g[0], scope)
+                    right = self._decode_labels(g[2], scope)
+                    data += self.proc_func(left, right, g[1])
+                    continue
+            data += self._decode_labels(arg, scope)
+        return data
 
     def add_reg(self, name, val):
         self.regnames[name] = val
@@ -270,110 +219,185 @@ class Compiler:
     def add_instr(self, instr: Instruction):
         instr.compiler = self
         operands = instr.reg_operands + instr.imm_operands
-        # ihash = self._hash_instr(instr.name, operands)
 
         if instr.name in self.instr_db:
             raise InstructionError(f"Instruction {instr.name} operands={operands} duplicate!")
         self.instr_db[instr.name] = instr
         for alias in instr.alias:
-            # ahash = self._hash_instr(alias, operands)
             if alias.lower() in self.instr_db:
                 raise InstructionError(f"Instruction alias {alias} operands={operands} duplicate!")
             self.instr_db[alias.lower()] = instr
 
-    def __func(self, f, args):
-        for arg in args:
-            if arg == '|':
-                pass
-            if arg == '^':
-                pass
-            if arg == '&':
-                pass
-            if arg == '<<':
-                pass
-            if arg == '>>':
-                pass
-            if arg == '+':
-                pass
-            if arg == '-':
-                pass
-            if arg == '*':
-                pass
-            if arg == '/' or arg == '//':
-                pass
-            if arg == '%' or arg == '%%':
-                pass
-
-    def __precompile(self, line):
-        line = line.split(';', 1)[0]
-        if ':' in line:
-            linespl = line.split(':', 1)
-            line = linespl[1]
-            label = linespl[0]
-            if label in self.labels:
-                raise CompilingError(f"Label {label} duplicate")
-            self.labels[label] = self.caddress.to_bytes(self.address_size, self.order)
-        if line.startswith('%define'):
-            sp = list(filter(None, line.split(' ', 3)))
-            if len(sp) != 3:
-                raise CompilingError(f"Invalid %define")
-            if '(' in sp[1] and ')' in sp[1]:  # Function
-                raise CompilingError(f"%define functions not implemented")
-            self.labels[sp[1]] = self.decode_bytes(sp[2])
-            return
-        instr0 = list(filter(None, line.strip().split(' ', 1)))
-        if len(instr0) == 0:
-            return
-        instr = instr0[0]
-        if len(instr0) == 1:
-            instr0.append('')
-        operands = list(filter(None, map(lambda x: x.strip(), instr0[1].split(','))))
-        if instr.lower() not in self.instr_db:
-            raise CompilingError(f"Instruction {instr} operands={operands} is not recognised!")
-        co = CompObject(self.instr_db[instr.lower()], operands, 0)
-        return co
+    def proc_func(self, left, right, op):
+        if op == '|':
+            return left | right
+        if op == '^':
+            return left ^ right
+        if op == '&':
+            return left & right
+        if op == '<<':
+            return left << right
+        if op == '>>':
+            return left >> right
+        if op == '+':
+            return left + right
+        if op == '-':
+            return left - right
+        if op == '*':
+            return left * right
+        if op == '/' or op == '//':
+            return left / right
+        if op == '%' or op == '%%':
+            return left % right
+        if op == '@':
+            return bytes([left[len(left)-int.from_bytes(right, byteorder=self.order)-1]])
+        raise CompilingError(f"Invalid function operation {op}")
 
     def compile(self, file, code):
         failure = False
-        instr = []
-        binary = []
+
+        sections: Dict[str, Section] = {}
+        csect = None
+        scope = None
+
         for lnum, line in enumerate(code):
             lnum += 1
+            line = line.split(';', 1)[0].strip()
+
             try:
-                co = self.__precompile(line)
-                if co is not None:
-                    co.line_num = lnum
-                    self.caddress += co.instr_len()
-                    instr.append(co)
+                line_args = [l.strip() for l in line.split(' ', 2)]
+                # line_args = list(filter(lambda x: len(x) > 0, line_args))
+                if len(line_args) == 0 or line_args[0] == '':
+                    continue
+
+                # Section
+                if line_args[0].lower() == 'section':
+                    if len(line_args) < 2:
+                        raise CompilingError(f"Invalid section arguments!")
+                    section_name = line_args[1].lower()
+                    if section_name not in sections:
+                        s = Section()
+                        if len(line_args) == 3:
+                            m = secs_re.match(line_args[2])
+                            if m is not None:
+                                g = m.groups()
+                                s.width = int(g[0])
+                                s.length = int(g[1])
+                                s.size = int(g[2])
+                            else:
+                                raise CompilingError(f"Invalid section argument: {line_args[2]}")
+                        sections[section_name] = s
+                    csect = sections[section_name]
+                    continue
+
+                # Macros
+                elif line_args[0].lower() == '%define':
+                    if len(line_args) != 3:
+                        raise CompilingError(f"Invalid %define arguments!")
+                    self.labels[line_args[1]] = self.decode_bytes(line_args[2])
+                    continue
+
+                if csect is None:
+                    raise CompilingError(f"No section defined!")
+
+                builtin_cmds = {'db'}
+
+                if line_args[0].lower() not in self.instr_db and\
+                        line_args[0].lower() not in builtin_cmds:  # Must be label
+                    label = line_args[0]
+                    line_args = line_args[1:]
+                    if label.startswith('.'):
+                        if scope is None:
+                            raise CompilingError(f"No local scope for {label}!")
+                        label = scope + label
+                    else:
+                        scope = label
+                    if label in self.labels:
+                        raise CompilingError(f"Label {label} duplicate")
+                    self.labels[label] = csect.count.to_bytes(csect.length, self.order)
+
+                if len(line_args) == 0:
+                    continue
+                elif len(line_args) == 1:
+                    instr_name, args = line_args[0].lower(), None
+                else:
+                    instr_name, args = line_args[0].lower(), line_args[1]
+
+                # Builtin instructions
+                if instr_name == 'db':
+                    data = self.decode_with_labels(args2operands(args), scope)
+                    if len(data) % csect.width != 0:
+                        fill = csect.width - (len(data) % csect.width)
+                        data += b'\x00' * fill
+                    csect.instr.append(data)
+                    csect.count += int(len(data)/csect.width)
+                    continue
+
+                if instr_name not in self.instr_db:
+                    raise CompilingError(f"Instruction '{instr_name}' not recognised!")
+
+                instr_obj = self.instr_db[instr_name.lower()]
+                csect.instr.append((instr_obj, args, lnum, scope))
+                csect.count += instr_obj.length
+
             except CompilingError as e:
                 failure = True
                 print(f"ERROR {file}:{lnum}: {e.message}")
-        for co in instr:
-            try:
-                binary += co.code
-            except CompilingError as e:
-                failure = True
-                print(f"ERROR {file}:{co.line_num}: {e.message}")
-            except Exception:
-                failure = True
-                print(f"ERROR {file}:{co.line_num}: Unexpected error:")
-                traceback.print_exc()
-
-        nbin = bytearray()
-        for b in binary:
-            if isinstance(b, int):
-                nbin += b.to_bytes(1, self.order)
-            elif isinstance(b, bytes):
-                nbin += b
-            elif isinstance(b, str):
-                if b in self.labels:
-                    nbin += self.labels[b]
-                else:
+
+        for section in sections.values():
+            for instr_tuple in section.instr:
+                if isinstance(instr_tuple, bytes):
+                    section.data += instr_tuple
+                    continue
+                instr, args, lnum, scope = instr_tuple
+                try:
+                    operands = args2operands(args)
+                    section.data += instr.compile(operands, scope)
+                except CompilingError as e:
                     failure = True
-                    print(f"ERROR {file}: Unable to find label '{b}'")
+                    print(f"ERROR {file}:{lnum}: {e.message}")
         if failure:
             return None
-        return nbin
+        return {k: (v.width, v.length, v.size, v.data) for k, v in sections.items()}
+
+    def decompile(self, binary):
+        addr = 0
+        res = []
+        ibin = iter(binary)
+        for data in ibin:
+            norm0 = int(data)
+            norm1 = norm0 & int('11110011', 2)
+            norm2 = norm0 & int('11110000', 2)
+
+            for instr in self.instr_db.values():
+                if not ((instr.reg_operands == 0 and norm0 == instr.opcode) or
+                        (instr.reg_operands == 1 and norm1 == instr.opcode) or
+                        (instr.reg_operands == 2 and norm2 == instr.opcode)):
+                    continue
+                asm = f'{addr:04x}: {instr.name.upper().ljust(6)}'
+                args = []
+                raw = format(norm0, '02x')
+                if instr.reg_operands > 0:
+                    args.append(f'r{(norm0 & 12) >> 2}')
+                if instr.reg_operands > 1:
+                    args.append(f'r{(norm0 & 3)}')
+                if instr.imm_operands > 0:
+                    b = '0x'
+                    for i in range(instr.imm_operands):
+                        try:
+                            bi = format(int(next(ibin)), '02x')
+                        except StopIteration:
+                            break
+                        b += bi
+                        raw += bi
+                        addr += 1
+                    args.append(b)
+                line = asm + ', '.join(args)
+                tabs = ' ' * (27 - int(len(line)))
+                res.append(f'{line}{tabs}[{raw}]')
+                break
+            addr += 1
+        return '\n'.join(res)
 
 
 def convert_to_binary(data):
@@ -381,31 +405,56 @@ def convert_to_binary(data):
     return a.encode()
 
 
-def convert_to_mem(data):
+def convert_to_mem(data, width=1, uhex=False):
     x = b''
-    fa = f'0{math.ceil(math.ceil(math.log2(len(data)))/4)}x'
-    a = [format(d, '02x') for d in data]
+
+    if uhex:
+        if width == 2:
+            for i in range(int(len(data)/2)):
+                x += format(data[-(i*2) - 2], f'02x').upper().encode()
+                x += format(data[-(i*2) - 1], f'02x').upper().encode()
+        else:
+            for i in range(len(data)):
+                x += format(data[-i-1], f'02x').upper().encode()
+        return x
+
+    if width == 2:
+        datax = [(x << 8) | y for x, y in zip(data[0::2], data[1::2])]
+        if len(data) % 2 == 1:
+            datax.append(data[-1] << 8)
+    else:
+        datax = data
+
+    fa = f'0{math.ceil(math.ceil(math.log2(len(datax))) / 4)}x'
+    a = [format(d, f'0{width*2}x') for d in datax]
     for i in range(int(len(a) / 8) + 1):
         y = a[i * 8:(i + 1) * 8]
         if len(y) > 0:
-            x += (' '.join(y) + ' '*((8-len(y))*3) + '  // ' + format((i*8-1)+len(y), fa) + '\n').encode()
+            x += (' '.join(y) + ' ' * ((8 - len(y)) * 3) + '  // ' + format((i * 8 - 1) + len(y), fa) + '\n').encode()
     return x
 
 
-def convert_to_mif(data, depth=32, width=8):
+def convert_to_mif(data, depth=32, width=1):
     x = f'''-- auto-generated memory initialisation file
-DEPTH = {depth};
-WIDTH = {width};
+DEPTH = {math.ceil(depth)};
+WIDTH = {width*8};
 ADDRESS_RADIX = HEX;
 DATA_RADIX = HEX;
 CONTENT
 BEGIN
 '''.encode()
-    addr_format = f'0{math.ceil(int(math.log2(len(data)))/4)}x'
-    a = [format(i, '02x') for i in data]
-    for i in range(int(len(a) / 8) + 1):
+
+    addr_format = f'0{math.ceil(int(math.log2(len(data))) / 4)}x'
+    if width == 2:
+        datax = [(x << 8) | y for x, y in zip(data[0::2], data[1::2])]
+        if len(data) % 2 == 1:
+            datax.append(data[-1] << 8)
+    else:
+        datax = data
+    a = [format(i, f'0{width*2}x') for i in datax]
+    for i in range(int(len(a*width) / 8) + 1):
         y = a[i * 8:(i + 1) * 8]
         if len(y) > 0:
-            x += (format(i*8, addr_format) + ' : ' + ' '.join(y) + ';\n').encode()
+            x += (format(i * 8, addr_format) + ' : ' + ' '.join(y) + ';\n').encode()
     x += b"END;"
     return x

+ 121 - 114
tools/risc8asm.py

@@ -1,9 +1,9 @@
 import argparse
 import sys
 import math
-from os import path
+from os import path, mkdir
 
-import asm_compiler as compiler
+import nasm_compiler as compiler
 
 asmc = compiler.Compiler(byte_order='big')
 asmc.add_reg('r0', 0)
@@ -11,112 +11,106 @@ asmc.add_reg('r1', 1)
 asmc.add_reg('r2', 2)
 asmc.add_reg('r3', 3)
 
-
-class MoveInstr(compiler.Instruction):
-    def get_imm_operands(self, operands):
-        try:
-            self.compiler.decode_reg(operands[1])
-            return 1
-        except compiler.CompilingError:
-            return 2
-
-    def compile(self, operands):
-        regs = [0, 0]
-        imm = []
-        regs[0] = self.compiler.decode_reg(operands[0])
-        try:
-            regs[1] = self.compiler.decode_reg(operands[1])
-            self.imm_operands = 0   # Assuming this gonna be changed every time
-        except compiler.CompilingError:
-            regs[1] = regs[0]
-            self.imm_operands = 1
-            imm = [self.compiler.decode_bytes(operands[1])]
-        instr = self._gen_instr(regs, imm)
-        return [instr] + imm
-
-
-asmc.add_instr(MoveInstr('MOVE ', 'b0000_????'))
-asmc.add_instr(compiler.Instruction('ADD  ', 'b0001_????'))
-asmc.add_instr(compiler.Instruction('SUB  ', 'b0010_????'))
-asmc.add_instr(compiler.Instruction('AND  ', 'b0011_????'))
-asmc.add_instr(compiler.Instruction('OR   ', 'b0100_????'))
-asmc.add_instr(compiler.Instruction('XOR  ', 'b0101_????'))
-asmc.add_instr(compiler.Instruction('MUL  ', 'b0110_????'))
-asmc.add_instr(compiler.Instruction('DIV  ', 'b0111_????'))
-asmc.add_instr(compiler.Instruction('BR   ', 'b1000_????', 2))
-asmc.add_instr(compiler.Instruction('SLL  ', 'b1001_??00'))
-asmc.add_instr(compiler.Instruction('SRL  ', 'b1001_??01'))
-asmc.add_instr(compiler.Instruction('SRA  ', 'b1001_??10'))
-asmc.add_instr(compiler.Instruction('SRAS ', 'b1001_??11'))
-asmc.add_instr(compiler.Instruction('LWHI ', 'b1010_??00', 3))
-asmc.add_instr(compiler.Instruction('SWHI ', 'b1010_??01'))
-asmc.add_instr(compiler.Instruction('LWLO ', 'b1010_??10', 3))
-asmc.add_instr(compiler.Instruction('SWLO ', 'b1010_??11', 3))
-asmc.add_instr(compiler.Instruction('INC  ', 'b1011_??00'))
-asmc.add_instr(compiler.Instruction('DEC  ', 'b1011_??01'))
-asmc.add_instr(compiler.Instruction('GETAH', 'b1011_??10'))
-asmc.add_instr(compiler.Instruction('GETIF', 'b1011_??11'))
-asmc.add_instr(compiler.Instruction('PUSH ', 'b1100_??00'))
-asmc.add_instr(compiler.Instruction('POP  ', 'b1100_??01'))
-asmc.add_instr(compiler.Instruction('COM  ', 'b1100_??10', 1))
-asmc.add_instr(compiler.Instruction('SETI ', 'b1100_??11'))
-asmc.add_instr(compiler.Instruction('BEQ  ', 'b1101_??00', 3))
-asmc.add_instr(compiler.Instruction('BGT  ', 'b1101_??01', 3))
-asmc.add_instr(compiler.Instruction('BGE  ', 'b1101_??10', 3))
-asmc.add_instr(compiler.Instruction('BZ   ', 'b1101_0011'))
-asmc.add_instr(compiler.Instruction('CALL ', 'b1111_0000', 2))
-asmc.add_instr(compiler.Instruction('RET  ', 'b1111_0001'))
-asmc.add_instr(compiler.Instruction('JUMP ', 'b1111_0010', 2))
-asmc.add_instr(compiler.Instruction('RETI ', 'b1111_0011'))
-asmc.add_instr(compiler.Instruction('CLC  ', 'b1111_0100'))
-asmc.add_instr(compiler.Instruction('SETC ', 'b1111_0101'))
-asmc.add_instr(compiler.Instruction('CLS  ', 'b1111_0110'))
-asmc.add_instr(compiler.Instruction('SETS ', 'b1111_0111'))
-asmc.add_instr(compiler.Instruction('SSETS', 'b1111_1000'))
-asmc.add_instr(compiler.Instruction('CLN  ', 'b1111_1001'))
-asmc.add_instr(compiler.Instruction('SETN ', 'b1111_1010'))
-asmc.add_instr(compiler.Instruction('SSETN', 'b1111_1011'))
-asmc.add_instr(compiler.Instruction('RJUMP', 'b1111_1100', 2))
-asmc.add_instr(compiler.Instruction('RBWI ', 'b1111_1101'))
-
+asmc.add_instr(compiler.Instruction('CPY0 ', '0000_0000', 1, alias=['COPY0']))
+asmc.add_instr(compiler.Instruction('CPY1 ', '0000_0101', 1, alias=['COPY1']))
+asmc.add_instr(compiler.Instruction('CPY2 ', '0000_1010', 1, alias=['COPY2']))
+asmc.add_instr(compiler.Instruction('CPY3 ', '0000_1111', 1, alias=['COPY3']))
+
+asmc.add_instr(compiler.Instruction('MOVE ', '0000_????'))
+asmc.add_instr(compiler.Instruction('ADD  ', '0001_????'))
+asmc.add_instr(compiler.Instruction('SUB  ', '0010_????'))
+asmc.add_instr(compiler.Instruction('AND  ', '0011_????'))
+asmc.add_instr(compiler.Instruction('OR   ', '0100_????'))
+asmc.add_instr(compiler.Instruction('XOR  ', '0101_????'))
+asmc.add_instr(compiler.Instruction('MUL  ', '0110_????'))
+asmc.add_instr(compiler.Instruction('DIV  ', '0111_????'))
+
+asmc.add_instr(compiler.Instruction('CI0  ', '1000_??00'))
+asmc.add_instr(compiler.Instruction('CI1  ', '1000_??01'))
+asmc.add_instr(compiler.Instruction('CI2  ', '1000_??10'))
+asmc.add_instr(compiler.Instruction('ADDC ', '1000_??11'))
+
+asmc.add_instr(compiler.Instruction('ADDI',  '1110_??00', 1))
+asmc.add_instr(compiler.Instruction('SUBI ', '1110_??01', 1))
+asmc.add_instr(compiler.Instruction('ANDI ', '1110_??10', 1))
+asmc.add_instr(compiler.Instruction('ORI  ', '1110_??11', 1))
+asmc.add_instr(compiler.Instruction('XORI ', '1100_??11', 1))
+
+asmc.add_instr(compiler.Instruction('SLL  ', '1001_??00'))
+asmc.add_instr(compiler.Instruction('SRL  ', '1001_??01'))
+asmc.add_instr(compiler.Instruction('SRA  ', '1001_??10'))
+asmc.add_instr(compiler.Instruction('SRAS ', '1001_??11'))
+asmc.add_instr(compiler.Instruction('LWHI ', '1010_??00', 3))
+asmc.add_instr(compiler.Instruction('SWHI ', '1010_??01'))
+asmc.add_instr(compiler.Instruction('LWLO ', '1010_??10', 3))
+asmc.add_instr(compiler.Instruction('SWLO ', '1010_??11', 3))
+asmc.add_instr(compiler.Instruction('INC  ', '1011_??00'))
+asmc.add_instr(compiler.Instruction('DEC  ', '1011_??01'))
+asmc.add_instr(compiler.Instruction('GETAH', '1011_??10'))
+asmc.add_instr(compiler.Instruction('GETIF', '1011_??11'))
+asmc.add_instr(compiler.Instruction('PUSH ', '1100_??00'))
+asmc.add_instr(compiler.Instruction('POP  ', '1100_??01'))
+asmc.add_instr(compiler.Instruction('COM  ', '1100_??10', 1))
+asmc.add_instr(compiler.Instruction('SETI ', '1100_??11'))
+asmc.add_instr(compiler.Instruction('BEQ  ', '1101_??00', 3))
+asmc.add_instr(compiler.Instruction('BGT  ', '1101_??01', 3))
+asmc.add_instr(compiler.Instruction('BGE  ', '1101_??10', 3))
+asmc.add_instr(compiler.Instruction('BZ   ', '1101_??11', 2))
+asmc.add_instr(compiler.Instruction('CALL ', '1111_0000', 2))
+asmc.add_instr(compiler.Instruction('RET  ', '1111_0001'))
+asmc.add_instr(compiler.Instruction('JUMP ', '1111_0010', 2))
+asmc.add_instr(compiler.Instruction('RETI ', '1111_0011'))
+asmc.add_instr(compiler.Instruction('CLC  ', '1111_0100'))
+asmc.add_instr(compiler.Instruction('SETC ', '1111_0101'))
+asmc.add_instr(compiler.Instruction('CLS  ', '1111_0110'))
+asmc.add_instr(compiler.Instruction('SETS ', '1111_0111'))
+asmc.add_instr(compiler.Instruction('SSETS', '1111_1000'))
+asmc.add_instr(compiler.Instruction('CLN  ', '1111_1001'))
+asmc.add_instr(compiler.Instruction('SETN ', '1111_1010'))
+asmc.add_instr(compiler.Instruction('SSETN', '1111_1011'))
+asmc.add_instr(compiler.Instruction('RJUMP', '1111_1100', 2))
+asmc.add_instr(compiler.Instruction('RBWI ', '1111_1101'))
 
 if __name__ == '__main__':
     parser = argparse.ArgumentParser(description='Assembly compiler', add_help=True)
     parser.add_argument('file', help='Files to compile')
-    parser.add_argument('-t', '--output_type', choices=['bin', 'mem', 'binary', 'mif'], default='mem', help='Output type')
-    parser.add_argument('-S', '--slice', type=int, default=0, help='if defined, output to multiple sliced files')
-    parser.add_argument('-o', '--output', help='Output file')
+    parser.add_argument('-t', '--output_type', choices=['bin', 'mem', 'binary', 'mif', 'uhex'], default='mem',
+                        help='Output type')
+    parser.add_argument('-S', '--slice', default=-1, type=int, help='Slice output for section')
+    parser.add_argument('-o', '--output', help='Output directory')
     parser.add_argument('-f', '--force', action='store_true', help='Force override output file')
     parser.add_argument('-s', '--stdout', action='store_true', help='Print to stdout')
-    parser.add_argument('-l', '--size', type=int, default=0, help='if defined, fill rest of memory with 0x00')
+    parser.add_argument('-D', '--decompile', action='store_true', help='Print decompiled')
+    parser.add_argument('section', help='Section')
     args = parser.parse_args(sys.argv[1:])
     if not path.isfile(args.file):
         print(f'No file {args.file}!')
         sys.exit(1)
 
-
-    output = args.output
-    if not output:
-        bname = args.file.rsplit('.', 1)
-        if args.output_type == 'mem':
-            ext = '.mem'
-        elif args.output_type == 'bin':
-            ext = '.bin'
-        elif args.output_type == 'mif':
-            ext = '.mif'
-        else:
-            ext = '.out'
-        output = bname[0] + ext
-    outputs = []
+    output_dir = args.output or path.dirname(args.file)
+    if not path.exists(output_dir):
+        mkdir(output_dir)
+
+    if args.output_type == 'mem':
+        ext = '.mem'
+    elif args.output_type == 'bin':
+        ext = '.bin'
+    elif args.output_type == 'mif':
+        ext = '.mif'
+    elif args.output_type == 'uhex':
+        ext = '.uhex'
+    else:
+        ext = '.out'
+    bname = path.basename(args.file).rsplit('.', 1)[0]
 
     sformat = f'01d'
+    outputs = []
     if args.slice > 0:
         sformat = f'0{int(math.log10(args.slice)) + 1}d'
         for i in range(0, args.slice):
-            bname = output.rsplit('.', 1)
-            outputs.append(f'{bname[0]}_{format(i, sformat)}.{bname[1]}')
+            outputs.append(path.join(output_dir,f'{bname}{args.section}_{format(i, sformat)}{ext}'))
     else:
-        outputs = [output]
+        outputs = [path.join(output_dir, bname + args.section + ext)]
     if not args.stdout and not args.force:
         for output in outputs:
             if path.isfile(output):
@@ -126,30 +120,43 @@ if __name__ == '__main__':
     with open(args.file, 'r') as f:
         data = asmc.compile(args.file, f.readlines())
     if data is not None:
-        if args.size > 0:
-            data = data + (args.size - len(data)) * bytearray(b'\x00')
-
-        for i, output in enumerate(outputs):
-
-            y = data[i::len(outputs)]
-            if args.output_type == 'binary':
-                x = compiler.convert_to_binary(y)
-            elif args.output_type == 'mem':
-                x = compiler.convert_to_mem(y)
-            elif args.output_type == 'mif':
-                x = compiler.convert_to_mif(y, depth=len(y))
-            else:
-                x = bytes(y)
-
-            op = 'Printing' if args.stdout else 'Saving'
-            print(f"{op} {args.output_type} data '{output}' [Size: {len(y)}B Slice: {format(i + 1, sformat)}/{len(outputs)}]")
-            if args.stdout:
-                print(x.decode())
+        section = args.section
+        if section in data:
+            width, length, size, bdata = data[section]
+            asize = len(bdata)
+            if size > 0:
+                bdataf = bdata + (size - len(bdata)) * bytearray(b'\x00')
             else:
-                with open(output, 'wb') as of:
-                    of.write(x)
-
-        print(f"Total program size: {len(data)}B")
+                bdataf = bdata
+
+            for i, output in enumerate(outputs):
+
+                y = bdataf[i::len(outputs)]
+                if args.output_type == 'binary':
+                    x = compiler.convert_to_binary(y)
+                elif args.output_type == 'mem':
+                    x = compiler.convert_to_mem(y, width=width)
+                elif args.output_type == 'mif':
+                    x = compiler.convert_to_mif(y, width=width, depth=len(y)/width)
+                elif args.output_type == 'uhex':
+                    x = compiler.convert_to_mem(y, width=width, uhex=True)
+                else:
+                    x = bytes(y)
+
+                op = 'Printing' if args.stdout else 'Saving'
+                print(f"{op} {args.output_type} {section} data '{output}' [Size: {len(y)}B Slice: {format(i + 1, sformat)}/{len(outputs)}]")
+                if args.stdout:
+                    if args.decompile:
+                        print(asmc.decompile(bdata))
+                    else:
+                        print(x.decode())
+                else:
+                    with open(output, 'wb') as of:
+                        of.write(x)
+
+            print(f"Total {section} size: {len(bdata)}B [{len(bdataf)}B]")
+        else:
+            print(f'No such section {section}!')
     else:
         print(f'Failed to compile {args.file}!')
         sys.exit(1)