3 Commits

6 changed files with 198 additions and 169 deletions

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 // reset
reg RST; 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 // Clock generator instance
CLK_GENERATOR clk_gen_inst(.CLK(CLK)); 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_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); $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 : 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 end
$stop; $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" `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_load 0
`define pc_sel_1 1 `define pc_sel_1 1
`define pc_sel_2 2 `define pc_sel_2 2
@@ -105,6 +105,7 @@ output READ, WRITE;
input ZERO, CLK, RST; input ZERO, CLK, RST;
input [`DATA_INDEX_LIMIT:0] INSTRUCTION; input [`DATA_INDEX_LIMIT:0] INSTRUCTION;
// Task to print instruction
task print_instruction; task print_instruction;
input [`DATA_INDEX_LIMIT:0] inst; input [`DATA_INDEX_LIMIT:0] inst;
reg [5:0] opcode; reg [5:0] opcode;
@@ -128,51 +129,45 @@ $write("@ %6dns -> [0X%08h] ", $time, inst);
case(opcode) case(opcode)
// R-Type // R-Type
6'h00 : begin `OP_RTYPE: case(funct)
case(funct) `FN_ADD: $write("add r[%02d], r[%02d], r[%02d];", rd, rs, rt);
6'h20: $write("add r[%02d], r[%02d], r[%02d];", rd, rs, rt); `FN_SUB: $write("sub r[%02d], r[%02d], r[%02d];", rd, rs, rt);
6'h22: $write("sub r[%02d], r[%02d], r[%02d];", rd, rs, rt); `FN_MUL: $write("mul r[%02d], r[%02d], r[%02d];", rd, rs, rt);
6'h2c: $write("mul r[%02d], r[%02d], r[%02d];", rd, rs, rt); `FN_AND: $write("and r[%02d], r[%02d], r[%02d];", rd, rs, rt);
6'h24: $write("and r[%02d], r[%02d], r[%02d];", rd, rs, rt); `FN_OR: $write("or r[%02d], r[%02d], r[%02d];", rd, rs, rt);
6'h25: $write("or r[%02d], r[%02d], r[%02d];", rd, rs, rt); `FN_NOR: $write("nor r[%02d], r[%02d], r[%02d];", rd, rs, rt);
6'h27: $write("nor r[%02d], r[%02d], r[%02d];", rd, rs, rt); `FN_SLT: $write("slt r[%02d], r[%02d], r[%02d];", rd, rs, rt);
6'h2a: $write("slt r[%02d], r[%02d], r[%02d];", rd, rs, rt); `FN_SLL: $write("sll r[%02d], r[%02d], %2d;", rd, rs, shamt);
6'h01: $write("sll r[%02d], r[%02d], %2d;", rd, rs, shamt); `FN_SRL: $write("srl r[%02d], 0X%02h, r[%02d];", rd, rs, shamt);
6'h02: $write("srl r[%02d], 0X%02h, r[%02d];", rd, rs, shamt); `FN_JR: $write("jr r[%02d];", rs);
6'h08: $write("jr r[%02d];", rs);
default: $write(""); default: $write("");
endcase endcase
end
// I-type // I-type
6'h08 : $write("addi r[%02d], r[%02d], 0X%04h;", rt, rs, imm); `OP_ADDI: $write("addi r[%02d], r[%02d], 0X%04h;", rt, rs, imm);
6'h1d : $write("muli r[%02d], r[%02d], 0X%04h;", rt, rs, imm); `OP_MULI: $write("muli r[%02d], r[%02d], 0X%04h;", rt, rs, imm);
6'h0c : $write("andi r[%02d], r[%02d], 0X%04h;", rt, rs, imm); `OP_ANDI: $write("andi r[%02d], r[%02d], 0X%04h;", rt, rs, imm);
6'h0d : $write("ori r[%02d], r[%02d], 0X%04h;", rt, rs, imm); `OP_ORI: $write("ori r[%02d], r[%02d], 0X%04h;", rt, rs, imm);
6'h0f : $write("lui r[%02d], 0X%04h;", rt, imm); `OP_LUI: $write("lui r[%02d], 0X%04h;", rt, imm);
6'h0a : $write("slti r[%02d], r[%02d], 0X%04h;", rt, rs, imm); `OP_SLTI: $write("slti r[%02d], r[%02d], 0X%04h;", rt, rs, imm);
6'h04 : $write("beq r[%02d], r[%02d], 0X%04h;", rt, rs, imm); `OP_BEQ: $write("beq r[%02d], r[%02d], 0X%04h;", rt, rs, imm);
6'h05 : $write("bne r[%02d], r[%02d], 0X%04h;", rt, rs, imm); `OP_BNE: $write("bne r[%02d], r[%02d], 0X%04h;", rt, rs, imm);
6'h23 : $write("lw r[%02d], r[%02d], 0X%04h;", rt, rs, imm); `OP_LW: $write("lw r[%02d], r[%02d], 0X%04h;", rt, rs, imm);
6'h2b : $write("sw r[%02d], r[%02d], 0X%04h;", rt, rs, imm); `OP_SW: $write("sw r[%02d], r[%02d], 0X%04h;", rt, rs, imm);
// J-Type // J-Type
6'h02 : $write("jmp 0X%07h;", addr); `OP_JMP: $write("jmp 0X%07h;", addr);
6'h03 : $write("jal 0X%07h;", addr); `OP_JAL: $write("jal 0X%07h;", addr);
6'h1b : $write("push;"); `OP_PUSH: $write("push;");
6'h1c : $write("pop;"); `OP_POP: $write("pop;");
default: $write(""); default: $write("");
endcase endcase
$write("\n"); $write("\n");
end end
endtask endtask
//------------------------------------- END ---------------------------------------//
reg read, write; reg read, write;
buf (READ, read); buf (READ, read);
buf (WRITE, write); buf (WRITE, write);
//assign READ = read;
//assign WRITE = write;
reg [31:0] C; reg [31:0] C;
@@ -192,7 +187,7 @@ reg [25:0] addr;
wire [2:0] state; wire [2:0] state;
PROC_SM proc_sm(state, CLK, RST); 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 always @ (state) begin
// R-type // R-type
{opcode, rs, rt, rd, shamt, funct} = INSTRUCTION; {opcode, rs, rt, rd, shamt, funct} = INSTRUCTION;
@@ -201,19 +196,6 @@ always @ (state) begin
// J-type // J-type
{opcode, addr} = INSTRUCTION; {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) case (state)
// fetch - next instruction from memory at PC // fetch - next instruction from memory at PC
`PROC_FETCH: begin `PROC_FETCH: begin
@@ -222,8 +204,8 @@ always @ (state) begin
// memory // memory
read = 1'b1; read = 1'b1;
write = 1'b0; write = 1'b0;
// selections // ma_sel_2: load data from mem[PC]
C[`ma_sel_2] = 1'b1; // load data from mem[PC] C[`ma_sel_2] = 1'b1;
end end
// decode - parse instruction and read values from register file // decode - parse instruction and read values from register file
`PROC_DECODE: begin `PROC_DECODE: begin
@@ -239,30 +221,30 @@ always @ (state) begin
print_instruction(INSTRUCTION); print_instruction(INSTRUCTION);
// loaded in previous state, set to 0 // loaded in previous state, set to 0
C[`ir_load] = 1'b0; C[`ir_load] = 1'b0;
// load now // load now - sp is incremented before pop
C[`sp_load] = opcode == `OP_POP; // sp is decremented before pop C[`sp_load] = opcode == `OP_POP;
// selections
// r1_sel_1: rs by default (0), push - r1 (1) // r1_sel_1: rs by default (0), push - r1 (1)
C[`r1_sel_1] = opcode == `OP_PUSH; C[`r1_sel_1] = opcode == `OP_PUSH;
// wa_sel_1: R-type - write to rd (0), I-type - write to rt (1) // wa_sel_1: R-type - write to rd (0), I-type - write to rt (1)
C[`wa_sel_1] = opcode != `OP_RTYPE; C[`wa_sel_1] = opcode != `OP_RTYPE;
// wa_sel_2: jal - write to r31 (0), pop - write to r0 (1) // wa_sel_2: pop - write to r0 (0), jal - write to r31 (1)
C[`wa_sel_2] = opcode == `OP_POP; C[`wa_sel_2] = opcode == `OP_JAL;
// wa_sel_3: push or pop - wa_sel_2, else wa_sel_1 // wa_sel_3: wa_sel_2 if push or pop or jal (0), else wa_sel_1 (1)
// wa_sel_3: wa_sel_2 if push or pop (0), else wa_sel_1 (1) C[`wa_sel_3] = ~(opcode == `OP_PUSH || opcode == `OP_POP || opcode == `OP_JAL);
C[`wa_sel_3] = ~(opcode == `OP_PUSH || opcode == `OP_POP);
// pc_sel_1: jr - jump to address in rs (0), else pc_inc (1) // pc_sel_1: jr - jump to address in rs (0), else pc_inc (1)
C[`pc_sel_1] = ~(opcode == `OP_JMP && funct == `FN_JR); 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: pc_sel_1 by default (0), beq, bne - branch if equal or not equal (1)
// TODO: this should only be selected if the condition is met // pc_sel_2 is set after EXE because it depends on ZERO
// pc_sel_2 = opcode == `OP_BEQ || opcode == `OP_BNE;
// pc_sel_3: jmp or jal - jump to address (0), else pc_sel_2 (1) // 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); C[`pc_sel_3] = ~(opcode == `OP_JMP || opcode == `OP_JAL);
// alu_oprn - operation to be performed by ALU // alu_oprn - operation to be performed by ALU
case (opcode)
// R-type // R-type
if (opcode == `OP_RTYPE) begin `OP_RTYPE: case (funct)
case (funct)
`FN_ADD: C[`alu_oprn] = `ALU_ADD; `FN_ADD: C[`alu_oprn] = `ALU_ADD;
`FN_SUB: C[`alu_oprn] = `ALU_SUB; `FN_SUB: C[`alu_oprn] = `ALU_SUB;
`FN_MUL: C[`alu_oprn] = `ALU_MUL; `FN_MUL: C[`alu_oprn] = `ALU_MUL;
@@ -274,10 +256,6 @@ always @ (state) begin
`FN_SLT: C[`alu_oprn] = `ALU_SLT; `FN_SLT: C[`alu_oprn] = `ALU_SLT;
default: C[`alu_oprn] = `ALU_NOP; default: C[`alu_oprn] = `ALU_NOP;
endcase endcase
end
// I-type and J-type
else begin
case (opcode)
// I-type // I-type
`OP_ADDI: C[`alu_oprn] = `ALU_ADD; // addi `OP_ADDI: C[`alu_oprn] = `ALU_ADD; // addi
`OP_MULI: C[`alu_oprn] = `ALU_MUL; // muli `OP_MULI: C[`alu_oprn] = `ALU_MUL; // muli
@@ -293,34 +271,35 @@ always @ (state) begin
`OP_POP: C[`alu_oprn] = `ALU_ADD; // pop - add `OP_POP: C[`alu_oprn] = `ALU_ADD; // pop - add
default: C[`alu_oprn] = `ALU_NOP; default: C[`alu_oprn] = `ALU_NOP;
endcase endcase
end
// op1_sel_1: r1 by default (0), push or pop - sp (1) // op1_sel_1: r1 by default (0), push or pop - sp (1)
C[`op1_sel_1] = opcode == `OP_PUSH || opcode == `OP_POP; C[`op1_sel_1] = opcode == `OP_PUSH || opcode == `OP_POP;
// op2_sel_1: const 1 (for inc/dec) (0), shamt for sll/srl (1) // 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); 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) // op2_sel_2: imm_zx for logical and/or (0), imm_sx otherise (1)
// ('nor' not availble in I-type) // ('nor' not availble in I-type)
C[`op2_sel_2] = ~(opcode == `OP_ANDI || opcode == `OP_ORI); 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) // op2_sel_3: op2_sel_2 for I-type (0), op2_sel_1 for R-type shift or inc/dec (1)
// inc/dec is push or pop // (inc/dec is for sp with pop or push)
C[`op2_sel_3] = opcode == `OP_RTYPE || opcode == `OP_PUSH || opcode == `OP_POP; 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) // 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 // 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) C[`op2_sel_4] = opcode == `OP_RTYPE && ~(funct == `FN_SLL || funct == `FN_SRL)
|| opcode == `OP_BEQ || opcode == `OP_BNE; || opcode == `OP_BEQ || opcode == `OP_BNE;
// wd_sel_1: alu_out or DATA_IN
// wd_sel_1: alu_out by default (0), DATA_IN for lw or pop (1) // 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; 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) // wd_sel_2: wd_sel_1 by default (0), imm_zx_lsb for lui (1)
C[`wd_sel_2] = opcode == `OP_LUI; C[`wd_sel_2] = opcode == `OP_LUI;
// wd_sel_3: pc_inc for jal (0), else wd_sel_2 (1) // wd_sel_3: pc_inc for jal (0), else wd_sel_2 (1)
C[`wd_sel_3] = ~(opcode == `OP_JAL); C[`wd_sel_3] = ~(opcode == `OP_JAL);
// ma_sel_1: alu_out for lw or sw, sp for push or pop
// ma_sel_1: alu_out for lw or sw (0), sp for push or pop (1) // 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; 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 // ma_sel_2: 0 for every memory access instruction (lw, sw, push, pop), 1 for fetch
C[`ma_sel_2] = 1'b0; C[`ma_sel_2] = 1'b0;
// md_sel_1: r2 for sw (0), r1 for push (1) // md_sel_1: r2 for sw (0), r1 for push (1)
C[`md_sel_1] = opcode == `OP_PUSH; C[`md_sel_1] = opcode == `OP_PUSH;
end end
@@ -333,13 +312,14 @@ always @ (state) begin
read = opcode == `OP_POP || opcode == `OP_LW; read = opcode == `OP_POP || opcode == `OP_LW;
end end
`PROC_WB: begin `PROC_WB: begin
// load now
C[`sp_load] = opcode == `OP_PUSH; // sp is incremented after push
// loaded in previous state, set to 0 // loaded in previous state, set to 0
read = 1'b0; read = 1'b0;
write = 1'b0; write = 1'b0;
// load now // load now
// pc gets next instruction address
C[`pc_load] = 1'b1; C[`pc_load] = 1'b1;
// sp is decremented after push
C[`sp_load] = opcode == `OP_PUSH;
// write to register file if // write to register file if
// R-type (except jr) or I-type (except beq, bne, sw) or pop or jal // R-type (except jr) or I-type (except beq, bne, sw) or pop or jal
C[`reg_w] = (opcode == `OP_RTYPE && funct != `FN_JR) // R-type (except jr) C[`reg_w] = (opcode == `OP_RTYPE && funct != `FN_JR) // R-type (except jr)
@@ -347,7 +327,6 @@ always @ (state) begin
|| opcode == `OP_LUI || opcode == `OP_SLTI || opcode == `OP_LW) // I-type (except beq, bne, sw) || opcode == `OP_LUI || opcode == `OP_SLTI || opcode == `OP_LW) // I-type (except beq, bne, sw)
|| (opcode == `OP_POP || opcode == `OP_JAL) // pop or jal || (opcode == `OP_POP || opcode == `OP_JAL) // pop or jal
; ;
// selections
// pc_sel_2: branch if equal or not equal // pc_sel_2: branch if equal or not equal
C[`pc_sel_2] = ((opcode == `OP_BEQ) && ZERO) || ((opcode == `OP_BNE) && ~ZERO); C[`pc_sel_2] = ((opcode == `OP_BEQ) && ZERO) || ((opcode == `OP_BNE) && ~ZERO);
end end
@@ -387,7 +366,7 @@ always @ (negedge RST) begin
state_sel = 3'bxxx; state_sel = 3'bxxx;
end end
// TBD - take action on each +ve edge of clock // take action on each +ve edge of clock
always @ (posedge CLK) begin always @ (posedge CLK) begin
case (state_sel) case (state_sel)
`PROC_FETCH: state_sel = `PROC_DECODE; `PROC_FETCH: state_sel = `PROC_DECODE;

View File

@@ -17,6 +17,7 @@
//------------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------------
// //
`include "prj_definition.v" `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); module DATA_PATH(DATA_OUT, ADDR, ZERO, INSTRUCTION, DATA_IN, CTRL, CLK, RST);
// output list // output list
@@ -29,53 +30,6 @@ input [`CTRL_WIDTH_INDEX_LIMIT:0] CTRL;
input CLK, RST; input CLK, RST;
input [`DATA_INDEX_LIMIT:0] DATA_IN; 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 // variables
wire [31:0] ir; // Instruction Register wire [31:0] ir; // Instruction Register
wire [31:0] r1, r2; // Register File 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] sp; // Stack Pointer
wire [31:0] alu_out; // ALU output wire [31:0] alu_out; // ALU output
// TODO: Why? // instruction sent to control unit
buf ir_buf [31:0] (INSTRUCTION, ir); buf ir_buf [31:0] (INSTRUCTION, ir);
// Parse the instruction data // Parse the instruction data
@@ -110,27 +64,26 @@ buf imm_buf [15:0] (imm, ir[15:0]);
// for J-type // for J-type
buf addr_buf [25:0] (addr, ir[25:0]); buf addr_buf [25:0] (addr, ir[25:0]);
// Instruction Register input
// Instruction Register // 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 // Register File Input
wire [31:0] r1_sel, wa_sel, wd_sel; 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] wa_sel_p1, wa_sel_p2, wd_sel_p1, wd_sel_p2;
wire [31:0] imm_zx_lsb; wire [31:0] imm_zx_lsb;
buf imm_zx_lsb_buf [31:0] (imm_zx_lsb, {imm, 16'b0}); 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_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}, wa_sel_1); MUX32_2x1 mux_wa_sel_p1(wa_sel_p1, {27'b0,rd}, {27'b0,rt}, CTRL[`wa_sel_1]);
// TODO: Why 31? // 0 for push/pop, 31 for jal
MUX32_2x1 mux_wa_sel_p2(wa_sel_p2, 32'b0, 31, wa_sel_2); 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, wa_sel_3); 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, wd_sel_1); 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, wd_sel_2); 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, wd_sel_3); MUX32_2x1 mux_wd_sel(wd_sel, pc_inc, wd_sel_p2, CTRL[`wd_sel_3]);
// Register File // Register File
REGISTER_FILE_32x32 rf_inst(.DATA_R1(r1), .DATA_R2(r2), .ADDR_R1(r1_sel[4:0]), .ADDR_R2(rt), 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 // ALU Input
wire [31:0] op1_sel, op2_sel; 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 shamt_zx_buf [31:0] (shamt_zx, {27'b0, shamt});
buf imm_sx_buf [31:0] (imm_sx, {{16{imm[15]}}, imm}); buf imm_sx_buf [31:0] (imm_sx, {{16{imm[15]}}, imm});
buf imm_zx_buf [31:0] (imm_zx, {16'b0, 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_op1_sel(op1_sel, r1, sp, CTRL[`op1_sel_1]);
MUX32_2x1 mux_op2_sel_p1(op2_sel_p1, 32'b1, shamt_zx, op2_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, op2_sel_2); 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, op2_sel_3); 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, op2_sel_4); MUX32_2x1 mux_op2_sel(op2_sel, op2_sel_p3, r2, CTRL[`op2_sel_4]);
// ALU // 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 // Progam Counter Input
wire [31:0] pc_sel; wire [31:0] pc_sel;
wire [31:0] pc_branch, pc_jump, pc_sel_p1, pc_sel_p2; 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)); 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); 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)); 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, pc_sel_2); 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}); 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 // Program Counter
defparam pc_inst.PATTERN = `INST_START_ADDR; 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 // Stack Pointer
defparam sp_inst.PATTERN = `INIT_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 // 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 // Address out
wire [31:0] ma_sel_p1; wire [31:0] ma_sel_p1;
MUX32_2x1 mux_ma_sel_p1(ma_sel_p1, alu_out, sp, ma_sel_1); MUX32_2x1 mux_ma_sel_p1(ma_sel_p1, alu_out, sp, CTRL[`ma_sel_1]);
// TODO: Check address calculation since it's 26 bit // discard the upper 6 bits of the address since it's only 26 bit addressable
(* keep="soft" *) (* keep="soft" *)
wire [5:0] _addr_ignored; 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 endmodule