diff --git a/.gitignore b/.gitignore
index 6d90a58..fa117e2 100644
--- a/.gitignore
+++ b/.gitignore
@@ -8,3 +8,4 @@ cpu/boot_code.txt
cpu/brainfuck.bin
cpu/brainfuck.txt
cpu/memdump.txt
+cpu/memdump.bin
diff --git a/cpu/Makefile b/cpu/Makefile
index 7021585..a82df3c 100644
--- a/cpu/Makefile
+++ b/cpu/Makefile
@@ -22,6 +22,7 @@ VVP=processor.vvp
.PHONY: brainf
brainf: ${VVP} brainfuck.txt
vvp ${VVP} +BOOT_CODE=brainfuck.txt
+ grep -v '^//' memdump.txt | xxd -ps -c 2 -r > memdump.bin
.PHONY: run
run: ${VVP} boot_code.txt
@@ -34,6 +35,7 @@ build: ${VVP}
wave: ${VVP} brainfuck.txt
vvp ${VVP} -lxt2 +BOOT_CODE=brainfuck.txt
gtkwave test.lx2 gtkwave_savefile.gtkw
+ grep -v '^//' memdump.txt | xxd -ps -c 2 -r > memdump.bin
${VVP} : ${SOURCES} ${INCLUDES}
iverilog -g2012 ${SOURCES} -o $@
diff --git a/cpu/gtkwave_savefile.gtkw b/cpu/gtkwave_savefile.gtkw
index 121166e..b54c00f 100644
--- a/cpu/gtkwave_savefile.gtkw
+++ b/cpu/gtkwave_savefile.gtkw
@@ -1,15 +1,15 @@
[*]
[*] GTKWave Analyzer v3.3.104 (w)1999-2020 BSI
-[*] Fri Feb 10 01:43:01 2023
+[*] Tue Feb 14 12:39:46 2023
[*]
[dumpfile] "/home/user/UNI_DATA/COMS30046_2022_TB-2/projects/9086/cpu/test.lx2"
-[dumpfile_mtime] "Fri Feb 10 01:42:12 2023"
-[dumpfile_size] 1058
+[dumpfile_mtime] "Tue Feb 14 12:37:32 2023"
+[dumpfile_size] 1922
[savefile] "/home/user/UNI_DATA/COMS30046_2022_TB-2/projects/9086/cpu/gtkwave_savefile.gtkw"
[timestart] 0
[size] 1438 1059
[pos] -1 -1
-*-21.795050 6163000 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
+*-23.795050 41712000 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
[treeopen] tb.
[treeopen] tb.p.
[sst_width] 221
@@ -19,18 +19,17 @@
@28
tb.p.clock[0]
tb.p.reset[0]
-tb.p.state[3:0]
+tb.p.state[4:0]
@22
tb.p.external_address_bus[19:0]
tb.p.external_data_bus[15:0]
tb.p.CIR[15:0]
-@28
-tb.p.EXCEPTION[0]
-@22
-tb.p.ADDER16_1.A[15:0]
-tb.p.ADDER16_1.B[15:0]
-tb.p.ADDER16_1.OUT[15:0]
+tb.p.PARAM1[15:0]
+tb.p.PARAM2[15:0]
@29
-tb.p.reg_write[0]
+tb.p.read[0]
+@28
+tb.p.write[0]
+tb.p.ERROR[0]
[pattern_trace] 1
[pattern_trace] 0
diff --git a/cpu/memory.v b/cpu/memory.v
index af18550..9f09108 100644
--- a/cpu/memory.v
+++ b/cpu/memory.v
@@ -17,7 +17,7 @@
You should have received a copy of the GNU General Public License
along with this program. If not, see . */
-module rom(input [19:0] address,output wire [15:0] data ,input rd,input cs);
+module mem(input [19:0] address,inout wire [15:0] data ,input rd,input wr,input cs);
reg [15:0] memory [0:599];
initial begin
string boot_code;
@@ -25,5 +25,11 @@ initial begin
boot_code="boot_code.txt";
$readmemh(boot_code, memory);
end
+
assign data = !rd & !cs ? memory[address]: 'hz;
+
+always @(negedge wr) begin
+ memory[address]=data;
+end
+
endmodule
diff --git a/cpu/proc_state_def.v b/cpu/proc_state_def.v
index e21418a..5572fa5 100644
--- a/cpu/proc_state_def.v
+++ b/cpu/proc_state_def.v
@@ -18,26 +18,39 @@
You should have received a copy of the GNU General Public License
along with this program. If not, see . */
-`define PROC_HALT_STATE 4'b0000
+`define PROC_STATE_BITS 5
+
+
+`define PROC_HALT_STATE 5'b00000
/*INSTRUCTION FETCH STATE*/
-`define PROC_IF_STATE_ENTRY 4'b0001
-`define PROC_IF_WRITE_CIR 4'b0010
-`define PROC_IF_STATE_EXTRA_FETCH_SET 4'b0011
-`define PROC_IF_STATE_EXTRA_FETCH 4'b1111 /******/
+`define PROC_IF_STATE_ENTRY 5'b00001
+`define PROC_IF_WRITE_CIR 5'b00010
+`define PROC_IF_STATE_EXTRA_FETCH_SET 5'b00011
+`define PROC_IF_STATE_EXTRA_FETCH 5'b00100
/*DECODE SATE*/
-`define PROC_DE_STATE_ENTRY 4'b0100
-`define PROC_DE_LOAD_16_PARAM 4'b0101
-`define PROC_DE_LOAD_16_EXTRA_FETCH_SET 4'b0110
-`define PROC_DE_LOAD_16_EXTRA_FETCH 4'b0111
+`define PROC_DE_STATE_ENTRY 5'b01000
+`define PROC_DE_LOAD_16_PARAM 5'b01001
+`define PROC_DE_LOAD_16_EXTRA_FETCH_SET 5'b01010
+`define PROC_DE_LOAD_16_EXTRA_FETCH 5'b01011
/*MEM/IO READ*/
-`define RPOC_MEMIO_READ 4'b1100
-`define PROC_MEMIO_SETADDR 4'b1101
-`define PROC_MEMIO_GET_ALIGNED_DATA 4'b1110 /* :) */
-`define PROC_MEMIO_GET_UNALIGNED_DATA 4'b1010 /* :( */
+`define RPOC_MEMIO_READ 5'b10000
+`define PROC_MEMIO_READ_SETADDR 5'b10001
+`define PROC_MEMIO_GET_ALIGNED_DATA 5'b10010 /* :) */
+`define PROC_MEMIO_GET_UNALIGNED_DATA 5'b10011 /* :( */
/*EXECUTE STATE*/
-`define PROC_EX_STATE_ENTRY 4'b1000
-`define PROC_EX_STATE_EXIT 4'b1001
+`define PROC_EX_STATE_ENTRY 5'b11000
+`define PROC_EX_STATE_EXIT 5'b11001
+
+/*MEM/IO WRITE*/
+`define PROC_MEMIO_WRITE 5'b10100
+//`define PROC_MEMIO_WRITE_SETADDR 5'b10101
+`define PROC_MEMIO_PUT_ALIGNED_DATA 5'b10101
+`define PROC_MEMIO_PUT_UNALIGNED_DATA 5'b10110
+`define PROC_MEMIO_PUT_BYTE 5'b10111
+`define PROC_MEMIO_PUT_BYTE_STOP_READ 5'b11110 /****/
+`define PROC_MEMIO_PUT_BYTE_WRITE 5'b11111 /****/
+
diff --git a/cpu/processor.v b/cpu/processor.v
index cfda752..0268145 100644
--- a/cpu/processor.v
+++ b/cpu/processor.v
@@ -34,9 +34,13 @@ endmodule
module processor ( input clock, input reset, output reg [19:0] external_address_bus, inout [15:0] external_data_bus,output reg read, output reg write, output reg HALT,output reg ERROR);
+/*if we don't read, output the register to have the bus stable by the write falling edge*/
+reg [15:0] data_bus_output_register;
+assign external_data_bus=read?data_bus_output_register:'hz;
+
/*** Global Definitions ***/
// State
-reg [3:0] state;
+reg [`PROC_STATE_BITS-1:0] state;
// Registers
reg [19:0] ProgCount;
@@ -44,8 +48,8 @@ reg [15:0] CIR;
reg [15:0] PARAM1;
reg [15:0] PARAM2;
reg unaligned_access;
-reg [1:0]IN_MOD;
-reg [2:0]IN_RM;
+reg [1:0]MOD;
+reg [2:0]RM;
reg Wbit;
reg [15:0]FLAGS;
/* . . . . O D I T S Z . A . P . C */
@@ -69,6 +73,7 @@ reg [15:0]FLAGS;
// D - Direction flag : 1: string instructions decrement 0: they increment
//
// O - Overflow flag : set on arithmetic overflow
+reg [15:0] BYTE_WRITE_TEMP_REG;//we read 16bits here if we want to change just 8 and leave the rest
// Execution units
@@ -91,7 +96,7 @@ always @(negedge reset) begin
@(posedge reset)
@(negedge clock);
state=`PROC_IF_STATE_ENTRY;
- IN_MOD=2'b11;
+ MOD=2'b11;
ERROR=0;
end
end
@@ -134,7 +139,7 @@ ALU ALU(ALU_1A,ALU_1B,ALU_1OE,ALU_1O,ALU_1OP,ALU_FLAGS,Wbit);
/*** Processor stages ***/
-`define invalid_instruction state=`PROC_IF_STATE_ENTRY;ERROR=1;IN_MOD=2'b11;
+`define invalid_instruction state=`PROC_IF_STATE_ENTRY;ERROR=1;MOD=2'b11;
`define start_aligning_instruction if(unaligned_access==0)begin ProgCount=ProgCount+1; external_address_bus <= ProgCount; end /*we normally don't advance PC in case of singly byte unaligning instructions leaving us with two instructions in one read so do that here*/
`define start_unaligning_instruction unaligned_access=~unaligned_access;
@@ -156,6 +161,50 @@ always @(negedge clock) begin
end
`PROC_EX_STATE_EXIT:begin
case(out_sel)
+ 3'b000,
+ 3'b001,
+ 3'b010 : begin
+ case (RM) /* Duplicate code with write... */
+ 3'b000:begin
+ /*[BX]+[SI]*/
+ `invalid_instruction
+ end
+ 3'b001:begin
+ /*[BX]+[SI]*/
+ `invalid_instruction
+ end
+ 3'b010:begin
+ /*[BP]+[SI]*/
+ `invalid_instruction
+ end
+ 3'b011:begin
+ /*[BP]+[DI]*/
+ `invalid_instruction
+ end
+ 3'b100:begin
+ /*[SI]*/
+ reg_read_addr=4'b1110;
+ reg_read_oe=0;
+ state=`PROC_MEMIO_WRITE;
+ end
+ 3'b101:begin
+ /*[DI]*/
+ reg_read_addr=4'b1111;
+ reg_read_oe=0;
+ state=`PROC_MEMIO_WRITE;
+ end
+ 3'b110:begin
+ /*d16 */
+ `invalid_instruction
+ end
+ 3'b111:begin
+ /*[BX]*/
+ reg_read_addr=4'b1011;
+ reg_read_oe=0;
+ state=`PROC_MEMIO_WRITE;
+ end
+ endcase
+ end
3'b011:begin
reg_write_we=0;
state=`PROC_IF_STATE_ENTRY;
@@ -177,10 +226,18 @@ always @(negedge clock) begin
external_address_bus = ProgCount;
state=`PROC_DE_LOAD_16_EXTRA_FETCH;
end
- `PROC_MEMIO_SETADDR:begin
+ `PROC_MEMIO_READ_SETADDR:begin
external_address_bus = {1'b0,reg_read_data[15:1]};
state=reg_read_data[0:0]?`PROC_MEMIO_GET_UNALIGNED_DATA:`PROC_MEMIO_GET_ALIGNED_DATA;
end
+ `PROC_MEMIO_PUT_BYTE:begin
+ BYTE_WRITE_TEMP_REG=external_data_bus;
+ state=`PROC_MEMIO_PUT_BYTE_STOP_READ;
+ end
+ `PROC_MEMIO_PUT_BYTE_WRITE:begin
+ write=0;
+ state=`PROC_IF_STATE_ENTRY;
+ end
endcase
end
@@ -225,7 +282,7 @@ always @(posedge clock) begin
`start_unaligning_instruction
else
`start_aligning_instruction
- IN_MOD=2'b11;
+ MOD=2'b11;
in1_sel=2'b00;
in2_sel=2'b01;
out_sel=3'b011;
@@ -252,7 +309,7 @@ always @(posedge clock) begin
/* 1 0 0 0 0 0 S W | MOD 0 0 0 R/M | < DISP LO > | < DISP HI > | DATA | DATA if W | */
`start_aligning_instruction
Wbit=CIR[8:8];
- IN_MOD=2'b11;
+ MOD=2'b11;
in1_sel=2'b00;
in2_sel=2'b01;
out_sel={1'b0,CIR[7:6]};
@@ -282,7 +339,7 @@ always @(posedge clock) begin
`start_unaligning_instruction
else
`start_aligning_instruction
- IN_MOD=2'b11;
+ MOD=2'b11;
in1_sel=2'b00;
in2_sel=2'b00;
out_sel=3'b011;
@@ -301,7 +358,7 @@ always @(posedge clock) begin
`start_unaligning_instruction
else
`start_aligning_instruction
- IN_MOD=2'b11;
+ MOD=2'b11;
in1_sel=2'b00;
in2_sel=2'b00;
out_sel=3'b011;
@@ -316,13 +373,13 @@ always @(posedge clock) begin
/* MOV - Reg/Mem to/from register */
/* 1 0 0 0 1 0 D W | MOD REG REG | < DISP LO > | < DISP HI > |*/
`start_aligning_instruction
- IN_MOD=CIR[7:6];
- IN_RM=CIR[2:0];
+ MOD=CIR[7:6];
+ RM=CIR[2:0];
Wbit=CIR[8:8];
if(CIR[9:9] == 1)begin
/* to reg */
- IN_MOD=CIR[7:6];
- if(IN_MOD==2'b11)begin
+ MOD=CIR[7:6];
+ if(MOD==2'b11)begin
in1_sel=2'b01;
reg_read_addr=CIR[2:0];
end else begin
@@ -339,7 +396,7 @@ always @(posedge clock) begin
ALU_1OP=`ALU_OP_ADD;
PARAM2=0;
state=`PROC_DE_LOAD_16_PARAM;
- if ( IN_MOD == 2'b11 )
+ if ( MOD == 2'b11 )
state=`PROC_EX_STATE_ENTRY;
else
state=`RPOC_MEMIO_READ;
@@ -357,7 +414,7 @@ always @(posedge clock) begin
in1_sel=2'b01;
in2_sel=2'b00;
out_sel=3'b011;
- IN_MOD=2'b11;
+ MOD=2'b11;
PARAM2=1;
reg_read_addr={1'b1,CIR[10:8]};
reg_write_addr={1'b1,CIR[10:8]};
@@ -378,14 +435,18 @@ always @(posedge clock) begin
/* 1 1 1 1 1 1 1 W | MOD 0 0 0 R/M | < DISP LO> | < DISP HI> */
`start_aligning_instruction
Wbit=CIR[8:8];
- IN_MOD=CIR[7:6];
- in1_sel=2'b00;/* number 1 */
- in2_sel=(CIR[7:6]==2'b11)? 2'b01 : 2'b00;
- out_sel={1'b0,CIR[7:6]};
- PARAM1=1;
- reg_read_addr={1'b0,CIR[2:0]};
- reg_write_addr={1'b0,CIR[2:0]};
+ MOD=CIR[7:6];
+ RM=CIR[2:0];
+ in1_sel=(MOD==2'b11)? 2'b01 : 2'b00;
+ in2_sel=2'b00;/* number 1 */
+ out_sel={1'b0,MOD};
+ PARAM2=1;
+
+ /*in case MOD=11 */
+ reg_read_addr={1'b0,RM};
+ reg_write_addr={1'b0,RM};
reg_read_oe=0;
+
ALU_1OE=0;
ALU_1OP=`ALU_OP_ADD;
if ( CIR[7:6] == 2'b11 )
@@ -408,7 +469,7 @@ always @(posedge clock) begin
/* HLT - Halt */
/* 1 1 1 1 0 1 0 0 | */
`start_unaligning_instruction
- IN_MOD=2'b11;
+ MOD=2'b11;
HALT=1;
state=`PROC_HALT_STATE;
end
@@ -430,7 +491,7 @@ always @(posedge clock) begin
`start_unaligning_instruction
else
`start_aligning_instruction
- IN_MOD=2'b11;
+ MOD=2'b11;
in1_sel=2'b00;
in2_sel=2'b01;
reg_read_addr={CIR[8:8],3'b000};
@@ -530,7 +591,7 @@ always @(posedge clock) begin
end
`RPOC_MEMIO_READ:begin
/*Decode MOD R/M, read the data and place it to PARAM1*/
- case (IN_RM)
+ case (RM)
3'b000:begin
/*[BX]+[SI]*/
`invalid_instruction
@@ -551,13 +612,13 @@ always @(posedge clock) begin
/*[SI]*/
reg_read_addr=4'b1110;
reg_read_oe=0;
- state=`PROC_MEMIO_SETADDR;
+ state=`PROC_MEMIO_READ_SETADDR;
end
3'b101:begin
/*[DI]*/
reg_read_addr=4'b1111;
reg_read_oe=0;
- state=`PROC_MEMIO_SETADDR;
+ state=`PROC_MEMIO_READ_SETADDR;
end
3'b110:begin
/*d16 */
@@ -567,10 +628,10 @@ always @(posedge clock) begin
/*[BX]*/
reg_read_addr=4'b1011;
reg_read_oe=0;
- state=`PROC_MEMIO_SETADDR;
+ state=`PROC_MEMIO_READ_SETADDR;
end
endcase
- if(IN_MOD!=2'b00)begin
+ if(MOD!=2'b00)begin
/*Actually check if 01 and add the 8bits or if 10 add the 16bits ....*/
`invalid_instruction;
end
@@ -593,6 +654,18 @@ always @(posedge clock) begin
FLAGS[7:0] = ALU_FLAGS[7:0];
state=`PROC_EX_STATE_EXIT;
end
+ `PROC_MEMIO_WRITE:begin
+ external_address_bus = {1'b0,reg_read_data[15:1]};
+ state = (Wbit==0) ? `PROC_MEMIO_PUT_BYTE : (reg_read_data[0:0]?`PROC_MEMIO_PUT_UNALIGNED_DATA:`PROC_MEMIO_PUT_ALIGNED_DATA) ;
+ end
+ `PROC_MEMIO_PUT_BYTE_STOP_READ:begin
+ read=1;
+ state=`PROC_MEMIO_PUT_BYTE_WRITE;
+ if(reg_read_data[0:0]==0)
+ data_bus_output_register={ALU_1O[7:0],BYTE_WRITE_TEMP_REG[7:0]};
+ else
+ data_bus_output_register={BYTE_WRITE_TEMP_REG[15:8],ALU_1O[7:0]};
+ end
endcase
end
diff --git a/cpu/testbench.v b/cpu/testbench.v
index 098e175..508f0e0 100644
--- a/cpu/testbench.v
+++ b/cpu/testbench.v
@@ -29,7 +29,7 @@ wire rd,wr,romcs,HALT;
wire ERROR;
processor p(clock,reset,address_bus,data_bus,rd,wr,HALT,ERROR);
-rom bootrom(address_bus,data_bus,rd,romcs);
+mem sysmem(address_bus,data_bus,rd,wr,romcs);
`define CPU_SPEED 1000
@@ -51,7 +51,7 @@ end
always @(posedge HALT) begin
$display("Processor halted.\nCycles run for: %d",cycles);
- $writememh("memdump.txt", bootrom.memory);
+ $writememh("memdump.txt", sysmem.memory);
#(`CPU_SPEED) //Just for the waveform
$finish;
end
@@ -59,7 +59,7 @@ end
always @(posedge ERROR) begin
clk_enable <= 0;
$display("PROCESSOR RUN INTO AN ERROR.\nCycles run for: %d",cycles);
- $writememh("memdump.txt", bootrom.memory);
+ $writememh("memdump.txt", sysmem.memory);
#(`CPU_SPEED) //Just for the waveform
$finish;
end