Added support for writing to memory
This commit is contained in:
parent
7c1067088c
commit
037f6dd7da
1
.gitignore
vendored
1
.gitignore
vendored
@ -8,3 +8,4 @@ cpu/boot_code.txt
|
||||
cpu/brainfuck.bin
|
||||
cpu/brainfuck.txt
|
||||
cpu/memdump.txt
|
||||
cpu/memdump.bin
|
||||
|
@ -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 $@
|
||||
|
@ -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
|
||||
|
@ -17,7 +17,7 @@
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
||||
|
||||
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
|
||||
|
@ -18,26 +18,39 @@
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
||||
|
||||
`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 /****/
|
||||
|
||||
|
133
cpu/processor.v
133
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
|
||||
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user