ready for first tests, not working ofcourse

This commit is contained in:
mrbesen 2020-02-04 19:41:15 +01:00
parent e1227820dd
commit 277a86ea64
Signed by: MrBesen
GPG Key ID: 596B2350DCD67504
6 changed files with 304 additions and 78 deletions

View File

@ -14,18 +14,35 @@ module mojo_top (
) {
sig rst; // reset signal
sig clk2;
sig subclk[3]; //alows for 8 subclock pulses
.clk(clk) {
// The reset conditioner is used to synchronize the reset signal to the FPGA
// clock. This ensures the entire FPGA comes out of reset at the same time.
reset_conditioner reset_cond;
.rst(rst) {
counter slow_clk(#SIZE(15), #DIV(15));
}
}
.clk(clk2), .rst(rst), .subclk(subclk) {
node nodeA(.up_in(GNode.NULL), .right_in(GNode.NULL), .down_in(GNode.NULL), .left_in(GNode.NULL));
}
always {
reset_cond.in = ~rst_n; // input raw inverted reset signal
rst = reset_cond.out; // conditioned reset
led = 8h00; // turn LEDs off
clk2 = slow_clk.value[11];
subclk = slow_clk.value[13:11];
led = c{nodeA.left_out.in[3:0], subclk, clk2};
// led = 8h00; // turn LEDs off
spi_miso = bz; // not using SPI
spi_channel = bzzzz; // not using flags
avr_rx = bz; // not using serial port

View File

@ -5,6 +5,8 @@ global GNode {
const WORDLEN = 11; //bits to store a number (-999 to 999)
const REGISTERADDRLEN = 3; //bits to address a register
const NULL = 11h0;
struct cmd {
cmd[4],
arg_is_const, //1 = argument is a 11bit signed integer, 0 argument is a register number
@ -22,17 +24,18 @@ Register numbers:
3 = RIGHT
4 = DOWN
5 = LEFT
6 = LAST
7 = ANY
6 = LAST (not implemented correctly)
7 = ANY (not implemented correctly)
Subclk:
Subclk: (a counter that steps every clock cycle to execute one part of an command)
0 = Read cmd
1 = interpret cmd
2 = Mark input as read
3 = try to read
4 = mark output as read
5 = write to output
6 = increment pc and reset everything thats not needed anymore
4 = calculate
5 = mark output as read
6 = write to output
7 = increment pc and reset everything thats not needed anymore and update last register special case: regiuster == 6!
cycles are skiped, if node is waiting for another node to read or write a connection
*/
@ -54,42 +57,96 @@ module node (
output<G_nodeCon.nodeConIn> left_out,
output error,
input subclk
input subclk[3]
) {
sig to_reg[GNode.WORDLEN];
sig read_reg;
sig write_reg;
sig i[$clog2(GNode.ROWS)]; //DEBUG ONLY, counter variable for a for-loop
signed sig mainarg[GNode.WORDLEN]; //always reading
//sig argtwo[GNode.WORDLEN]; //always writing (mov cmd)
.clk(clk), .rst(rst) {
dff pc[4](#INIT(0)); //program counter
dff<GNode.cmd> cmds[GNode.ROWS];
dff lastreg[3](#INIT(0)); // default = NIL
dff acc[GNode.WORDLEN](#INIT(0));
dff bak[GNode.WORDLEN](#INIT(0));
dff is_reading(#INIT(0));
dff is_writing(#INIT(0));
dff<GNode.cmd> currentCmd;
fsm currentCmdFSM = {MOV, // 2 args: 1const, 1reg or 2 reg
JEZ, JNZ, JGZ, JLZ, JRO, // 1 arg: 5bit(signed) const offset
JEZ, JNZ, JGZ, JLZ, JRO, // 1 arg: 5bit(signed) const offset
ADD, SUB, // 1 arg: 1reg or 1 signed const
NEG, SWP, SAV}; // no arg
dff currentCmd_has_const(#INIT(0));
dff currentCmd_const[GNode.WORDLEN](#INIT(0));
dff currentCmd_has_reg[2](#INIT(0)); // only mov has two arguments (dst ist first; src ist second)
dff currentCmd_reg[2][3];//registers to use TODO: add #INIT(0)
registerMultiplex reg1(.selection(currentCmd_reg[0]), .acc(acc), .up(up), .right(right), .down(down), .left(left), .last(lastreg));
#INIT(0) {
dff currentCmd_has_const;
signed dff currentCmd_const[GNode.WORDLEN];
dff currentCmd_has_reg[2]; // only mov has two arguments (dst ist first (every cmd); src ist second(only used for mov))
dff lastreg[3]; // which register to use with LAST keyword, default = NIL
signed dff acc[GNode.WORDLEN];
signed dff bak[GNode.WORDLEN];
dff is_reading; //is command reading from a register? reading from ACC or BAK may not count (depending on context)
dff is_writing; //is command writing to a register? writing to ACC or BAK may not count (should be a pseudonym for currentCmd == MOV)
dff is_reading_inProgress; //is reading or writing in progress? (block every thing then)
dff is_writing_inProgress; //only on of this two can be 1 !
dff pc[4]; //program counter (which instruction to execute?)
}
dff currentCmd_reg[2][3];//registers to use TODO: add #INIT(0)
//TODO: fix selection! - when select what as read or as write reg?
registerDemultiplex reg_read(.selection(currentCmd_reg.q[0]), .acc(acc.q), .up(up_in), .right(right_in), .down(down_in), .left(left_in), .last(lastreg.q), .any(11h0), .read(read_reg));
registerMultiplex reg_write(.selection(currentCmd_reg.q[1]), .lastadr(lastreg.q), .write(write_reg), .in(to_reg));
}
always {
error = 0;
if(subclk == 0 && is_reading.q == 0 && is_writing.q == 0) {
//EXAMPLE CODE
//ADD 1
cmds.d[0].cmd = currentCmdFSM.ADD;
cmds.d[0].arg_is_const = 1;
cmds.d[0].args = 11d1; //1
//MOV ACC, LEFT
cmds.d[1].cmd = currentCmdFSM.MOV;
cmds.d[1].arg_is_const = 0;
cmds.d[1].args = 11b0101001; //0 5 1 (leer, left, acc) von acc -> left
//write NULL-OP's to the rest of memory
for(i = 2; i < GNode.ROWS; i++) {
cmds.d[1].cmd = currentCmdFSM.ADD;
cmds.d[1].arg_is_const = 1;
cmds.d[1].args = 11h0;
}
error = 0; // no error
read_reg = 0; //default to non reading
//define outputs
up_out.in = reg_write.up;
up_out.write = reg_write.up_w;
right_out.in = reg_write.right;
right_out.write = reg_write.right_w;
down_out.in = reg_write.down;
down_out.write = reg_write.down_w;
left_out.in = reg_write.left;
left_out.write = reg_write.left_w;
if(subclk == 0 && is_reading_inProgress.q == 0 && is_writing_inProgress.q == 0) {
//read command
currentCmd.d = cmds.q[pc.q];
currentCmdFSM.d = cmds.q[pc.q];
} else if(subclk == 1 && is_reading.q == 0 && is_writing.q == 0) {
} else if(subclk == 1 && is_reading_inProgress.q == 0 && is_writing_inProgress.q == 0) {
//interpret
//set them for all commands just set the _has_ flag if reguired
@ -101,10 +158,89 @@ module node (
currentCmd_has_const.d = (currentCmdFSM.q >= currentCmdFSM.JEZ && currentCmdFSM.q <= currentCmdFSM.JLZ) || currentCmd.q.arg_is_const == 1; //last bit of cmd indicates a constant for cmd's that can do both
currentCmd_has_reg.d[0] = (currentCmdFSM.q == currentCmdFSM.MOV || currentCmd.q.arg_is_const == 0); //mov cmd -> at least 1 reg or no constant
currentCmd_has_reg.d[1] = (currentCmdFSM.q == currentCmdFSM.MOV && currentCmd.q.arg_is_const == 0); //mov cmd und arg ist keine constante -> 2 register
} else if(subclk == 2 && is_reading.q == 0 && is_writing.q == 0) {
//mark input as read
is_reading.d = 1;
//set flags for reading and writing
is_reading.d = (currentCmdFSM.q == currentCmdFSM.MOV || ((currentCmdFSM.q == currentCmdFSM.ADD || currentCmdFSM.q == currentCmdFSM.SUB) && currentCmd_has_const.q == 0)); //mov cmd or add/sub in register mode
is_writing.d = (currentCmdFSM.q == currentCmdFSM.MOV); //only mov cmd can write to a register aparently
} else if(subclk == 2 && is_reading_inProgress.q == 0 && is_writing_inProgress.q == 0) {
//mark input as read
if(is_reading.q == 1) {
//do reading stuff
//TODO: this
read_reg = 1;
}
} else if(subclk == 3 && is_writing_inProgress.q == 0) {
//reading
if(is_reading.q == 1) {
read_reg = 1; //try to read the register NOW
is_reading_inProgress.d = ~reg_read.done; //wenn fertig -> kein read mehr in progress, sonst: nächsten zyklus nochmal
}
} else if(subclk == 4 && is_reading_inProgress.q == 0 && is_writing_inProgress.q == 0) {
//calculate
//args
mainarg = currentCmd_has_const.q ? currentCmd_const.q : reg_read.out;
case (currentCmdFSM.q) {
currentCmdFSM.MOV:
to_reg = mainarg;
write_reg = 1;
is_writing_inProgress.d = 1;
currentCmdFSM.JEZ: //jump equals Zero
if (acc.q == 0) {
//jump
pc.d = pc.q + mainarg;
}
currentCmdFSM.JNZ: //jump not equals zero
if(acc.q != 0) {
//jump
pc.d = pc.q + mainarg;
}
currentCmdFSM.JGZ: //jmp greater zero
if(acc.q > 0) {
pc.d = pc.q + mainarg;
}
currentCmdFSM.JLZ: //jmp less zero
if(acc.q < 0) {
pc.d = pc.q + mainarg;
}
currentCmdFSM.JRO: //jmp ro (offset) unconditional
pc.d = pc.q + mainarg;
currentCmdFSM.ADD:
acc.d = acc.q + mainarg;
currentCmdFSM.SUB:
acc.d = acc.q - mainarg;
currentCmdFSM.NEG:
acc.d = -acc.q;
currentCmdFSM.SWP:
bak.d = acc.q; //does this work?
acc.d = bak.q;
currentCmdFSM.SAV:
bak.d = acc.q;
}
} else if(subclk == 7 && is_reading_inProgress.q == 0 && is_writing_inProgress.q == 0) {
//increment pc
if(pc.q + 1 >= GNode.ROWS) {
pc.d = 0; //loop over
} else {
pc.d = pc.q + 1;
}
//reset everything
}
}

View File

@ -6,13 +6,13 @@
*/
global G_nodeCon {
const WIDTH = 10;
const WIDTH = 11;
struct nodeConIn {
write,
read,
enable,
in[WIDTH]
signed in[WIDTH]
}
}
@ -22,7 +22,7 @@ module nodeCon (
input rst, // reset
input<G_nodeCon.nodeConIn> a_in,
output a_out[G_nodeCon.WIDTH],
signed output a_out[GNode.WORDLEN],
output done, //erledigt (blokirung kann uafgehoben werden)
@ -31,9 +31,9 @@ module nodeCon (
input b_enable,
input b_in[WIDTH],*/
input<G_nodeCon.nodeConIn> b_in,
output b_out[G_nodeCon.WIDTH],
signed output b_out[G_nodeCon.WIDTH],
output error
output error //output 1 on deadlock
) {
dff internalBuff[G_nodeCon.WIDTH](#INIT(0), .clk(clk), .rst(rst));

View File

@ -0,0 +1,74 @@
/**
Takes many registers and only reads from ONE selected
*/
module registerDemultiplex (
input clk, // clock
input rst, // reset
input selection[3], //which register? see node.luc for enumeration
input acc[GNode.WORDLEN],
input up[GNode.WORDLEN],
input right[GNode.WORDLEN],
input down[GNode.WORDLEN],
input left[GNode.WORDLEN],
input last[GNode.REGISTERADDRLEN], //CAREFULL! this is NOT a register! this is a address!
input any[GNode.WORDLEN],
output out[GNode.WORDLEN],
output done, //TODO: implement this fully
input read
) {
dff outb[GNode.WORDLEN](.clk(clk), .rst(rst), #INIT(0));
always {
//reading
done = 0;
if(read) {
if(selection == 0) {
outb.d = 0;
done = 1;
} else if(selection == 1) {
outb.d = acc;
done = 1;
} else if(selection == 2) {
outb.d = up;
} else if(selection == 3) {
outb.d = right;
} else if(selection == 4) {
outb.d = down;
} else if(selection == 5) {
outb.d = left;
} else if(selection == 6) {
//inner selection for last register
case (last) {
0: outb.d = 0; //NIL
done = 1;
1: outb.d = acc;
2: outb.d = up;
3: outb.d = right;
4: outb.d = down;
5: outb.d = left;
7: outb.d = 0; //ANY - not implemented correctly!
done = 1;
}
} else if(selection == 7) {
outb.d = any;
} else {
outb.d = 0;
done = 0;
}
} else {
outb.d = 0;
done = 0;
}
out = outb.q;
}
}

View File

@ -1,3 +1,10 @@
/**
Takes a value and many registers and writes the value to one specified register
*/
module registerMultiplex (
input clk, // clock
input rst, // reset
@ -5,54 +12,44 @@ module registerMultiplex (
input selection[3], //which register? see node.luc for enumeration
input acc[GNode.WORDLEN],
input up[GNode.WORDLEN],
input right[GNode.WORDLEN],
input down[GNode.WORDLEN],
input left[GNode.WORDLEN],
input last[GNode.REGISTERADDRLEN], //CAREFULL! this is NOT a register! this is a address!
input any[GNode.WORDLEN],
output acc[GNode.WORDLEN],
output up[GNode.WORDLEN],
output right[GNode.WORDLEN],
output down[GNode.WORDLEN],
output left[GNode.WORDLEN],
input lastadr[GNode.REGISTERADDRLEN], //CAUTION! JUST AN ADDRESS!
output any[GNode.WORDLEN],
output acc_w,
output up_w,
output right_w,
output down_w,
output left_w,
output any_w,
output out[GNode.WORDLEN],
input in[GNode.WORDLEN],
input write,
input read
input write
) {
dff outb[GNode.WORDLEN](.clk(clk), .rst(rst), #INIT(0));
always {
//reading
if(read) {
if(selection == 0) {
outb.d = 0;
} else if(selection == 1) {
outb.d = acc;
} else if(selection == 2) {
outb.d = up;
} else if(selection == 3) {
outb.d = right;
} else if(selection == 4) {
outb.d = down;
} else if(selection == 5) {
outb.d = left;
} else if(selection == 6) {
if(last == 0) { //inenr selection for last
}
} else if(selection == 7) {
outb.d = any;
} else {
outb.d = 0;
}
} else {
outb.d = 0;
}
out = outb.q;
acc_w = write && selection == 1;
up_w = write && selection == 2;
right_w = write && selection == 3;
down_w = write && selection == 4;
left_w = write && selection == 5;
any_w = write && selection == 7;
if(write) {
//TODO: fwd in to the register and set writing flags
acc = selection == 1 ? in : 0;
up = selection == 2 ? in : 0;
right = selection == 3 ? in : 0;
down = selection == 4 ? in : 0;
left = selection == 5 ? in : 0;
any = selection == 7 ? in : 0;
if(write && selection == 6) {
//last register
//TODO: this
}
}
}
}

View File

@ -1,6 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project name="tis-100" board="Mojo" language="Lucid" version="2">
<files>
<src>registerDemultiplex.luc</src>
<component>counter.luc</component>
<src>node.luc</src>
<src>tis100.luc</src>
<src top="true">mojo_top.luc</src>