5 Commits

11 changed files with 299 additions and 272 deletions

View File

@@ -1,13 +1,13 @@
// memory data file (do not edit the following line - required for mem load use)
// instance=/DA_VINCI_TB/da_vinci_inst/memory_inst/memory_inst/sram_32x64m
// format=hex addressradix=h dataradix=h version=1.0 wordsperline=1 noaddress
00000000
00000000
00000000
00000000
00000000
00000000
00000000
00000000
00000000
00000000
00000020
00000020
00000010
00000010
00000009
00000008
00000008
00000005
00000004
00000002

View File

@@ -6,4 +6,4 @@
00000004
00000010
00000010
00000040
00000000

View File

@@ -2,8 +2,8 @@
// instance=/DA_VINCI_TB/da_vinci_inst/memory_inst/memory_inst/sram_32x64m
// format=hex addressradix=h dataradix=h version=1.0 wordsperline=1 noaddress
00000000
00000000
00000000
00000000
00000000
00000200
00000020
00000008
00000008
00000002
00000002

View File

@@ -1,14 +1,14 @@
// memory data file (do not edit the following line - required for mem load use)
// instance=/DA_VINCI_TB/da_vinci_inst/memory_inst/memory_inst/sram_32x64m
// format=hex addressradix=h dataradix=h version=1.0 wordsperline=1 noaddress
00090001
00090003
00090005
00090007
00090009
0009000b
0009000d
0009000f
00090011
00090013
00090015
00000015
00000017
00000019
0000001b
0000001d
0000001f
00000021
00000023
00000025
00000025
00000000

View File

@@ -1,19 +1,19 @@
// memory data file (do not edit the following line - required for mem load use)
// instance=/DA_VINCI_TB/da_vinci_inst/memory_inst/memory_inst/sram_32x64m
// format=hex addressradix=h dataradix=h version=1.0 wordsperline=1 noaddress
ffffffc9
00000022
ffffffeb
0000000d
fffffff8
00000005
fffffffd
00000002
ffffffff
00000001
00000000
00000000
00000000
00000000
00000000
00000000
00000000
00000000
00000000
00000000
00000000
00000000
00000000
00000000
00000000
00000059
00000001
00000001
00000002
00000003
00000005

View File

@@ -0,0 +1,21 @@
// memory data file (do not edit the following line - required for mem load use)
// instance=/DA_VINCI_TB/da_vinci_inst/memory_inst/memory_inst/sram_32x64m
// format=hex addressradix=h dataradix=h version=1.0 wordsperline=1 noaddress
00001337
000039a5
00002024
0000335b
fffff313
00000ced
026993bc
00000024
00003337
ffffccc8
00000001
00000000
00013370
00000133
000039a5
00000005
00000005
fffff313

View File

@@ -0,0 +1,9 @@
// memory data file (do not edit the following line - required for mem load use)
// instance=/DA_VINCI_TB/da_vinci_inst/memory_inst/memory_inst/sram_32x64m
// format=hex addressradix=h dataradix=h version=1.0 wordsperline=1 noaddress
00000000
00000000
00000000
00000000
00000000
00001337

View File

@@ -30,7 +30,8 @@ wire [`DATA_INDEX_LIMIT:0] MEM_DATA_OUT, MEM_DATA_IN;
// reset
reg RST;
integer t1=1, t2=1, t3=1, t4=1, t5=1;
integer t1=1, t2=1, t3=1, t4=1, t5=1, t6=1;
//integer t1=0, t2=0, t3=0, t4=0, t5=0, t6=1;
// Clock generator instance
CLK_GENERATOR clk_gen_inst(.CLK(CLK));
@@ -129,6 +130,23 @@ begin
$writememh("./OUTPUT/CS147_SP15_HW01_02_mem_dump_01.dat", da_vinci_inst.memory_inst.memory_inst.sram_32x64m, 'h00048000, 'h00048005);
$writememh("./OUTPUT/CS147_SP15_HW01_02_mem_dump_02.dat", da_vinci_inst.memory_inst.memory_inst.sram_32x64m, `INIT_STACK_POINTER - 5, `INIT_STACK_POINTER);
/* END : test 5*/
end
if (t6 === 1)
begin
/* START : test 6*/
#5 RST=1'b0;
#5 RST=1'b1;
$write("\n");
$write("===> Simulating all_test.dat\n", "");
$write("\n");
$readmemh("./TESTPROGRAM/all_test.dat", da_vinci_inst.memory_inst.memory_inst.sram_32x64m);
#5000 $write("\n");
$write("===> Done simulating all_test.dat\n", "");
$write("\n");
$writememh("./OUTPUT/all_test_mem_dump_01.dat", da_vinci_inst.memory_inst.memory_inst.sram_32x64m, 'h00048000, 'h00048011);
$writememh("./OUTPUT/all_test_mem_dump_02.dat", da_vinci_inst.memory_inst.memory_inst.sram_32x64m, `INIT_STACK_POINTER - 5, `INIT_STACK_POINTER);
/* END : test 6*/
end
$stop;

49
TESTPROGRAM/all_test.dat Normal file
View File

@@ -0,0 +1,49 @@
@0001000
20001337 // addi r0, r0, 0x1337
6c000000 // push
3c1e0004 // lui r30, 0x0004
37de8000 // ori r30, r30 0x00008000
afc00000 // sw r0, r30, 0x0
0c001014 // jal 0x00001014
70000000 // pop
20212024 // addi r1, r1, 0x2024
00011020 // add r2, r0, r1
00011822 // sub r3, r0, r1
00202022 // sub r4, r1, r0
0001282c // mul r5, r0, r1
00013024 // and r6, r0, r1
00013825 // or r7, r0, r1
00014027 // nor r8, r0, r1
0001482a // slt r9, r0, r1
0020502a // slt r10, r1, r0
00005901 // sll r11, r0, 4
00006102 // srl r12, r0, 4
08001017 // jmp 0x00001017
74000003 // muli r0, r0, 3
afc00001 // sw r0, r30, 0x1
03e00008 // jr r31
8fcd0001 // lw r13, r30, 0x1
29ae1338 // slti r14, r13, 0x1338
302f0000 // andi r15, r1, 0x0
21ef0005 // addi r15, r15, 0x5
11ee0002 // beq r14, r15, 0x2
21ce0001 // addi r14, r14, 0x1
0800101b // jmp 0x0000101b
afc10002 // sw r1, r30, 0x2
afc20003 // sw r2, r30, 0x3
afc30004 // sw r3, r30, 0x4
afc40005 // sw r4, r30, 0x5
afc50006 // sw r5, r30, 0x6
afc60007 // sw r6, r30, 0x7
afc70008 // sw r7, r30, 0x8
afc80009 // sw r8, r30, 0x9
afc9000a // sw r9, r30, 0x0a
afca000b // sw r10, r30, 0x0b
afcb000c // sw r11, r30, 0x0c
afcc000d // sw r12, r30, 0x0d
afcd000e // sw r13, r30, 0x0e
afce000f // sw r14, r30, 0x0f
afcf0010 // sw r15, r30, 0x10
2210fbb1 // addi r16, r16, 0xfbb1
1470fffe // bne r16, r3, 0xfffe
afd00011 // sw r16, r30, 0x11

View File

@@ -19,7 +19,7 @@
//------------------------------------------------------------------------------------------
`include "prj_definition.v"
// Control signals, same as in data_path.v
// Control signals, referenced in data_path.v
`define pc_load 0
`define pc_sel_1 1
`define pc_sel_2 2
@@ -105,74 +105,69 @@ output READ, WRITE;
input ZERO, CLK, RST;
input [`DATA_INDEX_LIMIT:0] INSTRUCTION;
// Task to print instruction
task print_instruction;
input [`DATA_INDEX_LIMIT:0] inst;
reg [5:0] opcode2;
reg [4:0] rs2;
reg [4:0] rt2;
reg [4:0] rd2;
reg [4:0] shamt2;
reg [5:0] funct2;
reg [15:0] immediate2;
reg [25:0] address2;
reg [5:0] opcode;
reg [4:0] rs;
reg [4:0] rt;
reg [4:0] rd;
reg [4:0] shamt;
reg [5:0] funct;
reg [15:0] imm;
reg [25:0] addr;
begin
// parse the instruction
// R-type
{opcode2, rs2, rt2, rd2, shamt2, funct2} = inst;
{opcode, rs, rt, rd, shamt, funct} = inst;
// I-type
{opcode2, rs2, rt2, immediate2 } = inst;
{opcode, rs, rt, imm} = inst;
// J-type
{opcode2, address2} = inst;
{opcode, addr} = inst;
$write("@ %6dns -> [0X%08h] ", $time, inst);
case(opcode2)
// R-Type
6'h00 : begin
case(funct2)
6'h20: $write("add r[%02d], r[%02d], r[%02d];", rd2, rs2, rt2);
6'h22: $write("sub r[%02d], r[%02d], r[%02d];", rd2, rs2, rt2);
6'h2c: $write("mul r[%02d], r[%02d], r[%02d];", rd2, rs2, rt2);
6'h24: $write("and r[%02d], r[%02d], r[%02d];", rd2, rs2, rt2);
6'h25: $write("or r[%02d], r[%02d], r[%02d];", rd2, rs2, rt2);
6'h27: $write("nor r[%02d], r[%02d], r[%02d];", rd2, rs2, rt2);
6'h2a: $write("slt r[%02d], r[%02d], r[%02d];", rd2, rs2, rt2);
6'h01: $write("sll r[%02d], r[%02d], %2d;", rd2, rs2, shamt2);
6'h02: $write("srl r[%02d], 0X%02h, r[%02d];", rd2, rs2, shamt2);
6'h08: $write("jr r[%02d];", rs2);
case(opcode)
// R-Type
`OP_RTYPE: case(funct)
`FN_ADD: $write("add r[%02d], r[%02d], r[%02d];", rd, rs, rt);
`FN_SUB: $write("sub r[%02d], r[%02d], r[%02d];", rd, rs, rt);
`FN_MUL: $write("mul r[%02d], r[%02d], r[%02d];", rd, rs, rt);
`FN_AND: $write("and r[%02d], r[%02d], r[%02d];", rd, rs, rt);
`FN_OR: $write("or r[%02d], r[%02d], r[%02d];", rd, rs, rt);
`FN_NOR: $write("nor r[%02d], r[%02d], r[%02d];", rd, rs, rt);
`FN_SLT: $write("slt r[%02d], r[%02d], r[%02d];", rd, rs, rt);
`FN_SLL: $write("sll r[%02d], r[%02d], %2d;", rd, rs, shamt);
`FN_SRL: $write("srl r[%02d], 0X%02h, r[%02d];", rd, rs, shamt);
`FN_JR: $write("jr r[%02d];", rs);
default: $write("");
endcase
end
// I-type
6'h08 : $write("addi r[%02d], r[%02d], 0X%04h;", rt2, rs2, immediate2);
6'h1d : $write("muli r[%02d], r[%02d], 0X%04h;", rt2, rs2, immediate2);
6'h0c : $write("andi r[%02d], r[%02d], 0X%04h;", rt2, rs2, immediate2);
6'h0d : $write("ori r[%02d], r[%02d], 0X%04h;", rt2, rs2, immediate2);
6'h0f : $write("lui r[%02d], 0X%04h;", rt2, immediate2);
6'h0a : $write("slti r[%02d], r[%02d], 0X%04h;", rt2, rs2, immediate2);
6'h04 : $write("beq r[%02d], r[%02d], 0X%04h;", rt2, rs2, immediate2);
6'h05 : $write("bne r[%02d], r[%02d], 0X%04h;", rt2, rs2, immediate2);
6'h23 : $write("lw r[%02d], r[%02d], 0X%04h;", rt2, rs2, immediate2);
6'h2b : $write("sw r[%02d], r[%02d], 0X%04h;", rt2, rs2, immediate2);
`OP_ADDI: $write("addi r[%02d], r[%02d], 0X%04h;", rt, rs, imm);
`OP_MULI: $write("muli r[%02d], r[%02d], 0X%04h;", rt, rs, imm);
`OP_ANDI: $write("andi r[%02d], r[%02d], 0X%04h;", rt, rs, imm);
`OP_ORI: $write("ori r[%02d], r[%02d], 0X%04h;", rt, rs, imm);
`OP_LUI: $write("lui r[%02d], 0X%04h;", rt, imm);
`OP_SLTI: $write("slti r[%02d], r[%02d], 0X%04h;", rt, rs, imm);
`OP_BEQ: $write("beq r[%02d], r[%02d], 0X%04h;", rt, rs, imm);
`OP_BNE: $write("bne r[%02d], r[%02d], 0X%04h;", rt, rs, imm);
`OP_LW: $write("lw r[%02d], r[%02d], 0X%04h;", rt, rs, imm);
`OP_SW: $write("sw r[%02d], r[%02d], 0X%04h;", rt, rs, imm);
// J-Type
6'h02 : $write("jmp 0X%07h;", address2);
6'h03 : $write("jal 0X%07h;", address2);
6'h1b : $write("push;");
6'h1c : $write("pop;");
`OP_JMP: $write("jmp 0X%07h;", addr);
`OP_JAL: $write("jal 0X%07h;", addr);
`OP_PUSH: $write("push;");
`OP_POP: $write("pop;");
default: $write("");
endcase
$write("\n");
end
endtask
//------------------------------------- END ---------------------------------------//
reg read, write;
buf (READ, read);
buf (WRITE, write);
//assign READ = read;
//assign WRITE = write;
reg [31:0] C;
@@ -192,7 +187,7 @@ reg [25:0] addr;
wire [2:0] state;
PROC_SM proc_sm(state, CLK, RST);
// TBD - take action on each +ve edge of clock
// take action on each +ve edge of clock
always @ (state) begin
// R-type
{opcode, rs, rt, rd, shamt, funct} = INSTRUCTION;
@@ -201,19 +196,6 @@ always @ (state) begin
// J-type
{opcode, addr} = INSTRUCTION;
// Print current state
// $write("@ %6dns -> ", $time);
// $write("STATE ", state, ": ");
// case (state)
// `PROC_FETCH: $write("FETCH");
// `PROC_DECODE: $write("DECODE");
// `PROC_EXE: $write("EXECUTE");
// `PROC_MEM: $write("MEMORY");
// `PROC_WB: $write("WRITE BACK");
// default: $write("INVALID");
// endcase
// $write("\n");
case (state)
// fetch - next instruction from memory at PC
`PROC_FETCH: begin
@@ -222,12 +204,13 @@ always @ (state) begin
// memory
read = 1'b1;
write = 1'b0;
// selections
C[`ma_sel_2] = 1'b1; // load data from mem[PC]
// ma_sel_2: load data from mem[PC]
C[`ma_sel_2] = 1'b1;
end
// decode - parse instruction and read values from register file
`PROC_DECODE: begin
// loaded in previous state, set to 0
C[`ma_sel_2] = 1'b0;
read = 1'b0;
// load now
C[`ir_load] = 1'b1;
@@ -238,27 +221,30 @@ always @ (state) begin
print_instruction(INSTRUCTION);
// loaded in previous state, set to 0
C[`ir_load] = 1'b0;
// selections
// r1_sel_1: push - store value of r0 at stack pointer
C[`r1_sel_1] = opcode != 6'h1b ? 1'b0 : 1'b1;
// wa_sel_1: R-type - write to rd, I-type - write to rt
C[`wa_sel_1] = opcode == 6'h00 ? 1'b0 : 1'b1;
// wa_sel_2: jal - write to r31, pop - write to r0
C[`wa_sel_2] = opcode == 6'h03 ? 1'b1 : 1'b0;
// wa_sel_3: push or pop - wa_sel_2, else wa_sel_1
C[`wa_sel_3] = opcode == 6'h03 || opcode == 6'h1c ? 1'b0 : 1'b1;
// jr - jump to address in register
C[`pc_sel_1] = opcode == 6'h00 && funct == 6'h08 ? 1'b0 : 1'b1;
// beq, bne - branch if equal or not equal
// TODO: this should only be selected if the condition is met
// pc_sel_2 = opcode == 6'h04 || opcode == 6'h05 ? 1'b1 : 1'b0;
// jmp, jal - jump to address
C[`pc_sel_3] = opcode == `OP_JMP || opcode == `OP_JAL ? 1'b0 : 1'b1;
// load now - sp is incremented before pop
C[`sp_load] = opcode == `OP_POP;
// r1_sel_1: rs by default (0), push - r1 (1)
C[`r1_sel_1] = opcode == `OP_PUSH;
// wa_sel_1: R-type - write to rd (0), I-type - write to rt (1)
C[`wa_sel_1] = opcode != `OP_RTYPE;
// wa_sel_2: pop - write to r0 (0), jal - write to r31 (1)
C[`wa_sel_2] = opcode == `OP_JAL;
// wa_sel_3: wa_sel_2 if push or pop or jal (0), else wa_sel_1 (1)
C[`wa_sel_3] = ~(opcode == `OP_PUSH || opcode == `OP_POP || opcode == `OP_JAL);
// pc_sel_1: jr - jump to address in rs (0), else pc_inc (1)
C[`pc_sel_1] = ~(opcode == `OP_RTYPE && funct == `FN_JR);
// pc_sel_2: pc_sel_1 by default (0), beq, bne - branch if equal or not equal (1)
// pc_sel_2 is set after EXE because it depends on ZERO
// pc_sel_3: jmp or jal - jump to address (0), else pc_sel_2 (1)
C[`pc_sel_3] = ~(opcode == `OP_JMP || opcode == `OP_JAL);
// alu_oprn - operation to be performed by ALU
case (opcode)
// R-type
if (opcode == `OP_RTYPE) begin
case (funct)
`OP_RTYPE: case (funct)
`FN_ADD: C[`alu_oprn] = `ALU_ADD;
`FN_SUB: C[`alu_oprn] = `ALU_SUB;
`FN_MUL: C[`alu_oprn] = `ALU_MUL;
@@ -270,10 +256,6 @@ always @ (state) begin
`FN_SLT: C[`alu_oprn] = `ALU_SLT;
default: C[`alu_oprn] = `ALU_NOP;
endcase
end
// I-type and J-type
else begin
case (opcode)
// I-type
`OP_ADDI: C[`alu_oprn] = `ALU_ADD; // addi
`OP_MULI: C[`alu_oprn] = `ALU_MUL; // muli
@@ -289,69 +271,64 @@ always @ (state) begin
`OP_POP: C[`alu_oprn] = `ALU_ADD; // pop - add
default: C[`alu_oprn] = `ALU_NOP;
endcase
end
// op1_sel_1 - select r1 or sp based on opcode
// push or pop - sp, else r1
C[`op1_sel_1] = opcode == 6'h1b || opcode == 6'h1c ? 1'b1 : 1'b0;
// op2_sel_1 - select 1 or shamt based on alu_oprn
// sll or srl - shamt, else 1 (for increments/decrements)
C[`op2_sel_1] = C[`alu_oprn] == 6'h04 || C[`alu_oprn] == 6'h05 ? 1'b1 : 1'b0;
// op2_sel_2 - select imm_zx or imm_sx based on alu_oprn
// logical (and, or) - imm_zx, else imm_sx; ('nor' not availble in I-type)
C[`op2_sel_2] = C[`alu_oprn] == 6'h06 || C[`alu_oprn] == 6'h07 ? 1'b0 : 1'b1;
// op2_sel_3 - select op2_sel_2 or op2_sel_1 based on alu_oprn
// R-type - op2_sel_1, I-type - op2_sel_2
C[`op2_sel_3] = opcode == 6'h00 ? 1'b1 : 1'b0;
// op2_sel_4 - select op2_sel_3 or r2
// I-type or shift or inc/dec - op2_sel_3, else r2
// i.e. r2 only if R-type and not shift
C[`op2_sel_4] = opcode != 6'h00 || C[`alu_oprn] == 6'h04 || C[`alu_oprn] == 6'h05 ? 1'b0 : 1'b1;
// wd_sel_1 - alu_out or DATA_IN
C[`wd_sel_1] = 1'b0;
// wd_sel_2 - wd_sel_1 or imm_zx_lsb
// lui - imm_zx_lsb, else wd_sel_1
C[`wd_sel_2] = opcode == 6'h0f ? 1'b1 : 1'b0;
// wd_sel_3 - pc_inc or wd_sel_2
// jal - pc_inc, else wd_sel_2
C[`wd_sel_3] = opcode == 6'h03 ? 1'b0 : 1'b1;
// ma_sel_1 - alu_out for lw or sw, sp for push or pop
C[`ma_sel_1] = opcode == `OP_LW || opcode == `OP_SW ? 1'b0 : 1'b1;
// ma_sel_2 - 1 for pc, 0 for everything else
C[`ma_sel_2] = opcode == `OP_LW || opcode == `OP_SW || opcode == `OP_PUSH || opcode == `OP_POP ? 1'b0 : 1'b1;
// md_sel_1 - r1 for push, r2 for sw
C[`md_sel_1] = opcode == 6'h1b ? 1'b1 : 1'b0;
// op1_sel_1: r1 by default (0), push or pop - sp (1)
C[`op1_sel_1] = opcode == `OP_PUSH || opcode == `OP_POP;
// op2_sel_1: const 1 (for inc/dec) (0), shamt for sll/srl (1)
C[`op2_sel_1] = opcode == `OP_RTYPE && (funct == `FN_SLL || funct == `FN_SRL);
// op2_sel_2: imm_zx for logical and/or (0), imm_sx otherise (1)
// ('nor' not availble in I-type)
C[`op2_sel_2] = ~(opcode == `OP_ANDI || opcode == `OP_ORI);
// op2_sel_3: op2_sel_2 for I-type (0), op2_sel_1 for R-type shift or inc/dec (1)
// (inc/dec is for sp with pop or push)
C[`op2_sel_3] = opcode == `OP_RTYPE || opcode == `OP_PUSH || opcode == `OP_POP;
// op2_sel_4: op2_sel_3 for I-type (except beq, bne) or R-type shift or inc/dec (0), else r2 (1)
// i.e. r2 if R-type (except sll/srl), or bne/beq
C[`op2_sel_4] = opcode == `OP_RTYPE && ~(funct == `FN_SLL || funct == `FN_SRL)
|| opcode == `OP_BEQ || opcode == `OP_BNE;
// wd_sel_1: alu_out by default (0), DATA_IN for lw or pop (1)
C[`wd_sel_1] = opcode == `OP_LW || opcode == `OP_POP;
// wd_sel_2: wd_sel_1 by default (0), imm_zx_lsb for lui (1)
C[`wd_sel_2] = opcode == `OP_LUI;
// wd_sel_3: pc_inc for jal (0), else wd_sel_2 (1)
C[`wd_sel_3] = ~(opcode == `OP_JAL);
// ma_sel_1: alu_out for lw or sw (0), sp for push or pop (1)
C[`ma_sel_1] = opcode == `OP_PUSH || opcode == `OP_POP;
// ma_sel_2: 0 for every memory access instruction (lw, sw, push, pop), 1 for fetch
C[`ma_sel_2] = 1'b0;
// md_sel_1: r2 for sw (0), r1 for push (1)
C[`md_sel_1] = opcode == `OP_PUSH;
end
`PROC_MEM: begin
// load now
// loaded in previous state, set to 0
C[`sp_load] = 1'b0;
// push or sw - write to memory
if (opcode == `OP_PUSH || opcode == `OP_SW) begin
read = 1'b0;
write = 1'b1;
end
else begin
// read = 1'b1;
// write = 1'b0;
end
write = opcode == `OP_PUSH || opcode == `OP_SW;
// pop or lw - read from memory
read = opcode == `OP_POP || opcode == `OP_LW;
end
`PROC_WB: begin
// loaded in previous state, set to 0
read = 1'b0;
write = 1'b0;
// load now
// pc gets next instruction address
C[`pc_load] = 1'b1;
// sp is decremented after push
C[`sp_load] = opcode == `OP_PUSH;
// write to register file if
// R-type (except jr) or I-type (except beq, bne, sw) or pop or jal
C[`reg_w] = (opcode == 6'h00 && funct != 6'h08) // R-type (except jr)
|| (opcode == 6'h08 || opcode == 6'h1d || opcode == 6'h0c || opcode == 6'h0d
|| opcode == 6'h0f || opcode == 6'h0a || opcode == 6'h23) // I-type (except beq, bne, sw)
|| (opcode == 6'h1c || opcode == 6'h03) // pop or jal
? 1'b1 : 1'b0;
// selections
// pc_sel_2 - branch if equal or not equal
C[`pc_sel_2] = (opcode == 6'h04 && ZERO) || (opcode == 6'h05 && ~ZERO) ? 1'b1 : 1'b0;
C[`reg_w] = (opcode == `OP_RTYPE && funct != `FN_JR) // R-type (except jr)
|| (opcode == `OP_ADDI || opcode == `OP_MULI || opcode == `OP_ANDI || opcode == `OP_ORI
|| opcode == `OP_LUI || opcode == `OP_SLTI || opcode == `OP_LW) // I-type (except beq, bne, sw)
|| (opcode == `OP_POP || opcode == `OP_JAL) // pop or jal
;
// pc_sel_2: branch if equal or not equal
C[`pc_sel_2] = ((opcode == `OP_BEQ) && ZERO) || ((opcode == `OP_BNE) && ~ZERO);
end
endcase
end
@@ -389,7 +366,7 @@ always @ (negedge RST) begin
state_sel = 3'bxxx;
end
// TBD - take action on each +ve edge of clock
// take action on each +ve edge of clock
always @ (posedge CLK) begin
case (state_sel)
`PROC_FETCH: state_sel = `PROC_DECODE;

View File

@@ -17,6 +17,7 @@
//------------------------------------------------------------------------------------------
//
`include "prj_definition.v"
`include "control_unit.v" // for control signal index macros
module DATA_PATH(DATA_OUT, ADDR, ZERO, INSTRUCTION, DATA_IN, CTRL, CLK, RST);
// output list
@@ -29,53 +30,6 @@ input [`CTRL_WIDTH_INDEX_LIMIT:0] CTRL;
input CLK, RST;
input [`DATA_INDEX_LIMIT:0] DATA_IN;
wire pc_load, pc_sel_1, pc_sel_2, pc_sel_3,
ir_load, reg_r, reg_w,
r1_sel_1, wa_sel_1, wa_sel_2, wa_sel_3,
sp_load, op1_sel_1,
op2_sel_1, op2_sel_2, op2_sel_3, op2_sel_4,
wd_sel_1, wd_sel_2, wd_sel_3,
ma_sel_1, ma_sel_2,
md_sel_1;
wire [5:0] alu_oprn;
buf (pc_load, CTRL[0]);
buf (pc_sel_1, CTRL[1]);
buf (pc_sel_2, CTRL[2]);
buf (pc_sel_3, CTRL[3]);
buf (ir_load, CTRL[4]);
buf (r1_sel_1, CTRL[5]);
buf (reg_r, CTRL[6]);
buf (reg_w, CTRL[7]);
buf (sp_load, CTRL[8]);
buf (op1_sel_1, CTRL[9]);
buf (op2_sel_1, CTRL[10]);
buf (op2_sel_2, CTRL[11]);
buf (op2_sel_3, CTRL[12]);
buf (op2_sel_4, CTRL[13]);
buf alu_oprn_buf [5:0] (alu_oprn, CTRL[19:14]);
buf (ma_sel_1, CTRL[20]);
buf (ma_sel_2, CTRL[21]);
buf (md_sel_1, CTRL[22]);
buf (wd_sel_1, CTRL[23]);
buf (wd_sel_2, CTRL[24]);
buf (wd_sel_3, CTRL[25]);
buf (wa_sel_1, CTRL[26]);
buf (wa_sel_2, CTRL[27]);
buf (wa_sel_3, CTRL[28]);
// variables
wire [31:0] ir; // Instruction Register
wire [31:0] r1, r2; // Register File
@@ -83,7 +37,7 @@ wire [31:0] pc, pc_inc; // Program Counter
wire [31:0] sp; // Stack Pointer
wire [31:0] alu_out; // ALU output
// TODO: Why?
// instruction sent to control unit
buf ir_buf [31:0] (INSTRUCTION, ir);
// Parse the instruction data
@@ -110,27 +64,26 @@ buf imm_buf [15:0] (imm, ir[15:0]);
// for J-type
buf addr_buf [25:0] (addr, ir[25:0]);
// Instruction Register input
// Instruction Register
D_LATCH32 ir_inst(.Q(ir), .D(DATA_IN), .LOAD(ir_load), .RESET(RST));
D_LATCH32 ir_inst(.Q(ir), .D(DATA_IN), .LOAD(CTRL[`ir_load]), .RESET(RST));
// Register File Input
wire [31:0] r1_sel, wa_sel, wd_sel;
wire [31:0] wa_sel_p1, wa_sel_p2, wd_sel_p1, wd_sel_p2;
wire [31:0] imm_zx_lsb;
buf imm_zx_lsb_buf [31:0] (imm_zx_lsb, {imm, 16'b0});
MUX32_2x1 mux_r1_sel(r1_sel, {27'b0,rs}, 32'b0, r1_sel_1);
MUX32_2x1 mux_wa_sel_p1(wa_sel_p1, {27'b0,rd}, {27'b0,rt}, wa_sel_1);
// TODO: Why 31?
MUX32_2x1 mux_wa_sel_p2(wa_sel_p2, 32'b0, 31, wa_sel_2);
MUX32_2x1 mux_wa_sel(wa_sel, wa_sel_p2, wa_sel_p1, wa_sel_3);
MUX32_2x1 mux_wd_sel_p1(wd_sel_p1, alu_out,DATA_IN, wd_sel_1);
MUX32_2x1 mux_wd_sel_p2(wd_sel_p2, wd_sel_p1, imm_zx_lsb, wd_sel_2);
MUX32_2x1 mux_wd_sel(wd_sel, pc_inc, wd_sel_p2, wd_sel_3);
MUX32_2x1 mux_r1_sel(r1_sel, {27'b0,rs}, 32'b0, CTRL[`r1_sel_1]);
MUX32_2x1 mux_wa_sel_p1(wa_sel_p1, {27'b0,rd}, {27'b0,rt}, CTRL[`wa_sel_1]);
// 0 for push/pop, 31 for jal
MUX32_2x1 mux_wa_sel_p2(wa_sel_p2, 32'b0, 31, CTRL[`wa_sel_2]);
MUX32_2x1 mux_wa_sel(wa_sel, wa_sel_p2, wa_sel_p1, CTRL[`wa_sel_3]);
MUX32_2x1 mux_wd_sel_p1(wd_sel_p1, alu_out,DATA_IN, CTRL[`wd_sel_1]);
MUX32_2x1 mux_wd_sel_p2(wd_sel_p2, wd_sel_p1, imm_zx_lsb, CTRL[`wd_sel_2]);
MUX32_2x1 mux_wd_sel(wd_sel, pc_inc, wd_sel_p2, CTRL[`wd_sel_3]);
// Register File
REGISTER_FILE_32x32 rf_inst(.DATA_R1(r1), .DATA_R2(r2), .ADDR_R1(r1_sel[4:0]), .ADDR_R2(rt),
.DATA_W(wd_sel), .ADDR_W(wa_sel[4:0]), .READ(reg_r), .WRITE(reg_w), .CLK(CLK), .RST(RST));
.DATA_W(wd_sel), .ADDR_W(wa_sel[4:0]), .READ(CTRL[`reg_r]), .WRITE(CTRL[`reg_w]),
.CLK(CLK), .RST(RST));
// ALU Input
wire [31:0] op1_sel, op2_sel;
@@ -139,40 +92,40 @@ wire [31:0] shamt_zx, imm_sx, imm_zx;
buf shamt_zx_buf [31:0] (shamt_zx, {27'b0, shamt});
buf imm_sx_buf [31:0] (imm_sx, {{16{imm[15]}}, imm});
buf imm_zx_buf [31:0] (imm_zx, {16'b0, imm});
MUX32_2x1 mux_op1_sel(op1_sel, r1, sp, op1_sel_1);
MUX32_2x1 mux_op2_sel_p1(op2_sel_p1, 32'b1, shamt_zx, op2_sel_1);
MUX32_2x1 mux_op2_sel_p2(op2_sel_p2, imm_zx, imm_sx, op2_sel_2);
MUX32_2x1 mux_op2_sel_p3(op2_sel_p3, op2_sel_p2, op2_sel_p1, op2_sel_3);
MUX32_2x1 mux_op2_sel(op2_sel, op2_sel_p3, r2, op2_sel_4);
MUX32_2x1 mux_op1_sel(op1_sel, r1, sp, CTRL[`op1_sel_1]);
MUX32_2x1 mux_op2_sel_p1(op2_sel_p1, 32'b1, shamt_zx, CTRL[`op2_sel_1]);
MUX32_2x1 mux_op2_sel_p2(op2_sel_p2, imm_zx, imm_sx, CTRL[`op2_sel_2]);
MUX32_2x1 mux_op2_sel_p3(op2_sel_p3, op2_sel_p2, op2_sel_p1, CTRL[`op2_sel_3]);
MUX32_2x1 mux_op2_sel(op2_sel, op2_sel_p3, r2, CTRL[`op2_sel_4]);
// ALU
ALU alu_inst(.OUT(alu_out), .ZERO(ZERO), .OP1(op1_sel), .OP2(op2_sel), .OPRN(alu_oprn));
ALU alu_inst(.OUT(alu_out), .ZERO(ZERO), .OP1(op1_sel), .OP2(op2_sel), .OPRN(CTRL[`alu_oprn]));
// Progam Counter Input
wire [31:0] pc_sel;
wire [31:0] pc_branch, pc_jump, pc_sel_p1, pc_sel_p2;
RC_ADD_SUB_32 pc_inc_inst(.Y(pc_inc), .CO(), .A(pc), .B(32'b1), .SnA(1'b0));
MUX32_2x1 mux_pc_sel_p1(pc_sel_p1, r1, pc_inc, pc_sel_1);
RC_ADD_SUB_32 pc_sel_2_inst(.Y(pc_branch), .CO(), .A(pc), .B(imm_sx), .SnA(1'b0));
MUX32_2x1 mux_pc_sel_p2(pc_sel_p2, pc_sel_p1, pc_branch, pc_sel_2);
MUX32_2x1 mux_pc_sel_p1(pc_sel_p1, r1, pc_inc, CTRL[`pc_sel_1]);
RC_ADD_SUB_32 pc_sel_2_inst(.Y(pc_branch), .CO(), .A(pc_inc), .B(imm_sx), .SnA(1'b0));
MUX32_2x1 mux_pc_sel_p2(pc_sel_p2, pc_sel_p1, pc_branch, CTRL[`pc_sel_2]);
buf pc_jump_buf [31:0] (pc_jump, {6'b0, addr});
MUX32_2x1 mux_pc_sel(pc_sel, pc_jump, pc_sel_p2, pc_sel_3);
MUX32_2x1 mux_pc_sel(pc_sel, pc_jump, pc_sel_p2, CTRL[`pc_sel_3]);
// Program Counter
defparam pc_inst.PATTERN = `INST_START_ADDR;
REG32_PP pc_inst(.Q(pc), .D(pc_sel), .LOAD(pc_load), .CLK(CLK), .RESET(RST));
REG32_PP pc_inst(.Q(pc), .D(pc_sel), .LOAD(CTRL[`pc_load]), .CLK(CLK), .RESET(RST));
// Stack Pointer
defparam sp_inst.PATTERN = `INIT_STACK_POINTER;
REG32_PP sp_inst(.Q(sp), .D(alu_out), .LOAD(sp_load), .CLK(CLK), .RESET(RST));
REG32_PP sp_inst(.Q(sp), .D(alu_out), .LOAD(CTRL[`sp_load]), .CLK(CLK), .RESET(RST));
// Data out
MUX32_2x1 mux_data_out(DATA_OUT, r2, r1, md_sel_1);
MUX32_2x1 mux_data_out(DATA_OUT, r2, r1, CTRL[`md_sel_1]);
// Address out
wire [31:0] ma_sel_p1;
MUX32_2x1 mux_ma_sel_p1(ma_sel_p1, alu_out, sp, ma_sel_1);
// TODO: Check address calculation since it's 26 bit
MUX32_2x1 mux_ma_sel_p1(ma_sel_p1, alu_out, sp, CTRL[`ma_sel_1]);
// discard the upper 6 bits of the address since it's only 26 bit addressable
(* keep="soft" *)
wire [5:0] _addr_ignored;
MUX32_2x1 mux_ma_sel({_addr_ignored,ADDR}, ma_sel_p1, pc, ma_sel_2);
MUX32_2x1 mux_ma_sel({_addr_ignored,ADDR}, ma_sel_p1, pc, CTRL[`ma_sel_2]);
endmodule