global GNode { const ROWS = 14; //number of commands to hold const CMDLEN = 16; //number of bits a command is in size const WORDLEN = 11; //bits to store a number (-999 to 999) const REGISTERADDRLEN = 3; //bits to address a register struct cmd { cmd[4], arg_is_const, //1 = argument is a 11bit signed integer, 0 argument is a register number args[11] //11 bit number or at most 2 reigster (mov cmd) } } /** Register numbers: 0 = NIL 1 = ACC 2 = UP 3 = RIGHT 4 = DOWN 5 = LEFT 6 = LAST 7 = ANY Subclk: 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 cycles are skiped, if node is waiting for another node to read or write a connection */ module node ( input clk, // clock input rst, // reset input up_in[GNode.WORDLEN], output up_out, input right_in[GNode.WORDLEN], output right_out, input down_in[GNode.WORDLEN], output down_out, input left_in[GNode.WORDLEN], output left_out, output error, input subclk ) { .clk(clk), .rst(rst) { dff pc[4](#INIT(0)); //program counter dff 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 currentCmd; fsm currentCmdFSM = {MOV, // 2 args: 1const, 1reg or 2 reg 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)); } always { error = 0; if(subclk == 0 && is_reading.q == 0 && is_writing.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) { //interpret //set them for all commands just set the _has_ flag if reguired currentCmd_reg.d[0] = currentCmd.q.args[ GNode.REGISTERADDRLEN -1 : 0]; //3 LSB bytes = register 1 currentCmd_reg.d[1] = currentCmd.q.args[(2*GNode.REGISTERADDRLEN) -1 : GNode.REGISTERADDRLEN]; //3 next bytes = register 2 currentCmd_const.d = currentCmd.q.args; //set the _has_ flags 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; } }