/* * Pipelined PICO * * $Revision: 1.1 $ */ /* Ope-code IR15-11 */ %d ROP 0b00000 /* Register Type operation */ %d NOP 0b00000 /* NOP */ %d LDLI 0b11100 %d LDHI 0b11101 %d BNEZ 0b01001 %d BEQZ 0b01010 /* Ope-code IR 4-0 */ %d LD 0b01000 %d ST 0b01001 /**** Module declaration ****/ declare if { input idata<16>, pcset, pcbra<16>; output ifpc<16>, ifir<16>; instrin enable; instr_arg enable(idata, pcset, pcbra); } declare rf { input ifir<16>, ifpc<16>, rwe, rwen, c<16>, rwadr<3>, fdata<16>; output rfir<16>, rfpc<16>, a<16>, b<16>, imm<16>, badr<16>; instrout pcset; instrin enable; instr_arg enable(ifir, ifpc, rwe, rwen, rwadr, c, fdata); } declare ex { input rfir<16>, rfpc<16>, rfim<16>, a<16>, b<16>, ddatain<16>; output c<16>, ddataout<16>, address<16>, rwadr<3>, fdata<16>; instrin enable; instrout dmoe, dmwe, rwen ; instr_arg enable(rfir, rfpc, rfim, a, b, ddatain); } declare wb { input rwen; output rwe; instrin enable; instr_arg enable(rwen); } declare regfile { input addr1<3>, addr2<3>, addr3<3>, din<16>, we; output dout1<16>, dout2<16>; instrin enable; instr_arg enable(addr1, addr2, addr3, din, we); } declare alu16 { input ina<16>, inb<16>, com<4>; output y<16>; instrin enable; instr_arg enable(ina, inb, com); } declare addsub16 { input ina<16>, inb<16>, sel; output sumdiff<16> ; instrin enable; instr_arg enable(ina, inb, sel); } declare add16 { input a<16>, b<16>, ci; output y<16>, co; instrin enable; instr_arg enable(a, b, ci); } declare cla4 { input a<4>, b<4>, ci; output y<4>, co, go, po; instrin enable; instr_arg enable(a,b,ci); } declare lcg4 { input g<4>, p<4>, ci; output c0, c1, c2, go, po; instrin enable; instr_arg enable(g,p,ci); } /**** Modules ****/ module ppico16 { input idata<16>, ddatain<16>; output iaddr<16>, daddr<16>, ddataout<16>; output dmoe, dmwe; instrin enable; if IFETCH; rf RFETCH; ex EXEC; wb WBACK; sel_v pcset, pcbra<16>, ifir<16>, ifpc<16>; sel_v a<16>, b<16>, c<16>; sel_v rwe, rwen, rfir<16>, rfpc<16>, rfim<16>, rwadr<3>, fdata<16> ; sel_v badr<16> ; instruct enable par { IFETCH.enable(idata, pcset, badr); RFETCH.enable(ifir, ifpc, rwe, rwen, rwadr, c, fdata); EXEC.enable(rfir, rfpc, rfim, a, b, ddatain); WBACK.enable(rwen); iaddr = IFETCH.ifpc; ifpc = IFETCH.ifpc; ifir = IFETCH.ifir; rfir = RFETCH.rfir; rfpc = RFETCH.rfpc; a = RFETCH.a; b = RFETCH.b; rfim = RFETCH.imm; pcset = RFETCH.pcset; badr = RFETCH.badr; c = EXEC.c; rwen = EXEC.rwen; rwadr = EXEC.rwadr; dmoe = EXEC.dmoe; dmwe = EXEC.dmwe; daddr = EXEC.address; ddataout = EXEC.ddataout; fdata = EXEC.fdata; rwe = WBACK.rwe; } } /**** Instuction Fetch ****/ module if { input idata<16>, pcset, pcbra<16>; output ifpc<16>, ifir<16>; instrin enable; add16 PCINC; reg_wr pc<16>, ir<16>; instruct enable par { ifir = ir; ifpc = pc; ir := idata; alt{ pcset: pc := pcbra; else: pc := PCINC.enable(pc, 0x0002, 0b0).y; } } } /**** Register Fetch ****/ module rf { input ifir<16>, ifpc<16>, rwe, rwen, c<16>, rwadr<3>, fdata<16>; output rfir<16>, rfpc<16>, a<16>, b<16>, imm<16>, badr<16>; instrout pcset; instrin enable; regfile REG; add16 BADDER; reg_wr reg_ir<16>; reg_wr reg_a<16>, reg_b<16>, reg_im<16>, reg_pc<16>; sel_v frega<16>; instruct enable par { a = reg_a; b = reg_b; imm = reg_im; rfpc = reg_pc; rfir = reg_ir; reg_im := 16 # ifir<7:0>; reg_pc := ifpc; reg_ir := ifir; REG.enable(ifir<10:8>, ifir<7:5>, rwadr, c, rwe); alt { rwen & ^/|(rfir<10:8> @ ifir<10:8>): frega = fdata; else: frega = REG.dout1;} alt{ rwen & ^/|(rfir<10:8> @ ifir<7:5>): reg_b := fdata; else: reg_b := REG.dout2; } reg_a := frega; badr = BADDER.enable(ifpc,16#ifir<7:0>,0b0).y; alt { ifir<15:11> == BEQZ: alt { ^/|frega: pcset();} ifir<15:11> == BNEZ: alt { /|frega: pcset(); } } } } /**** Exection ****/ module ex { input rfir<16>, rfpc<16>, rfim<16>, a<16>, b<16>, ddatain<16>; output c<16>, ddataout<16>, address<16>, rwadr<3>, fdata<16>; instrin enable; instrout dmoe, dmwe, rwen ; alu16 ALU; reg reg_c<16>, reg_rwadr<3>; instruct enable par { c = reg_c; ddataout = b; rwadr = reg_rwadr; reg_rwadr := rfir<10:8>; alt{ (rfir<15:11> == ROP) & (rfir<4:0> == ST) : address = a; else: address = b;} alt{ rfir<15:11> == ROP: alt { /* R type functions */ rfir<4:0> == LD: par { /* LD */ dmoe(); rwen(); fdata = ddatain; reg_c := ddatain; } rfir<4:0> == ST: dmwe(); /* ST */ rfir<4:3> == 0b00: par {/* ALU instructions */ fdata = ALU.enable(a,b,rfir<3:0>).y; reg_c := fdata; alt {/|rfir<4:0>: rwen();} } } rfir<15:11> == LDLI: par { /* LDLI */ fdata = rfim; reg_c := fdata; rwen(); } rfir<15:14> == 0b00: par { /* ALU instructions */ fdata = ALU.enable(a,rfim,rfir<14:11>).y; reg_c := fdata; rwen(); } } } } module wb { input rwen ; output rwe ; instrin enable; reg_wr rwe_reg; instruct enable par{ rwe = rwe_reg; rwe_reg:= rwen; } } /**** register file with two output ports ****/ module regfile { input addr1<3>, addr2<3>, addr3<3>, din<16>, we; output dout1<16>, dout2<16>; instrin enable; reg register0<16>; reg register1<16>; reg register2<16>; reg register3<16>; reg register4<16>; reg register5<16>; reg register6<16>; reg register7<16>; instruct enable par { alt{ we & ^/|(addr1 @ addr3): dout1 = din; addr1 == 0b000: dout1 = register0; addr1 == 0b001: dout1 = register1; addr1 == 0b010: dout1 = register2; addr1 == 0b011: dout1 = register3; addr1 == 0b100: dout1 = register4; addr1 == 0b101: dout1 = register5; addr1 == 0b110: dout1 = register6; addr1 == 0b111: dout1 = register7; } alt{ we & ^/|(addr2 @ addr3): dout2 = din; addr2 == 0b000: dout2 = register0; addr2 == 0b001: dout2 = register1; addr2 == 0b010: dout2 = register2; addr2 == 0b011: dout2 = register3; addr2 == 0b100: dout2 = register4; addr2 == 0b101: dout2 = register5; addr2 == 0b110: dout2 = register6; addr2 == 0b111: dout2 = register7; } alt { we & addr3 == 0b000: register0 := din; we & addr3 == 0b001: register1 := din; we & addr3 == 0b010: register2 := din; we & addr3 == 0b011: register3 := din; we & addr3 == 0b100: register4 := din; we & addr3 == 0b101: register5 := din; we & addr3 == 0b110: register6 := din; we & addr3 == 0b111: register7 := din; } } } /**** alu16 ****/ module alu16 { input ina<16>, inb<16>,com<4>; output y<16>; instrin enable; addsub16 as16; /* 16bit adder */ instruct enable alt { com==0b0000: y = ina ; /* Through A */ com==0b0001: y = inb ; /* Through B */ com==0b0010: y = ina & inb ; /* A and B */ com==0b0011: y = ina | inb ; /* A or B */ com==0b0100: y = ina @ inb ; /* Exclusive OR */ com==0b0101: y = ^inb; /* Not */ com==0b1100: y = inb<14:0>|| 0b0 ; /* Shift Left */ com==0b1101: y = 0b0||inb<15:1>; /* Shift Right */ else: y = as16.enable(ina, inb, com<0>).sumdiff;/* SUB/ADD */ } } /**** addsub16 ****/ module addsub16 { input ina<16>, inb<16>, sel; output sumdiff<16>; instrin enable; add16 add; instruct enable alt { sel: sumdiff = add.enable(ina, ^inb, sel).y; else: sumdiff = add.enable(ina, inb, sel).y; } } /**** 16-Bits Carry Lookahead Adder ****/ module add16 { input a<16>, b<16>, ci; output y<16>, co; instrin enable; cla4 CLA0; cla4 CLA1; cla4 CLA2; cla4 CLA3; lcg4 LCG; sel_v c0, c1, c2; sel_v g0, g1, g2, g3; sel_v p0, p1, p2, p3; sel_v s0<4>, s1<4>, s2<4>, s3<4>; instruct enable par { LCG.enable(g3||g2||g1||g0, p3||p2||p1||p0, ci); CLA0.enable(a< 3: 0>, b< 3: 0>, ci); CLA1.enable(a< 7: 4>, b< 7: 4>, c0); CLA2.enable(a<11: 8>, b<11: 8>, c1); CLA3.enable(a<15:12>, b<15:12>, c2); c0 = LCG.c0; c1 = LCG.c1; c2 = LCG.c2; g0 = CLA0.go; g1 = CLA1.go; g2 = CLA2.go; g3 = CLA3.go; p0 = CLA0.po; p1 = CLA1.po; p2 = CLA2.po; p3 = CLA3.po; s0 = CLA0.y; s1 = CLA1.y; s2 = CLA2.y; s3 = CLA3.y; co = CLA3.co; y = s3 || s2 || s1 || s0; } } module cla4 { input a<4>, b<4>, ci; output y<4>, co, go, po; instrin enable; sel_v c0, c1, c2; instruct enable par { c0 = (a<0> & b<0>) | ((a<0> | b<0>) & ci); c1 = (a<1> & b<1>) | ((a<1> | b<1>) & a<0> & b<0>) | ((a<1> | b<1>) & (a<0> | b<0>) & ci); c2 = (a<2> & b<2>) | ((a<2> | b<2>) & a<1> & b<1>) | ((a<2> | b<2>) & (a<1> | b<1>) & a<0> & b<0>) | ((a<2> | b<2>) & (a<1> | b<1>) & (a<0> | b<0>) & ci); go = (a<3> & b<3>) | ((a<3> | b<3>) & a<2> & b<2>) | ((a<3> | b<3>) & (a<2> | b<2>) & a<1> & b<1>) | ((a<3> | b<3>) & (a<2> | b<2>) & (a<1> | b<1>) & a<0> & b<0>); po = (a<3>|b<3>) & (a<2>|b<2>) & (a<1>|b<1>) & (a<0>|b<0>); co = go | (po & ci); y = a @ b @ (c2 || c1 || c0 || ci); } } module lcg4 { input g<4>, p<4>, ci; output c0, c1, c2, go, po; instrin enable; instruct enable par { c0 = g<0>|(p<0>&ci); c1 = g<1>|(p<1>&g<0>)|(p<1>&p<0>&ci); c2 = g<2>|(p<2>&g<1>)|(p<2>&p<1>&g<0>)|(p<2>&p<1>&p<0>&ci); go = g<3>|(p<3>&g<2>)|(p<3>&p<2>&g<1>)|(p<3>&p<2>&p<1>&g<0>); po = p<3> & p<2> & p<1> & p<0>; } }