module nonvontop(reset, f_in,f_out,f_alert,fclk,f_write,f_read,f_en,f_kill,send_in, //Father connections l_in,l_out,l_alert,lclk,l_write,l_read,l_en,l_kill,l_send, //Left child connections r_in,r_out,r_alert,rclk,r_write,r_read,r_en,r_kill,r_send); //Right child connections //PE input reset; //external bus lines - 3 8-bit wide buses - F(father),L(left child), and R(right child) input [7:0]f_in; //8-bit Father-bus output wire [7:0] f_out; output wire f_alert; //alert output to propagate/initiate upstream alert input fclk; //input clock from host input f_write; //essentially a "downstream enable" from the host input f_read; input f_en; input f_kill; input send_in; input [7:0]l_in; //8-bit Left-Child bus output [7:0]l_out; wire [7:0] l_out; input l_alert; //alert input for left-child to send "upstream" (has priority over right side) output lclk; //left-child clock propagated from fclk wire lclk; output wire l_write; //propagated f_write output wire l_read; output wire l_en; output wire l_kill; output reg l_send; input [7:0]r_in; //8-bit Right_child bus output [7:0]r_out; wire [7:0]r_out; input r_alert; //alert input for right-child to send "upstream" output wire rclk; //right-child clock propagated from fclk output wire r_write; //propagated f_write output wire r_read; output wire r_en; output wire r_kill; output reg r_send; //internal storage elements reg [7:0]pe_ram[0:63]; reg [7:0]A8; reg [7:0]B8; reg [7:0]C8; reg [7:0]X8; reg [7:0]Y8; reg [7:0]Z8; reg [7:0]IO8; reg [7:0]MAR; reg [7:0] temp_out; reg [2:0] mode; //set to 01 if ready to receive broadcast8, 10=broadcast1, 00=idle reg EN1,IO1,Z1,Y1,X1,C1,B1,A1; //internal buses wire i_alert; //internal alert signal reg [2:0] oprnd; //communications switch assign i_alert = ((A1 | (mode==3'b100)) & (EN1==1'b1)); assign rclk=fclk; assign r_write=f_write; assign r_out[7:0]= ((mode==3'b101)|(mode==3'b110)|(mode==3'b111)) ? temp_out[7:0] : f_in[7:0]; assign r_en = f_en; assign r_read = f_read; assign lclk=fclk; assign l_write=f_write; assign l_out[7:0]= ((mode==3'b101)|(mode==3'b110)|(mode==3'b111)) ? temp_out[7:0] : f_in[7:0]; assign l_en = f_en; assign l_read = f_read; assign f_out[7:0] = EN1 ? temp_out[7:0] : (l_alert ? l_in[7:0] : r_in[7:0]); //*should* work right: outputs own value until disabled, then outputs left child input, //then outputs right child input (both inputs should never =1 in a valid stable state) assign r_kill = f_kill | l_alert | i_alert; //kill things on the right side if father issues kill or left child issues alert, or you are alerting assign f_alert= i_alert | l_alert | r_alert; //Alert father node if current node or either child node is raising alert assign l_kill = f_kill; //kill left node if kill signal comes from father node //ALU //Bits 7:3 of the data bus hold the opcode //Bits 2:0 of the data bus hold the register always@(posedge fclk) if (reset) begin mode <= 3'b000; A8 <= 0; B8 <= 0; C8 <= 0; X8 <= 0; Y8 <= 0; Z8 <= 0; MAR <= 0; IO8 <= 0; A1 <= 0; B1 <= 0; C1 <= 0; X1 <= 0; Y1 <= 0; Z1 <= 0; IO1 <= 0; EN1 <= 1; //i_alert <= 0; l_send <= 1'b0; r_send <= 1'b0; temp_out <= 0; oprnd <= 0; end else case(mode) 3'b000:if ((f_write==1'b1) & (f_en==1'b1) & (EN1==1'b0) & (f_in[7:3]==26)) //catch "ENABLE" case EN1 <= 1'b1; else if ((f_write==1'b1) & (f_en==1'b1) & (EN1==1'b0) & (f_in[7:3]==24)) //catch RECV8 begin temp_out <= A8; oprnd <= f_in[2:0]; mode <= 3'b110; end else if ((f_write==1'b1) & (f_en==1'b1) & (EN1==1'b0) & (f_in[7:3]==25)) //catch RECV1 begin mode <= 3'b111; oprnd <= f_in[2:0]; temp_out <= {7'b0000000,A1}; end else if ((EN1==1'b1) & (f_write==1'b1) & (f_en==1'b1)) begin //process normally case(f_in[7:3]) 0: begin case(f_in[2:0]) //LOADA8 0:A8<=A8; 1:A8<=B8; 2:A8<=C8; 3:A8<=X8; 4:A8<=Y8; 5:A8<=Z8; 6:A8<=MAR; 7:A8<=IO8; endcase // mode <= 3'b000; end 1:begin case(f_in[2:0]) //LOADB8 0:B8<=A8; 1:B8<=B8; 2:B8<=C8; 3:B8<=X8; 4:B8<=Y8; 5:B8<=Z8; 6:B8<=MAR; 7:B8<=IO8; endcase // mode <= 3'b000; end 2:begin case(f_in[2:0]) //LOADA1 0:A1<=A1; 1:A1<=B1; 2:A1<=C1; 3:A1<=X1; 4:A1<=Y1; 5:A1<=Z1; 6:A1<=IO1; 7:A1<=EN1; endcase // mode <= 3'b000; end 3:begin case(f_in[2:0]) //LOADB1 0:B1<=A1; 1:B1<=B1; 2:B1<=C1; 3:B1<=X1; 4:B1<=Y1; 5:B1<=Z1; 6:B1<=IO1; 7:B1<=EN1; endcase // mode <= 3'b000; end 4:begin case(f_in[2:0]) //STOREA8 0:A8<=A8; 1:B8<=A8; 2:C8<=A8; 3:X8<=A8; 4:Y8<=A8; 5:Z8<=A8; 6:MAR<=A8; 7:IO8<=A8; endcase // mode <= 3'b000; end 5:begin case(f_in[2:0]) //STOREB8 0:A8<=B8; 1:B8<=B8; 2:C8<=B8; 3:X8<=B8; 4:Y8<=B8; 5:Z8<=B8; 6:MAR<=B8; 7:IO8<=B8; endcase // mode <= 3'b000; end 6:begin case(f_in[2:0]) //STOREA1 0:A1 <=A1; 1:B1 <=A1; 2:C1 <=A1; 3:X1 <=A1; 4:Y1 <=A1; 5:Z1 <=A1; 6:IO1 <=A1; 7:EN1 <=A1; endcase // EN1 <= A1; // mode <= 3'b000; end 7:begin case(f_in[2:0]) //STOREB1 0:A1 <=B1; 1:B1 <=B1; 2:C1 <=B1; 3:X1 <=B1; 4:Y1 <=B1; 5:Z1 <=B1; 6:IO1 <=B1; 7:EN1 <=B1; endcase // mode <= 3'b000; end 8:begin A8 <= pe_ram[MAR[5:0]]; //READRAM // mode <= 3'b000; end 9:begin pe_ram[MAR[5:0]] <= A8; //WRITERAM // mode <= 3'b000; end 10: begin //ADD1 A1 <= (A1 ^ B1 ^ C1); C1 <= ((A1 & B1) | (A1 & C1) | (B1 & C1)); // mode <= 3'b000; end 11: begin //SUB1 A1 <= (A1 ^ (~B1) ^ C1); C1 <= ((A1 & (~B1)) | (A1 & C1) | ((~B1) & C1)); // mode <= 3'b000; end 12: begin //ROTRA A8 <= {A1,A8[7:1]}; A1 <= A8[0]; // mode <= 3'b000; end 13: begin //ROTLA A8 <= {A8[6:0],A1}; A1 <= A8[7]; // mode <= 3'b000; end 14: begin //ROTRB B8 <= {B1,B8[7:1]}; B1 <= B8[0]; // mode <= 3'b000; end 15: begin //ROTLB B8 <= {B8[6:0],B1}; B1 <= B8[7]; // mode <= 3'b000; end 16:begin case(f_in[2:0]) //LOGIC1 0: A1 <= 1'b0; //CLEAR 1: A1 <= 1'b1; //SET 2: A1 <= ~A1; //negate 3: A1 <= A1 & B1; //AND 4: A1 <= A1 | B1; //OR 5: A1 <= A1 ^ B1; //XOR 6: A1 <= (A1 & B1) | (~A1 & ~B1); //EQU 7: A1 <= ~(A1 & B1); //NAND endcase // mode <= 3'b000; end 17:begin case(f_in[2:0]) //LOGIC2 0: A1 <= ~(A1 | B1); //NOR default: A1 <= A1; endcase // mode <= 3'b000; end 18: mode <= 3'b010; //BROADCAST8 19: mode <= 3'b011; //BROADCAST1 20: begin //REPORT8 temp_out <= A8; //i_alert <= 1'b1; mode <= 3'b100; end 21: begin //REPORT1 temp_out <= {7'b0000000,A1}; //i_alert <= 1'b1; mode <= 3'b100; end 22: begin //SEND8 mode <= 3'b101; //go to SEND mode oprnd <= 0; temp_out <= A8; if (f_in[0]==0) // instr[0]=0 => send to right child r_send <= 1'b1; else l_send <= 1'b1; //else send to left child end 23: begin //SEND1 mode <= 3'b101; //go to SEND mode oprnd <= 1; temp_out <= {7'b0000000,A1}; if (f_in[0]==0) r_send <= 1'b1; else l_send <= 1'b1; end 24: begin temp_out <= A8; oprnd <= f_in[2:0]; mode <= 3'b110; //RECV8 end 25: begin mode <= 3'b111; //RECV1 oprnd <= f_in[2:0]; temp_out <= {7'b0000000,A1}; end 26: EN1 <= 1'b1; //ENABLE 27: begin A1 <= (A8==B8); //COMPARE B1 <= (A8>B8); end 28: begin //RESOLVE // EN1 <= A1; mode <= 3'b001; //i_alert <= A1; end default: mode <= 3'b000; endcase end 3'b001: begin //RESOLVE Mode // EN1 <= ~(f_kill | l_alert | (~EN1) ); //die if f_kill==1, l_alert==1 or you were already disabled A1 <= ~(f_kill | l_alert | (~A1) ); //i_alert <= 0; mode <= 3'b000; //return to idle mode end 3'b010: begin //broadcast8 mode A8[7:0] <= f_in[7:0]; mode <= 3'b000; end 3'b011: begin //Broadcast1 mode A1 <= f_in[0]; mode <= 3'b000; end 3'b100: if ((f_en==1'b1) & (f_read==1'b1)) begin //Report Mode mode <= 3'b000; //i_alert <= 1'b0; end 3'b101: begin //SEND mode if ((send_in==1'b1) & (oprnd==0)) //if someone is sending to you, grab byte and place in IO8 IO8 <= f_in[7:0]; else if ((send_in==1'b1) & (oprnd==1)) IO1 <= f_in[0]; mode <= 3'b000; l_send <= 1'b0; r_send <= 1'b0; end 3'b110: begin case(oprnd) //RECV8 mode 0: A8[7:0] <= l_in[7:0]; //0=left child 1: A8[7:0] <= r_in[7:0]; //1=right child default: A8[7:0] <= f_in[7:0]; //else grab from parent endcase mode <= 3'b000; end 3'b111: begin //RECV1 mode case(oprnd) 0: A1 <= l_in[0]; 1: A1 <= r_in[0]; default: A1 <= f_in[0]; endcase mode <= 3'b000; end endcase endmodule