diff --git a/Partial_sum_adder.sv b/Partial_sum_adder.sv index 0e53777..89cbf9b 100644 --- a/Partial_sum_adder.sv +++ b/Partial_sum_adder.sv @@ -1,21 +1,18 @@ //unfinished `timescale 1ns/100ps import SystemVerilogCSP::*; -module Partial_sum_adder ( - interface in, - interface out - ); +module Partial_sum_adder (interface in,out); parameter adder_number=2'b00; //00--adder1,01--adder2,10--adder3 parameter adder3_num=2'b10; parameter WIDTH=34; parameter memb_p_WIDTH=8; -parameter threshold=64; -parameter PE1_addr=4'b1000; -parameter PE2_addr=4'b1001; +parameter threshold=16; +parameter PE1_addr=4'b0010; +parameter PE2_addr=4'b0110; parameter PE3_addr=4'b1010; parameter Adder_addr=4'b0110; parameter Mem_addr=4'b0000; -parameter WR_addr=4'b0001; +parameter WR_addr=4'b0000; parameter Out_to_Mem_zeros={20{1'b0}}; parameter MP_to_Mem_zeros={16{1'b0}}; parameter count_number=2'b10; @@ -23,7 +20,7 @@ parameter done_singal=4'b1111; parameter mem_p_type=2'b10; parameter output_spike_type=2'b11; logic [WIDTH-1:0] value; -logic [memb_p_WIDTH-1:0] partial_PE1,partial_PE2,partial_PE3,membrane_potential; +reg [memb_p_WIDTH-1:0] partial_PE1,partial_PE2,partial_PE3,membrane_potential; logic output_spike; logic [WIDTH-1:0] out_packet; logic [3:0]output_spike_addr; @@ -68,6 +65,7 @@ begin begin partial_PE1=value[7:0]; //flag_PE1_received=1;//count=count+1; + $display("firstRe---if--partial_PE1=%b",partial_PE1); end if (value[WIDTH-1:WIDTH-4]==PE2_addr) //src_addr=PE2 @@ -85,6 +83,7 @@ begin begin membrane_potential=value[WIDTH-27:WIDTH-34]; end + $display("%m first receive----packet:%b",value); //second receive @@ -93,6 +92,7 @@ begin begin partial_PE1=value[7:0]; //flag_PE1_received=1;//count=count+1; + //$display("secondRe---if--partial_PE1=%b",partial_PE1); end if (value[WIDTH-1:WIDTH-4]==PE2_addr) //PE2 @@ -110,12 +110,14 @@ begin begin membrane_potential=value[WIDTH-27:WIDTH-34]; end + $display("%m second receive----packet:%b",value); //third receive in.Receive(value);//PE3 if (value[WIDTH-1:WIDTH-4]==PE1_addr) //src_addr=PE1_addr begin partial_PE1=value[7:0]; + //$display("thirdRe---if--partial_PE1=%b",partial_PE1); //flag_PE1_received=1;//count=count+1; end @@ -135,6 +137,7 @@ begin begin membrane_potential=value[WIDTH-27:WIDTH-34]; end + $display("%m third receive----packet:%b",value); //----------------------------------------------------------------------------------------------- @@ -146,6 +149,7 @@ begin if (value[WIDTH-1:WIDTH-4]==PE1_addr) //src_addr=PE1_addr begin partial_PE1=value[7:0]; + //$display("forthRe---if--partial_PE1=%b",partial_PE1); //flag_PE1_received=1;//count=count+1; end @@ -163,18 +167,23 @@ begin if(value[WIDTH-1:WIDTH-4]==WR_addr)//src addr=WR_addr if(value[WIDTH-9:WIDTH-10]==mem_p_type)//type=mem_p_type begin - membrane_potential=value[WIDTH-27:WIDTH-34]; + membrane_potential=value[WIDTH-27:WIDTH-34];//34-27=7:0 end + $display("partial_PE1:%b---partial_PE2:%b---partial_PE3:%b---mem_p:%b",partial_PE1,partial_PE2,partial_PE3,membrane_potential); membrane_potential=partial_PE1+partial_PE2+partial_PE3+membrane_potential; - end + //$display("partial_PE1:%b---partial_PE2:%b---partial_PE3:%b---mem_p:%b",partial_PE1,partial_PE2,partial_PE3,membrane_potential); + $display("%m forth receive----packet:%b",value); + end + else //first input map begin membrane_potential=partial_PE1+partial_PE2+partial_PE3; + $display("partial_PE1:%b---partial_PE2:%b---partial_PE3:%b---",partial_PE1,partial_PE2,partial_PE3); end //generate output_spike 1-bit - if (membrane_potential>threshold) + if (membrane_potential>=threshold) begin output_spike=1; membrane_potential=membrane_potential-threshold; @@ -184,25 +193,27 @@ begin output_spike=0; end - + //$display("partial_PE1:%b---partial_PE2:%b---partial_PE3:%b---",partial_PE1,partial_PE2,partial_PE3); out_packet={Adder_addr,Mem_addr,mem_p_type,MP_to_Mem_zeros,membrane_potential}; - $display("Membrane_P after compare%b",out_packet); + $display("add_num:%m---Membrane_P after compare%b",out_packet); //4+4+2+16*zeros+8bits //mem_p_type=10 out.Send(out_packet); if (output_spike==1) begin - output_spike_addr={adder_number,count};//row-col + output_spike_addr={count,adder_number};//row-col out_packet={Adder_addr,Mem_addr,output_spike_type,Out_to_Mem_zeros,output_spike_addr};//4+4+22+4 //output_spike_type=10 - $display("output_spike no_zero_send:%b",out_packet); + $display("add_num:%m---output_spike no_zero_send:%b,row:%b---col:%b",out_packet,count,adder_number); out.Send(out_packet); end if (adder_number==adder3_num)//every time when adder3 finish calculating, send done_singal begin - output_spike_addr=done_singal; - out_packet={Adder_addr,Mem_addr,output_spike_type,Out_to_Mem_zeros,output_spike_addr}; + //output_spike_addr=done_singal; + //out_packet={Adder_addr,Mem_addr,output_spike_type,Out_to_Mem_zeros,output_spike_addr}; + out_packet={Adder_addr,Mem_addr,output_spike_type,Out_to_Mem_zeros,done_singal}; out.Send(out_packet);//send done_singal + $display("add_num:%m---Done signal Sent!!!"); end /***if (count==count_number)//count=2'b10 begin diff --git a/SNN_Accelerator123.sv b/SNN_Accelerator123.sv new file mode 100644 index 0000000..af0aadc --- /dev/null +++ b/SNN_Accelerator123.sv @@ -0,0 +1,208 @@ +`timescale 1ns/1ps +import SystemVerilogCSP::*; +module SNN_Accelerator123; +parameter WIDTH=34; +parameter FL=2; +parameter BL=1; +parameter x1=2'b00; +parameter x2=2'b01; +parameter x3=2'b10; +parameter y1=2'b00; +parameter y2=2'b01; +parameter y3=2'b10; +parameter adder1_num=2'b00; +parameter adder2_num=2'b01; +parameter adder3_num=2'b10; +parameter Adder1_addr=4'b0001; +parameter Adder2_addr=4'b0101; +parameter Adder3_addr=4'b1001; + +Channel #(.hsProtocol(P4PhaseBD),.WIDTH(34)) intf [49:0] (); + + +router #(.WIDTH(WIDTH), + .FL(FL), + .BL(BL), + .Xaddr(x1), + .Yaddr(y1)) +router1 (.N_in(intf[49]), + .N_out(intf[49]), + .S_in(intf[5]), + .S_out(intf[4]), + .E_in(intf[1]), + .E_out(intf[0]), + .W_in(intf[49]), + .W_out(intf[49]), + .P_in(intf[3]), + .P_out(intf[2])); + + +router #(.WIDTH(WIDTH), + .FL(FL), + .BL(BL), + .Xaddr(x2), + .Yaddr(y1)) +router2 (.N_in(intf[49]), + .N_out(intf[49]), + .S_in(intf[11]), + .S_out(intf[10]), + .E_in(intf[7]), + .E_out(intf[6]), + .W_in(intf[0]), + .W_out(intf[1]), + .P_in(intf[9]), + .P_out(intf[8])); + + + +router #(.WIDTH(WIDTH), + .FL(FL), + .BL(BL), + .Xaddr(x3), + .Yaddr(y1)) +router3 (.N_in(intf[49]), + .N_out(intf[49]), + .S_in(intf[22]), + .S_out(intf[21]), + .E_in(intf[49]), + .E_out(intf[49]), + .W_in(intf[6]), + .W_out(intf[7]), + .P_in(intf[20]), + .P_out(intf[19])); + +router #(.WIDTH(WIDTH), + .FL(FL), + .BL(BL), + .Xaddr(x1), + .Yaddr(y2)) +router4 (.N_in(intf[4]), + .N_out(intf[5]), + .S_in(intf[28]), + .S_out(intf[27]), + .E_in(intf[24]), + .E_out(intf[23]), + .W_in(intf[49]), + .W_out(intf[49]), + .P_in(intf[26]), + .P_out(intf[25])); + + +router #(.WIDTH(WIDTH), + .FL(FL), + .BL(BL), + .Xaddr(x2), + .Yaddr(y2)) +router5 (.N_in(intf[10]), + .N_out(intf[11]), + .S_in(intf[34]), + .S_out(intf[33]), + .E_in(intf[30]), + .E_out(intf[29]), + .W_in(intf[23]), + .W_out(intf[24]), + .P_in(intf[32]), + .P_out(intf[31])); + + +router #(.WIDTH(WIDTH), + .FL(FL), + .BL(BL), + .Xaddr(x3), + .Yaddr(y2)) +router6 (.N_in(intf[21]), + .N_out(intf[22]), + .S_in(intf[38]), + .S_out(intf[37]), + .E_in(intf[49]), + .E_out(intf[49]), + .W_in(intf[29]), + .W_out(intf[30]), + .P_in(intf[36]), + .P_out(intf[35])); + + +router #(.WIDTH(WIDTH), + .FL(FL), + .BL(BL), + .Xaddr(x1), + .Yaddr(y3)) +router7 (.N_in(intf[27]), + .N_out(intf[28]), + .S_in(intf[49]), + .S_out(intf[49]), + .E_in(intf[40]), + .E_out(intf[39]), + .W_in(intf[49]), + .W_out(intf[49]), + .P_in(intf[42]), + .P_out(intf[41])); + +router #(.WIDTH(WIDTH), + .FL(FL), + .BL(BL), + .Xaddr(x2), + .Yaddr(y3)) +router8 (.N_in(intf[33]), + .N_out(intf[34]), + .S_in(intf[49]), + .S_out(intf[49]), + .E_in(intf[44]), + .E_out(intf[43]), + .W_in(intf[39]), + .W_out(intf[40]), + .P_in(intf[46]), + .P_out(intf[45])); + +router #(.WIDTH(WIDTH), + .FL(FL), + .BL(BL), + .Xaddr(x3), + .Yaddr(y3)) +router9 (.N_in(intf[37]), + .N_out(intf[38]), + .S_in(intf[49]), + .S_out(intf[49]), + .E_in(intf[49]), + .E_out(intf[49]), + .W_in(intf[43]), + .W_out(intf[44]), + .P_in(intf[48]), + .P_out(intf[47])); + + + +memory_wrapper memory_wrapper1(.toMemRead(intf[12]), .toMemWrite(intf[13]), + .toMemT(intf[14]), + .toMemX(intf[15]),.toMemY(intf[16]), + .toMemSendData(intf[17]), + .fromMemGetData(intf[18]), + .toNOC(intf[3]),.fromNOC(intf[2])); +memory memory1(.read(intf[12]), + .write(intf[13]), + .T(intf[14]), + .x(intf[15]), + .y(intf[16]), + .data_out(intf[18]), + .data_in(intf[17])); +data_bucket db1 (.r(intf[8])); +data_bucket db2 (.r(intf[19])); +Partial_sum_adder #(.adder_number(adder1_num),.Adder_addr(Adder1_addr)) + adder1 (.in(intf[25]),.out(intf[26])); +Partial_sum_adder #(.adder_number(adder2_num),.Adder_addr(Adder2_addr)) + adder2(.in(intf[31]),.out(intf[32])); +Partial_sum_adder #(.adder_number(adder3_num),.Adder_addr(Adder3_addr)) + adder3(.in(intf[35]),.out(intf[36])); +pe pe1(.packet_in(intf[41]),.packet_out(intf[42])); +pe pe2(.packet_in(intf[45]),.packet_out(intf[46])); +pe pe3(.packet_in(intf[47]),.packet_out(intf[48])); + +initial begin +#20000; +$stop; + + +end +endmodule + + diff --git a/SystemVerilogCSP.sv b/SystemVerilogCSP.sv new file mode 100644 index 0000000..f28daa4 --- /dev/null +++ b/SystemVerilogCSP.sv @@ -0,0 +1,322 @@ +//------------------------------------------------------------------------------------------------- +// Written by Arash Saifhashemi, saifhash@usc.edu +// SystemVerilogCSP: Channel interface for modeling channel based asynchronous circuits +// USC Asynchronous CAD/VLSI Group +// University of Southern California +// http://async.usc.edu +//------------------------------------------------------------------------------------------------- +`timescale 1ns/1fs +// uncomment the following line to enable stall calculation and display +//`define displayStalls 1 +//uncomment the following line for automatic deadlock detection +`define detectDeadlock 1 +`define defaultWatchDogTime 1000ns + +package SystemVerilogCSP; + typedef enum {idle, r_pend, s_pend, s12m_pend} ChannleStatus; + typedef enum {P2PhaseBD, P4PhaseBD, P1of2, P1of4} ChannelProtocol; + typedef enum {ZERO, ONE, NUTRAL} V1of2; + typedef logic [4] Channel1Of4 ; +endpackage : SystemVerilogCSP +//------------------------------------------------------------------------------------------------- +import SystemVerilogCSP::*; +//------------------------------------------------------------------------------------------------- +interface Channel; + parameter SHARED = 0; + parameter WIDTH = 34; + parameter ChannelProtocol hsProtocol = P2PhaseBD; + parameter NUMBER_OF_RECEIVERS = 1; +`ifdef detectDeadlock + time lastSendEvent = 0; + time lastReceiveEvent = 0; +`endif + ChannleStatus status = idle; //Stores the status of a channel + logic req=0, ack=0, e=1; //Handshaking signals + logic oReq, oAck, oE; //Shadow handshaking signals + + logic hsSenderPhase=1; + logic hsReceiverPhase=1; + + logic [WIDTH-1:0] data=0, data0=0,data1=0; //Actual data being communicated + logic [WIDTH-1:0] oData, oData0,oData1; //Actual data being communicated + logic _RESET = 1; + + Channel1Of4 [((WIDTH+1)/2)-1:0] data_1of4; + integer receiveCounter =0; + semaphore receivers = new(0); //Mehrdad: It seems this semaphore is not in use + genvar i; + + always @oReq req = oReq; + always @oAck ack = oAck; + always @oData data = oData; + always @oData0 data0 = oData0; + always @oData1 data1 = oData1; + always @oE ack=~oE; + always @ack e = ~ack; + //always @_RESET ack=~RESET; + +`ifdef detectDeadlock + always + begin + # (`defaultWatchDogTime); + fork + if(status==s_pend) + begin + if(($time - lastSendEvent) > `defaultWatchDogTime) + begin + #(lastSendEvent - ($time - 2*`defaultWatchDogTime)) $display("###Deadlock Detected on %m @ %t",lastSendEvent); + wait(0); + end + end + if(status==r_pend) + begin + if(($time - lastReceiveEvent) > `defaultWatchDogTime) + begin + #(lastReceiveEvent - ($time - 2*`defaultWatchDogTime)) $display("###Deadlock Detected on %m @ %t",lastReceiveEvent); + wait(0); + end + end + join + end +`endif +//------------------------------------------------------------------------------------------------- +function Channel1Of4 [((WIDTH+1)/2)-1:0] SingleRailToP1of4 (); + for (integer i = 0 ; i <= WIDTH-2 ; i+=2) + begin + case ({data [i+1], data[i]}) + 2'b00: data_1of4[i/2] = 4'b0001; + 2'b01: data_1of4[i/2] = 4'b0010; + 2'b10: data_1of4[i/2] = 4'b0100; + 2'b11: data_1of4[i/2] = 4'b1000; + endcase + end + SingleRailToP1of4 = data_1of4; +endfunction +//------------------------------------------------------------------------------------------------- +function logic [WIDTH-1:0] P1of4ToSingleRail (); + for (integer i = 0 ; i <= WIDTH-2 ; i+=2) + begin + case ( data_1of4 [i/2]) + 4'b0001: data[i/2] = 2'b00; + 4'b0010: data[i/2] = 2'b01; + 4'b0100: data[i/2] = 2'b10; + 4'b1000: data[i/2] = 2'b11; + endcase + end + P1of4ToSingleRail = data_1of4; +endfunction +//------------------------------------------------------------------------------------------------- +//Communication Action Tasks +//------------------------------------------------------------------------------------------------- +task Send (input logic[WIDTH-1:0] d); +`ifdef displayStalls +time start,stall; +start = $time; +`endif +`ifdef detectDeadlock +lastSendEvent = $time; +`endif + if(hsProtocol == P4PhaseBD || hsProtocol == P1of2) + begin + data = d; + data0 = ~d; + data1 = d; + req = 1; + status = s_pend; //Set the status to s_pend before wait + wait (ack == 1 ); + data0 = 0; + data1 = 0; + req = 0; + wait (ack == 0 ); + status = idle; + end + else if (hsProtocol == P2PhaseBD ) + begin + data = d; + data0 = ~d; + req = hsSenderPhase; + status = s_pend; //Set the status to s_pend before wait + wait (ack == hsSenderPhase ); + status = idle; + hsSenderPhase = ~hsSenderPhase; + end +`ifdef displayStalls +stall = $time - start; +if(stall != 0) $display("### %m Stalled(%d) @ %t",stall,$time); +`endif +endtask +//------------------------------------------------------------------------------------------------- +task SplitSend (input logic[WIDTH-1:0] d, input integer part, input integer FL = 0); + case(hsProtocol) + P1of2: P4PhaseBD: + begin + case (part) + 1: begin + data <= #FL d; + data0 <= #FL ~d; + data1 <= #FL d; + req = 1; + status = s_pend; //Set the status to s_pend before wait + end + 2: begin + wait (ack == 1 ); + end + 3: begin + data0 = 0; + data1 = 0; + req = 0; + end + 4: begin + wait (ack == 0 ); + status = idle; + end + endcase + end //P1of2, P4PhaseBD + P2PhaseBD: + begin + case (part) + 1: begin + data = d; //Mehrdad: Do we need to have #FL here is well? + data0 = ~d; + req = hsSenderPhase; + status = s_pend; //Set the status to s_pend before wait + end + 2: begin + wait (ack == hsSenderPhase ); + status = idle; + hsSenderPhase = ~hsSenderPhase; + end + endcase + end //P2PhaseBD + endcase +endtask +//------------------------------------------------------------------------------------------------- +task Receive (output logic[WIDTH-1:0] d); +`ifdef displayStalls +time start,stall; +start = $time; +`endif +`ifdef detectDeadlock +lastReceiveEvent = $time; +`endif + if (hsProtocol==P4PhaseBD || hsProtocol == P1of2) + begin + status = r_pend; + if (hsProtocol == P1of2 ) + wait ( (&(data0 | data1)==1) ); + else + begin + wait (req == 1 ); + if (SHARED) + req = 'z; // Inhibit other receivers from receiving + end + d = data1; + data = data1; + //If the last receiver: + if (receiveCounter == NUMBER_OF_RECEIVERS-1) + begin + ack = 1; + if (hsProtocol == P1of2) + wait ( (|(data0 | data1)==0) ); + else + wait (req == 0 ); + ack = 0; + status = idle; + receiveCounter=0; + #0; //Release the control to other processes + end + else // If not the last receiver wait for other receivers to finish + begin + status = s12m_pend; + receiveCounter++; + wait (receiveCounter ==0); //Wait for other Receivers to finish. + end + end //P4PhaseBD or P1of2 + + else if (hsProtocol == P2PhaseBD) + begin + status = r_pend; //Set the status to r_pend before wait + wait (req == hsReceiverPhase ); + if (SHARED) + req = 'z; // Inhibit other receivers from receiving + d = data; + //Is this the last receiver? + if (receiveCounter == NUMBER_OF_RECEIVERS-1) + begin + ack = hsReceiverPhase; + status = idle; + receiveCounter=0; + #0; //Release the control to other processes + hsReceiverPhase=~hsReceiverPhase; + end + else //Wait for all other receivers to finish receiving + begin + status = s12m_pend; + receiveCounter++; + wait (receiveCounter ==0 ); + #0; //Release the control to other processes + end + end +`ifdef displayStalls +stall = $time - start; +if(stall != 0) $display("### %m Stalled(%d) @ %t",stall,$time); +`endif +endtask +//------------------------------------------------------------------------------------------------- +task SplitReceive (output logic[WIDTH-1:0] d, input integer part); + case(hsProtocol) + P1of2: + P4PhaseBD: + begin + case (part) + 1: begin + status = r_pend; + if (hsProtocol == P1of2 ) + wait ( (&(data0 | data1)==1) ); + else + wait (req == 1 ); + end + 2: begin + d = data1; + ack = 1; + end + 3: begin + if (hsProtocol == P1of2 ) + wait ( (|(data0 | data1)==0) ); + else + wait (req == 0 ); + end + 4:begin + ack = 0; + status = idle; + end + endcase + end //P1of2 or P4PhaseBD + P2PhaseBD: begin + case (part) + 1: begin + status = r_pend; //Set the status to r_pend before wait + wait (req == hsReceiverPhase ); + d = data; + end + 2: begin + ack = hsReceiverPhase; + status = idle; + hsReceiverPhase = ~ hsReceiverPhase; + end + endcase + end //P2PhaseBD + endcase +endtask +//------------------------------------------------------------------------------------------------- +task Peek (output logic[WIDTH-1:0] d); + wait (status != idle && status != r_pend ); + d = data; +endtask +//------------------------------------------------------------------------------------------------- +//probe_wait_input: used on an input/output port. wait until other party starts communication +task Probe_wait_input () ; + wait (status != idle); +endtask +//------------------------------------------------------------------------------------------------- +endinterface: Channel diff --git a/arbiter+++packet.sv b/arbiter+++packet.sv new file mode 100644 index 0000000..54b7aa3 --- /dev/null +++ b/arbiter+++packet.sv @@ -0,0 +1,270 @@ +`timescale 1ns/1fs +import SystemVerilogCSP::*; + +module arbiter_pipeline_2 (interface A,B,W,O); +parameter FL=2; +parameter BL=2; +parameter WIDTH=2; +int winner; +logic [WIDTH-1:0]a,b; +always begin + wait (A.status != idle || B.status != idle); + if (A.status != idle && B.status != idle) begin + winner = ($urandom%2 == 0) ? 0 : 1; + //$display("1.Both A&B are not idle, winner=%b @ %t",winner,$time); + end + else if (A.status != idle) begin + winner = 0; + //$display("1.A is not idle(B is idle), winner=%b @ %t",winner,$time); + end + else begin // B.status != idle + winner = 1; + //$display("1.B is not idle(A is idle), winner=%b @ %t",winner,$time); + end + if (winner ==0) begin + A.Receive(a); + //$display("1.A receive %b @ %t",a,$time); + #FL; + fork + begin + W.Send(0); + //$display("1.W sends 0 from A @ %t",$time); + end + begin + O.Send(0); + //$display("1.O sends 0 from A @ %t",$time); + end + join + #BL; + end + else begin + B.Receive(b); #FL; + fork + begin + W.Send(1); + //$display("1.W sends 1 from B @ %t",$time); + end + begin + O.Send(1); + //$display("1.O sends 1 from B @ %t",$time); + end + join + #BL; + end +end//always +endmodule + + + +module arbiter_slackless_2 (interface A,B,W); +parameter FL=2; +parameter BL=2; +parameter WIDTH=2; +int winner; +logic [WIDTH-1:0]a,b; +always begin + wait (A.status != idle || B.status != idle); + if (A.status != idle && B.status != idle) begin + winner = ($urandom%2 == 0) ? 0 : 1; + //$display("2.Both A&B are not idle, winner=%d @ %t",winner,$time); + end + else if (A.status != idle) begin + winner = 0; + //$display("2.A is not idle(B is idle), winner=%d @ %t",winner,$time); + end + else begin // B.status != idle + winner = 1; + //$display("2.B is not idle(A is idle), winner=%d @ %t",winner,$time); + end + if (winner == 0) begin + A.Receive(a); #FL; + fork + W.Send(0); + //$display("2.W receive 0 from A @ %t",$time); + join + #BL; + end + else begin + B.Receive(b); #FL; + fork + W.Send(1); + //$display("2.W receive 1 from B @ %t",$time); + join + #BL; + end +end//always +endmodule + + + +module merge_2(interface L1, interface L2, interface R, interface Ctrl); +parameter FL=2; +parameter BL=2; +parameter WIDTH=2; +logic [WIDTH-2:0]inPort0; +logic [WIDTH-2:0]inPort1; +logic [WIDTH-2:0]controlPort; +always begin + Ctrl.Receive(controlPort); + if(controlPort==0) + begin + L1.Receive(inPort0); + //$display("3. Merge receive %b from inport0 @ %t",inPort0,$time); #FL; + R.Send({1'b0,inPort0}); //send_v={1'b1,inprot}; R.Send(send_v) + //$display("3. Merge send %b @ %t",{1'b0,inPort0},$time); #BL; + end + else if(controlPort==1) + begin + L2.Receive(inPort1); + //$display("3. Merge receive %b from inport1 @ %t",inPort1,$time); #FL; + R.Send({1'b1,inPort1}); + //$display("3. Merge send %b @ %t",{1'b1,inPort1},$time); #BL; + end +end +endmodule + + + +module packet_dispatch_2(interface A,A_P,A_S,B,B_P,B_S,C,C_P,C_S,D,D_P,D_S); +parameter FL=2; +parameter BL=2; +parameter WIDTH=34; +logic [WIDTH-1:0] packetA,packetB,packetC,packetD; +always begin + A.Receive(packetA); #FL; + fork + A_P.Send(packetA); + A_S.Send(2'b00); + //$display("1. A Receive packetA @ %t",$time); + join + #BL; +end +always begin + B.Receive(packetB); #FL; + fork + B_P.Send(packetB); + B_S.Send(2'b01); + //$display("1. B Receive packetB @ %t",$time); + join + #BL; +end +always begin + C.Receive(packetC); #FL; + fork + C_P.Send(packetC); + C_S.Send(2'b10); + //$display("1. C Receive packetC @ %t",$time); + join + #BL; +end +always begin + D.Receive(packetD); #FL; + fork + D_P.Send(packetD); + D_S.Send(2'b11); + //$display("1. D Receive packetD @ %t",$time); + join + #BL; +end +endmodule + + + +module merge_packet_2(interface A,B,C,D,Ctrl,R); +parameter FL=2; +parameter BL=2; +parameter WIDTH=34; +logic [WIDTH-1:0] packetA,packetB,packetC,packetD; +logic [1:0] controlPort; +always begin + Ctrl.Receive(controlPort); + if(controlPort==2'b00) + begin + A.Receive(packetA); #FL; + fork + R.Send(packetA); + //$display("2. A Send packetA @ %t",$time); + join + #BL; + end + else if(controlPort==2'b01) + begin + B.Receive(packetB); #FL; + fork + R.Send(packetB); + //$display("2. B Send packetB @ %t",$time); + join + #BL; + end + else if(controlPort==2'b10) + begin + C.Receive(packetC); #FL; + fork + R.Send(packetC); + //$display("2. C Send packetC @ %t",$time); + join + #BL; + end + else if(controlPort==2'b11) + begin + D.Receive(packetD); #FL; + fork + R.Send(packetD); + //$display("2. D Send packetD @ %t",$time); + join + #BL; + end +end +endmodule + + + +module data_generator_2(interface R); +parameter WIDTH = 34; +parameter FL = 4; +logic [WIDTH-1:0] SendValue; +always begin + SendValue = $random() % (2**WIDTH);//2**WIDTH=MAX 256 0-255 + #FL; + R.Send(SendValue); + //$display("dg send data=%d @ %t",SendValue,$time); +end +endmodule + + +module data_bucket_2 (interface L); +parameter WIDTH = 12; +parameter BL = 2; +logic [WIDTH-1:0] ReceiveValue; +always begin + L.Receive(ReceiveValue); + #BL; +end +endmodule + + + + + + + +module arbiter_withpacket_tb; + Channel #(.hsProtocol(P4PhaseBD),.WIDTH(34)) intf [18:0] (); + data_generator_2 #(.WIDTH(31), .FL(15)) dgA(.R(intf[10])); + data_generator_2 #(.WIDTH(31), .FL(15)) dgB(.R(intf[11])); + data_generator_2 #(.WIDTH(31), .FL(15)) dgC(.R(intf[12])); + data_generator_2 #(.WIDTH(31), .FL(15)) dgD(.R(intf[13])); + packet_dispatch_2 #(.WIDTH(31), .FL(2)) P_dis(.A(intf[10]), .A_P(intf[14]), .A_S(intf[0]), + .B(intf[11]), .B_P(intf[15]), .B_S(intf[1]), + .C(intf[12]), .C_P(intf[16]), .C_S(intf[4]), + .D(intf[13]), .D_P(intf[17]), .D_S(intf[5])); + arbiter_pipeline_2 #(.WIDTH(2), .FL(2), .BL(2)) ap1(.A(intf[0]), .B(intf[1]), .W(intf[2]), .O(intf[3])); + arbiter_pipeline_2 #(.WIDTH(2), .FL(2), .BL(2)) ap2(.A(intf[4]), .B(intf[5]), .W(intf[6]), .O(intf[7])); + arbiter_slackless_2 #(.WIDTH(2), .FL(2), .BL(2)) as1(.A(intf[3]), .B(intf[7]), .W(intf[8])); + merge_2 #(.FL(2), .BL(2)) mg(.L1(intf[2]), .L2(intf[6]), .R(intf[9]), .Ctrl(intf[8])); + merge_packet_2 #(.WIDTH(31), .FL(2), .BL(2)) mg_P(.A(intf[14]), .B(intf[15]), .C(intf[16]), .D(intf[17]), .R(intf[18]), .Ctrl(intf[9])); + data_bucket_2 #(.WIDTH(31), .BL(2)) db1(.L(intf[18])); + +initial + #80 $stop; +endmodule \ No newline at end of file diff --git a/arbiter.sv b/arbiter.sv new file mode 100644 index 0000000..8d76677 --- /dev/null +++ b/arbiter.sv @@ -0,0 +1,197 @@ +`timescale 1ns/1fs +import SystemVerilogCSP::*; + +module arbiter_pipeline_1 (interface A,B,W,O); +parameter FL=2; +parameter BL=2; +parameter WIDTH=2; +logic winner; +logic [WIDTH-1:0]a,b; +always begin + wait (A.status != idle || B.status != idle); + if (A.status != idle && B.status != idle) begin + winner = ($urandom%2 == 0) ? 0 : 1; + $display("1.Both A&B are not idle, winner=%d @ %t",winner,$time); + end + else if (A.status != idle) begin + winner = 0; + $display("1.A is not idle(B is idle), winner=%d @ %t",winner,$time); + end + else begin // B.status != idle + winner = 1; + $display("1.B is not idle(A is idle), winner=%d @ %t",winner,$time); + end + if (winner == 0) begin + A.Receive(a); #FL; + fork + begin + W.Send(a); + $display("1.W receive %d from A @ %t",a,$time); + end + begin + O.Send(0); + //$display("1.O sends A @ %t",$time); + end + join + #BL; + end + else begin + B.Receive(b); #FL; + fork + begin + W.Send(b); + $display("1.W receive %d from B @ %t",b,$time); + end + begin + O.Send(1); + //$display("1.O sends B @ %t",$time); + end + join + #BL; + end +end//always +endmodule + + + +module arbiter_slackless_1 (interface A,B,W); +parameter FL=2; +parameter BL=2; +parameter WIDTH=2; +int winner; +logic [WIDTH-1:0]a,b; +always begin + wait (A.status != idle || B.status != idle); + if (A.status != idle && B.status != idle) begin + winner = ($urandom%2 == 0) ? 0 : 1; + //$display("2.Both A&B are not idle, winner=%d @ %t",winner,$time); + end + else if (A.status != idle) begin + winner = 0; + //$display("2.A is not idle(B is idle), winner=%d @ %t",winner,$time); + end + else begin // B.status != idle + winner = 1; + //$display("2.B is not idle(A is idle), winner=%d @ %t",winner,$time); + end + if (winner == 0) begin + A.Receive(a); #FL; + fork + W.Send(a); + //$display("2.W receive %d from A @ %t",a,$time); + join + #BL; + end + else begin + B.Receive(b); #FL; + fork + W.Send(b); + //$display("2.W receive %d from B @ %t",b,$time); + join + #BL; + end +end//always +endmodule + + + +module merge_1(interface L0, interface L1, interface R, interface Ctrl); +parameter FL=2; +parameter BL=2; +parameter WIDTH=2; +logic [WIDTH-1:0]inPort1;//00,01,10,11 +logic [WIDTH-1:0]inPort0; +logic [WIDTH-1:0]controlPort; +always begin + Ctrl.Receive(controlPort); + if(controlPort==0) + begin + L0.Receive(inPort0); + $display("3. Merge receive %d from port1 @ %t",inPort1,$time); + R.Send(inPort0); + end + else if(controlPort==1) + begin + L1.Receive(inPort1); + $display("3. Merge receive %d from port0 @ %t",inPort0,$time); + R.Send(inPort1); + end +end +endmodule + + + + +module data_generator_1(interface R); +parameter WIDTH = 12; +parameter FL = 4; +logic [WIDTH-1:0] SendValue; +always begin + SendValue = $random() % (2**WIDTH);//2**WIDTH=MAX + #FL; + R.Send(SendValue); + //$display("dg send data=%d @ %t",SendValue,$time); +end +endmodule + + +/*module data_generator_A(interface R); +parameter WIDTH = 12; +parameter FL = 4; +logic [WIDTH-1:0] SendValue; +initial begin + SendValue = 1; + R.Send(SendValue); #15; + SendValue = 2; + R.Send(SendValue); #15; + SendValue = 3; + R.Send(SendValue); #5; + SendValue = 4; + R.Send(SendValue); #15; +end +endmodule +module data_generator_B(interface R); +parameter WIDTH = 12; +parameter FL = 4; +logic [WIDTH-1:0] SendValue; +initial begin + #20; + SendValue = 1; + R.Send(SendValue); #15; + SendValue = 2; + R.Send(SendValue); #15; + SendValue = 3; + R.Send(SendValue); #15; +end +endmodule +*/ + + + +module data_bucket_1 (interface L); +parameter WIDTH = 12; +parameter BL = 2; +logic [WIDTH-1:0] ReceiveValue; +always begin + L.Receive(ReceiveValue); + #BL; +end +endmodule + + + +module arbiter_tb; + Channel #(.hsProtocol(P4PhaseBD)) intf [9:0] (); + data_generator_1 #(.WIDTH(2), .FL(15)) dg1(.R(intf[0])); + data_generator_1 #(.WIDTH(2), .FL(15)) dg2(.R(intf[1])); + data_generator_1 #(.WIDTH(2), .FL(15)) dg3(.R(intf[4])); + data_generator_1 #(.WIDTH(2), .FL(15)) dg4(.R(intf[5])); + arbiter_pipeline_1 #(.WIDTH(2), .FL(2), .BL(2)) ap1(.A(intf[0]), .B(intf[1]), .W(intf[2]), .O(intf[3])); + arbiter_pipeline_1 #(.WIDTH(2), .FL(2), .BL(2)) ap2(.A(intf[4]), .B(intf[5]), .W(intf[6]), .O(intf[7])); + arbiter_slackless_1 #(.WIDTH(2), .FL(2), .BL(2)) as1(.A(intf[3]), .B(intf[7]), .W(intf[8])); + merge_1 #(.WIDTH(2), .FL(2), .BL(2)) mg(.L0(intf[2]), .L1(intf[6]), .R(intf[9]), .Ctrl(intf[8])); + data_bucket_1 #(.WIDTH(2), .BL(2)) db1(.L(intf[9])); + +initial + #80 $stop; +endmodule \ No newline at end of file diff --git a/data_bucket.sv b/data_bucket.sv new file mode 100644 index 0000000..ea1318e --- /dev/null +++ b/data_bucket.sv @@ -0,0 +1,39 @@ +`timescale 1ns/1fs +import SystemVerilogCSP::*; +module data_bucket (interface r); + parameter WIDTH = 12; + parameter BL = 2; //ideal environment + logic [WIDTH-1:0] ReceiveValue = 0; + logic [3:0] Value; + + //Variables added for performance measurements + real cycleCounter=0, //# of cycles = Total number of times a value is received + timeOfReceive=0, //Simulation time of the latest Receive + cycleTime=0; // time difference between the last two receives + real averageThroughput=0, averageCycleTime=0, sumOfCycleTimes=0; + always + begin + //$display("START module data_bucket and time is %d", $time); + //Save the simulation time when Receive starts + timeOfReceive = $time; + r.Receive(ReceiveValue); + //value=ReceiveValue[]; + //$display("ReceiveValue is %d",ReceiveValue); + //$display("ReceiveTime is %d",timeOfReceive); + #BL; + cycleCounter += 1; + //Measuring throughput: calculate the number of Receives per unit of time + //CycleTime stores the time it takes from the begining to the end of the always block + + /***cycleTime = $time - timeOfReceive; + averageThroughput = cycleCounter/$time; + sumOfCycleTimes += cycleTime; + averageCycleTime = sumOfCycleTimes / cycleCounter; + $display("Execution cycle= %d, Cycle Time= %d, + Average CycleTime=%f, Average Throughput=%f", cycleCounter, cycleTime, + averageCycleTime, averageThroughput);***/ + + //$display("End module data_bucket and time is %d", $time); + end + +endmodule \ No newline at end of file diff --git a/data_generator.sv b/data_generator.sv new file mode 100644 index 0000000..084f7ce --- /dev/null +++ b/data_generator.sv @@ -0,0 +1,58 @@ +`timescale 1ns/1fs +import SystemVerilogCSP::*; +module data_generator (interface r); + parameter WIDTH = 34; + parameter FL = 2; //ideal environment + parameter MAX=50; + logic [33:0] SendValue; + logic [15:0] zeros=0000_0000_0000_0000; + //always + initial + begin + //add a display here to see when this module starts its main loop + //$display("START_data_gen_time %m %d",$time); + //SendValue = {$random()} % MAX; + //SendValue={1000_0100,10,{16{1'b0}},0001_0011};//19---PE1 + SendValue={8'b1000_0100,2'b10,{16{1'b0}},8'b0001_0011};//19---PE1 + #FL; + r.Send(SendValue); + //$display("Send Value%d",SendValue); + SendValue={8'b1001_0100,2'b10,{16{1'b0}},8'b0000_1100};//12---PE2 + #FL; + r.Send(SendValue); + //SendValue={8'b1010_0100,2'b10,{16{1'b0}},8'b0001_1101};//29---PE3 + SendValue={8'b1010_0100,2'b10,{16{1'b0}},8'b0010_0111};//39---PE3 + #FL; + r.Send(SendValue); + + //SendValue=48; + + + //Communication action Send is about to start + // $display("Starting %m.Send @ %d", $time); + + //Communication action Send is finished + // $display("Finished %m.Send @ %d", $time); + SendValue={8'b1000_0100,2'b10,{16{1'b0}},8'b0001_0011};//19---PE1 + #FL; + r.Send(SendValue); + //$display("Send Value%d",SendValue); + SendValue={8'b1001_0100,2'b10,{16{1'b0}},8'b0001_0011};//19---PE2 + #FL; + r.Send(SendValue); + SendValue={8'b1010_0100,2'b10,{16{1'b0}},8'b0000_1001};//9---PE3 + #FL; + r.Send(SendValue); + + SendValue={8'b1000_0100,2'b10,{16{1'b0}},8'b0001_1011};//27---PE1 + #FL; + r.Send(SendValue); + //$display("Send Value%d",SendValue); + SendValue={8'b1001_0100,2'b10,{16{1'b0}},8'b0000_1000};//8---PE2 + #FL; + r.Send(SendValue); + SendValue={8'b1010_0100,2'b10,{16{1'b0}},8'b0000_0000};//0---PE3 + #FL; + r.Send(SendValue); + end +endmodule \ No newline at end of file diff --git a/memory.sv b/memory.sv index 99d4d87..c2d2b36 100644 --- a/memory.sv +++ b/memory.sv @@ -56,7 +56,8 @@ module memory(interface read, write, T, x, y, data_out, data_in); initial begin // Load golden mem - $readmemb("base_output_bin.mem", pre_golden_memory); + $readmemb("sparse_output_bin.mem", pre_golden_memory); + //$readmemb("base_output_bin.mem", pre_golden_memory); for (ofi = 0; ofi < OF_ROWS; ofi++) begin for (ofj = 0; ofj < OF_COLS; ofj++) begin index = OF_COLS * ofi + ofj; @@ -67,8 +68,9 @@ module memory(interface read, write, T, x, y, data_out, data_in); end // fi for - // Load filters - $readmemh("base_kernel_hex.mem", pre_filt_memory); + // Load filters + $readmemh("sparse_kernel_hex.mem", pre_filt_memory); + //$readmemh("base_kernel_hex.mem", pre_filt_memory); for (fi = 0; fi < F_ROWS; fi++) begin for (fj = 0; fj < F_COLS; fj++) begin @@ -80,8 +82,8 @@ module memory(interface read, write, T, x, y, data_out, data_in); end // fi for // Load spikes - $readmemb("base_ifmaps_bin.mem", pre_ifmaps_mem); - + // $readmemb("base_ifmaps_bin.mem", pre_ifmaps_mem); + $readmemb("sparse_ifmaps_bin.mem", pre_ifmaps_mem); for (ift = 0; ift < timesteps;++ift) begin for (ifi = 0; ifi < IF_ROWS;++ifi) begin for (ifj = 0; ifj < IF_COLS;++ifj) begin @@ -185,7 +187,63 @@ module memory(interface read, write, T, x, y, data_out, data_in); $display("%m Golden[%d][%d} = %b",golden_i,golden_j,golden_of_mem[golden_i][golden_j]); $display("%m Your mem val = %b", of_mem[timesteps-1][golden_i][golden_j]); end // golden_i - end // golden_i + end + + for (integer golden_i = 0; golden_i < OF_ROWS; golden_i++) begin + for (integer golden_j = 0; golden_j < OF_COLS; golden_j++) begin + $display("%m Your 1st mem val = %b", of_mem[0][golden_i][golden_j]); + end // golden_i + end + + for (integer golden_i = 0; golden_i < OF_ROWS; golden_i++) begin + for (integer golden_j = 0; golden_j < OF_COLS; golden_j++) begin + $display("%m Your 2nd mem val = %b", of_mem[1][golden_i][golden_j]); + end // golden_i + end + + for (integer golden_i = 0; golden_i < OF_ROWS; golden_i++) begin + for (integer golden_j = 0; golden_j < OF_COLS; golden_j++) begin + $display("%m Your 3rd mem val = %b", of_mem[2][golden_i][golden_j]); + end // golden_i + end + + for (integer golden_i = 0; golden_i < OF_ROWS; golden_i++) begin + for (integer golden_j = 0; golden_j < OF_COLS; golden_j++) begin + $display("%m Your 4th mem val = %b", of_mem[3][golden_i][golden_j]); + end // golden_i + end + + for (integer golden_i = 0; golden_i < OF_ROWS; golden_i++) begin + for (integer golden_j = 0; golden_j < OF_COLS; golden_j++) begin + $display("%m Your 5th mem val = %b", of_mem[4][golden_i][golden_j]); + end // golden_i + end + + for (integer golden_i = 0; golden_i < OF_ROWS; golden_i++) begin + for (integer golden_j = 0; golden_j < OF_COLS; golden_j++) begin + $display("%m Your 6th mem val = %b", of_mem[5][golden_i][golden_j]); + end // golden_i + end + + for (integer golden_i = 0; golden_i < OF_ROWS; golden_i++) begin + for (integer golden_j = 0; golden_j < OF_COLS; golden_j++) begin + $display("%m Your 7th mem val = %b", of_mem[6][golden_i][golden_j]); + end // golden_i + end + + for (integer golden_i = 0; golden_i < OF_ROWS; golden_i++) begin + for (integer golden_j = 0; golden_j < OF_COLS; golden_j++) begin + $display("%m Your 8th mem val = %b", of_mem[7][golden_i][golden_j]); + end // golden_i + end + + for (integer golden_i = 0; golden_i < OF_ROWS; golden_i++) begin + for (integer golden_j = 0; golden_j < OF_COLS; golden_j++) begin + $display("%m Your 9th mem val = %b", of_mem[8][golden_i][golden_j]); + end // golden_i + end + + // golden_i #5; $display("%m User reports completion"); $stop; diff --git a/memory_wrapper.sv b/memory_wrapper.sv index 1dfc8bb..3d76894 100644 --- a/memory_wrapper.sv +++ b/memory_wrapper.sv @@ -127,7 +127,7 @@ parameter DONE=4'b1111; fromNOC.Receive(nocval); $display("%m receive value is %b in %t", nocval, $time); if((nocval[WIDTH_NOC-9:WIDTH_NOC-10]==out_type) & (nocval[WIDTH_NOC-31:0]==DONE)) begin - flag+=1; + flag+=1; if(t>=2 & i>=1 & flag<3) begin for(int k=0; k< ofy; k++) begin toMemRead.Send(read_mempots); @@ -143,6 +143,7 @@ parameter DONE=4'b1111; $display("%m toNOC send oldmem_p is %b in %t", nocval, $time); end end + $display("%m Done received"); if(flag<=2) begin for(int k=0; k< ify; k++) begin diff --git a/packet_analyser.sv b/packet_analyser.sv new file mode 100644 index 0000000..aaf2520 --- /dev/null +++ b/packet_analyser.sv @@ -0,0 +1,136 @@ + +`timescale 1ns/1fs +import SystemVerilogCSP::*; + +module packet_analyser_3(interface N_L, N_ctrl, N_R, S_L, S_ctrl, S_R, E_L, E_ctrl, E_R, W_L, W_ctrl, W_R, P_L, P_ctrl, P_R); +parameter FL=2; +parameter BL=1; +parameter WIDTH=34; +parameter Xaddr=00; +parameter Yaddr=00; +logic [1:0]Xsour_Nin, Xdest_Nin, Xoffset_Nin; +logic [1:0]Xsour_Sin, Xdest_Sin, Xoffset_Sin; +logic [1:0]Xsour_Ein, Xdest_Ein, Xoffset_Ein; +logic [1:0]Xsour_Win, Xdest_Win, Xoffset_Win; +logic [1:0]Xsour_Pin, Xdest_Pin, Xoffset_Pin; +logic [1:0]Ysour_Nin, Ydest_Nin, Yoffset_Nin; +logic [1:0]Ysour_Sin, Ydest_Sin, Yoffset_Sin; +logic [1:0]Ysour_Ein, Ydest_Ein, Yoffset_Ein; +logic [1:0]Ysour_Win, Ydest_Win, Yoffset_Win; +logic [1:0]Ysour_Pin, Ydest_Pin, Yoffset_Pin; +logic [WIDTH-1:0]packet_Nin, packet_Sin, packet_Ein, packet_Win, packet_Pin; + +//packet comes from NORTH +always begin + N_L.Receive(packet_Nin); #FL; + fork + Xsour_Nin = packet_Nin[WIDTH-1:WIDTH-2]; + Ysour_Nin = packet_Nin[WIDTH-3:WIDTH-4]; + Xdest_Nin = packet_Nin[WIDTH-5:WIDTH-6]; + Ydest_Nin = packet_Nin[WIDTH-7:WIDTH-8]; + join + Xoffset_Nin = Xdest_Nin - Xaddr; + Yoffset_Nin = Ydest_Nin - Yaddr; + if (Xoffset_Nin==0 & Yoffset_Nin==0) N_ctrl.Send(10); + else if (Xoffset_Nin > 0) N_ctrl.Send(11); + else if (Xoffset_Nin < 0) N_ctrl.Send(00); + else if (Yoffset_Nin > 0) N_ctrl.Send(01); + N_R.Send(packet_Nin); #BL; +end + + +//packet comes from SOUTH +always begin + S_L.Receive(packet_Sin); #FL; + fork + Xsour_Sin = packet_Sin[WIDTH-1:WIDTH-2]; + Ysour_Sin = packet_Sin[WIDTH-3:WIDTH-4]; + Xdest_Sin = packet_Sin[WIDTH-5:WIDTH-6]; + Ydest_Sin = packet_Sin[WIDTH-7:WIDTH-8]; + join + Xoffset_Sin = Xdest_Sin - Xaddr; + Yoffset_Sin = Ydest_Sin - Yaddr; + if (Xoffset_Sin==0 & Yoffset_Sin==0) S_ctrl.Send(10); + else if (Xoffset_Sin > 0) S_ctrl.Send(11); + else if (Xoffset_Sin < 0) S_ctrl.Send(00); + else if (Yoffset_Sin < 0) S_ctrl.Send(01); + S_R.Send(packet_Sin); #BL; +end + + +//packet comes from EAST +always begin + E_L.Receive(packet_Ein); #FL; + fork + Xsour_Ein = packet_Ein[WIDTH-1:WIDTH-2]; + Ysour_Ein = packet_Ein[WIDTH-3:WIDTH-4]; + Xdest_Ein = packet_Ein[WIDTH-5:WIDTH-6]; + Ydest_Ein = packet_Ein[WIDTH-7:WIDTH-8]; + join + Xoffset_Ein = Xdest_Ein - Xaddr; + Yoffset_Ein = Ydest_Ein - Yaddr; + if (Xoffset_Ein==0 & Yoffset_Ein==0) E_ctrl.Send(10); + else if (Xoffset_Ein < 0) E_ctrl.Send(00); + else if (Yoffset_Ein > 0) E_ctrl.Send(11); + else if (Yoffset_Ein < 0) E_ctrl.Send(01); + E_R.Send(packet_Ein); #BL; +end + + +//packet comes from WEST +always begin + W_L.Receive(packet_Win); #FL; + fork + Xsour_Win = packet_Win[WIDTH-1:WIDTH-2]; + Ysour_Win = packet_Win[WIDTH-3:WIDTH-4]; + Xdest_Win = packet_Win[WIDTH-5:WIDTH-6]; + Ydest_Win = packet_Win[WIDTH-7:WIDTH-8]; + join + Xoffset_Win = Xdest_Win - Xaddr; + Yoffset_Win = Ydest_Win - Yaddr; + if (Xoffset_Win==0 & Yoffset_Win==0) W_ctrl.Send(10); + else if (Xoffset_Win > 0) W_ctrl.Send(11); + else if (Yoffset_Win > 0) W_ctrl.Send(00); + else if (Yoffset_Win < 0) W_ctrl.Send(01); + W_R.Send(packet_Win); #BL; +end + + +//packet comes from PE +always begin + P_L.Receive(packet_Pin); #FL; + fork + Xsour_Pin = packet_Pin[WIDTH-1:WIDTH-2]; + Ysour_Pin = packet_Pin[WIDTH-3:WIDTH-4]; + Xdest_Pin = packet_Pin[WIDTH-5:WIDTH-6]; + Ydest_Pin = packet_Pin[WIDTH-7:WIDTH-8]; + join + Xoffset_Pin = Xdest_Pin - Xaddr; + Yoffset_Pin = Ydest_Pin - Yaddr; + if (Xoffset_Pin > 0) P_ctrl.Send(11); + else if (Xoffset_Pin < 0) P_ctrl.Send(00); + else if (Yoffset_Pin > 0) P_ctrl.Send(10); + else if (Yoffset_Pin < 0) P_ctrl.Send(01); + P_R.Send(packet_Pin); #BL; +end +endmodule + + + + + + + + + + + + + + + + + + + + diff --git a/router.sv b/router.sv new file mode 100644 index 0000000..f291910 --- /dev/null +++ b/router.sv @@ -0,0 +1,422 @@ +`timescale 1ns/1fs +import SystemVerilogCSP::*; + +//------------------------------------------------------------------------------------------------------------------------------------------------------- +module packet_analyser_5(interface N_L, N_ctrl, N_R, S_L, S_ctrl, S_R, E_L, E_ctrl, E_R, W_L, W_ctrl, W_R, P_L, P_ctrl, P_R); +parameter FL=2; +parameter BL=1; +parameter WIDTH=34; +parameter [1:0]Xaddr=00; +parameter [1:0]Yaddr=00; +logic [1:0]Xsour_Nin, Xdest_Nin; +logic [1:0]Xsour_Sin, Xdest_Sin; +logic [1:0]Xsour_Ein, Xdest_Ein; +logic [1:0]Xsour_Win, Xdest_Win; +logic [1:0]Xsour_Pin, Xdest_Pin; +logic [1:0]Ysour_Nin, Ydest_Nin; +logic [1:0]Ysour_Sin, Ydest_Sin; +logic [1:0]Ysour_Ein, Ydest_Ein; +logic [1:0]Ysour_Win, Ydest_Win; +logic [1:0]Ysour_Pin, Ydest_Pin; +logic [WIDTH-1:0]packet_Nin, packet_Sin, packet_Ein, packet_Win, packet_Pin; + +//packet comes from NORTH +always begin + N_L.Receive(packet_Nin); #FL; + $display("router_num:%m---1. NORTH receive packetN(%b)",packet_Nin); + fork + Xsour_Nin = packet_Nin[WIDTH-1:WIDTH-2]; + Ysour_Nin = packet_Nin[WIDTH-3:WIDTH-4]; + Xdest_Nin = packet_Nin[WIDTH-5:WIDTH-6]; + Ydest_Nin = packet_Nin[WIDTH-7:WIDTH-8]; + join + //$display("router_num:%m---1. The router address is %b%b",Xaddr,Yaddr); + //$display("router_num:%m---1. packetN destination address is %b%b",Xdest_Nin,Ydest_Nin); + if (Xdest_Nin==Xaddr & Ydest_Nin==Yaddr) + begin + N_ctrl.Send(10); + //$display("router_num:%m---1. packetN should send from NORTH to PE"); + end + else if (Xdest_Nin > Xaddr) + begin + N_ctrl.Send(11); + //$display("router_num:%m---1. packetN should send from NORTH to EAST"); + end + else if (Xdest_Nin < Xaddr) + begin + N_ctrl.Send(00); + //$display("router_num:%m---1. packetN should send from NORTH to WEST"); + end + else if (Ydest_Nin > Yaddr & Xdest_Nin==Xaddr) + begin + N_ctrl.Send(01); + //$display("router_num:%m---1. packetN should send from NORTH to SOUTH"); + end + N_R.Send(packet_Nin); #BL; +end + + +//packet comes from SOUTH +always begin + S_L.Receive(packet_Sin); #FL; + //$display("router_num:%m---2. SOUTH receive packetS(%b)",packet_Sin); + fork + Xsour_Sin = packet_Sin[WIDTH-1:WIDTH-2]; + Ysour_Sin = packet_Sin[WIDTH-3:WIDTH-4]; + Xdest_Sin = packet_Sin[WIDTH-5:WIDTH-6]; + Ydest_Sin = packet_Sin[WIDTH-7:WIDTH-8]; + join + //$display("router_num:%m---2. The router address is %b%b",Xaddr,Yaddr); + //$display("router_num:%m---2. packetS destination address is %b%b",Xdest_Sin,Ydest_Sin); + if (Xdest_Sin==Xaddr & Ydest_Sin==Yaddr) + begin + S_ctrl.Send(10); + //$display("router_num:%m---2. packetS should send from SOUTH to PE"); + end + else if (Xdest_Sin > Xaddr) + begin + S_ctrl.Send(11); + //$display("router_num:%m---2. packetS should send from SOUTH to EAST"); + end + else if (Xdest_Sin < Xaddr) + begin + S_ctrl.Send(00); + //$display("router_num:%m---2. packetS should send from SOUTH to WEST"); + end + else if (Ydest_Sin < Yaddr & Xdest_Sin==Xaddr) + begin + S_ctrl.Send(01); + //$display("router_num:%m---2. packetS should send from SOUTH to NORTH"); + end + S_R.Send(packet_Sin); #BL; +end + + +//packet comes from EAST +always begin + E_L.Receive(packet_Ein); #FL; + //$display("router_num:%m---3. EAST receive packetE(%b)",packet_Ein); + fork + Xsour_Ein = packet_Ein[WIDTH-1:WIDTH-2]; + Ysour_Ein = packet_Ein[WIDTH-3:WIDTH-4]; + Xdest_Ein = packet_Ein[WIDTH-5:WIDTH-6]; + Ydest_Ein = packet_Ein[WIDTH-7:WIDTH-8]; + join + //$display("router_num:%m---3. The router address is %b%b",Xaddr,Yaddr); + //$display("router_num:%m---3. packetE destination address is %b%b",Xdest_Ein,Ydest_Ein); + if (Xdest_Ein==Xaddr & Ydest_Ein==Yaddr) + begin + E_ctrl.Send(10); + //$display("router_num:%m---3. packetE should send from EAST to PE"); + end + else if (Xdest_Ein < Xaddr) + begin + E_ctrl.Send(00); + //$display("router_num:%m---3. packetE should send from EAST to WEST"); + end + else if (Ydest_Ein > Yaddr & Xdest_Ein==Xaddr) + begin + E_ctrl.Send(11); + //$display("router_num:%m---3. packetE should send from EAST to SOUTH"); + end + else if (Ydest_Ein < Yaddr & Xdest_Ein==Xaddr) + begin + E_ctrl.Send(01); + //$display("router_num:%m---3. packetE should send from EAST to NORTH"); + end + E_R.Send(packet_Ein); #BL; + //$display("router_num:%m---3. SOUTH already sent packetE(%b)",packet_Ein); +end + + +//packet comes from WEST +always begin + W_L.Receive(packet_Win); #FL; + //$display("router_num:%m---4. WEST receive packetW(%b)",packet_Win); + fork + Xsour_Win = packet_Win[WIDTH-1:WIDTH-2]; + Ysour_Win = packet_Win[WIDTH-3:WIDTH-4]; + Xdest_Win = packet_Win[WIDTH-5:WIDTH-6]; + Ydest_Win = packet_Win[WIDTH-7:WIDTH-8]; + join + //$display("router_num:%m---4. The router address is %b%b",Xaddr,Yaddr); + //$display("router_num:%m---4. packetW destination address is %b%b",Xdest_Win,Ydest_Win); + if (Xdest_Win==Xaddr & Ydest_Win==Yaddr) + begin + W_ctrl.Send(10); + //$display("router_num:%m---4. packetW should send from WEST to PE"); + end + else if (Xdest_Win > Xaddr) + begin + W_ctrl.Send(11); + //$display("router_num:%m---4. packetW should send from WEST to EAST"); + end + else if (Ydest_Win > Yaddr & Xdest_Win==Xaddr) + begin + W_ctrl.Send(00); + //$display("router_num:%m---4. packetW should send from WEST to SOUTH"); + end + else if (Ydest_Win < Yaddr & Xdest_Win==Xaddr) + begin + W_ctrl.Send(01); + //$display("router_num:%m---4. packetW should send from WEST to NORTH"); + end + W_R.Send(packet_Win); #BL; +end + + +//packet comes from PE +always begin + P_L.Receive(packet_Pin); #FL; + //$display("router_num:%m---5. PE receive packetP(%b)",packet_Pin); + fork + Xsour_Pin = packet_Pin[WIDTH-1:WIDTH-2]; + Ysour_Pin = packet_Pin[WIDTH-3:WIDTH-4]; + Xdest_Pin = packet_Pin[WIDTH-5:WIDTH-6]; + Ydest_Pin = packet_Pin[WIDTH-7:WIDTH-8]; + join + //$display("router_num:%m---5. The router address is %b%b",Xaddr,Yaddr); + //$display("router_num:%m---5. packetP destination address is %b%b",Xdest_Pin,Ydest_Pin); + if (Xdest_Pin > Xaddr) + begin + P_ctrl.Send(11); + //$display("router_num:%m---5. packetP should send from PE to EAST"); + end + else if (Xdest_Pin < Xaddr) + begin + P_ctrl.Send(00); + //$display("router_num:%m---5. packetP should send from PE to WEST"); + end + else if (Ydest_Pin > Yaddr & Xdest_Pin==Xaddr) + begin + P_ctrl.Send(10); + //$display("router_num:%m---5. packetP should send from PE to SOUTH"); + end + else if (Ydest_Pin < Yaddr & Xdest_Pin==Xaddr) + begin + P_ctrl.Send(01); + //$display("router_num:%m---5. packetP should send from PE to NORTH"); + end + P_R.Send(packet_Pin); #BL; +end +endmodule + + + + + + + +//------------------------------------------------------------------------------------------------------------------------------------------------------- +module split_5(interface L, interface Ctrl, interface A, B, C, D); +parameter FL=4; +parameter BL=6; +parameter WIDTH=34; +logic [WIDTH-1:0]packet; +logic [1:0]controlPort; +always begin + fork + begin + L.Receive(packet); + //$display("router_split:%m---6. Split already receive packet(%b)",packet); + #FL; + end + begin + Ctrl.Receive(controlPort); + //$display("router_split:%m---6. Split already receive contrl(%b)",controlPort); + #FL; + end + join + + if(controlPort==2'b00) begin + A.Send(packet); + //$display("router_split:%m---6. Split already send packet(%b) to A port",packet); + #BL; end + else if(controlPort==2'b01) begin + B.Send(packet); + //$display("router_split:%m---6. Split already send packet(%b) to B port",packet); + #BL; end + else if(controlPort==2'b10) begin + C.Send(packet); + //$display("router_split:%m---6. Split already send packet(%b) to C port",packet); + #BL; end + else if(controlPort==2'b11) begin + D.Send(packet); +// $display("router_split:%m---6. Split already send packet(%b) to D port",packet); + #BL; end +end +endmodule + + + + + + +//------------------------------------------------------------------------------------------------------------------------------------------------------- +module arbiter_withpacket_5 (interface A, B, C, D, R); +parameter WIDTH; +parameter FL, BL; + Channel #(.hsProtocol(P4PhaseBD),.WIDTH(34)) intf [19:0] (); + packet_dispatch_2 #(.WIDTH(WIDTH), .FL(FL), .BL(BL)) P_dis(.A(A), .A_P(intf[14]), .A_S(intf[0]), + .B(B), .B_P(intf[15]), .B_S(intf[1]), + .C(C), .C_P(intf[16]), .C_S(intf[4]), + .D(D), .D_P(intf[17]), .D_S(intf[5])); + arbiter_pipeline_2 #(.WIDTH(2), .FL(FL), .BL(BL)) ap1(.A(intf[0]), .B(intf[1]), .W(intf[2]), .O(intf[3])); + arbiter_pipeline_2 #(.WIDTH(2), .FL(FL), .BL(BL)) ap2(.A(intf[4]), .B(intf[5]), .W(intf[6]), .O(intf[7])); + arbiter_slackless_2 #(.WIDTH(2), .FL(FL), .BL(FL)) as1(.A(intf[3]), .B(intf[7]), .W(intf[8])); + merge_2 #(.WIDTH(2), .FL(FL), .BL(FL)) mg(.L1(intf[2]), .L2(intf[6]), .R(intf[9]), .Ctrl(intf[8])); + merge_packet_2 #(.WIDTH(WIDTH), .FL(FL), .BL(FL)) mg_P(.A(intf[14]), .B(intf[15]), .C(intf[16]), .D(intf[17]), .R(R), .Ctrl(intf[9])); +endmodule + + + + + + +//------------------------------------------------------------------------------------------------------------------------------------------------------- +module router (interface N_in, N_out, S_in, S_out, E_in, E_out, W_in, W_out, P_in, P_out); +parameter WIDTH; +parameter FL, BL; +parameter Xaddr; +parameter Yaddr; + Channel #(.hsProtocol(P4PhaseBD),.WIDTH(34)) intf [59:20] (); + packet_analyser_5 #(.WIDTH(WIDTH), .FL(FL), .BL(BL), .Xaddr(Xaddr), .Yaddr(Yaddr)) + pac_ana(.N_L(N_in), .N_ctrl(intf[50]), .N_R(intf[20]), + .S_L(S_in), .S_ctrl(intf[51]), .S_R(intf[21]), + .E_L(E_in), .E_ctrl(intf[53]), .E_R(intf[23]), + .W_L(W_in), .W_ctrl(intf[52]), .W_R(intf[22]), + .P_L(P_in), .P_ctrl(intf[54]), .P_R(intf[24])); + split_5 #(.WIDTH(WIDTH), .FL(FL), .BL(BL)) splt_N(.L(intf[20]), .Ctrl(intf[50]), .A(intf[25]), .B(intf[26]), .C(intf[27]), .D(intf[28])); + split_5 #(.WIDTH(WIDTH), .FL(FL), .BL(BL)) splt_S(.L(intf[21]), .Ctrl(intf[51]), .A(intf[29]), .B(intf[30]), .C(intf[31]), .D(intf[32])); + split_5 #(.WIDTH(WIDTH), .FL(FL), .BL(BL)) splt_E(.L(intf[23]), .Ctrl(intf[53]), .A(intf[37]), .B(intf[38]), .C(intf[39]), .D(intf[40])); + split_5 #(.WIDTH(WIDTH), .FL(FL), .BL(BL)) splt_W(.L(intf[22]), .Ctrl(intf[52]), .A(intf[33]), .B(intf[34]), .C(intf[35]), .D(intf[36])); + split_5 #(.WIDTH(WIDTH), .FL(FL), .BL(BL)) splt_P(.L(intf[24]), .Ctrl(intf[54]), .A(intf[41]), .B(intf[42]), .C(intf[43]), .D(intf[44])); + arbiter_withpacket_5 #(.WIDTH(WIDTH), .FL(FL), .BL(BL)) arbi_N(.A(intf[30]), .B(intf[34]), .C(intf[38]), .D(intf[42]), .R(N_out)); + arbiter_withpacket_5 #(.WIDTH(WIDTH), .FL(FL), .BL(BL)) arbi_S(.A(intf[26]), .B(intf[33]), .C(intf[40]), .D(intf[43]), .R(S_out)); + arbiter_withpacket_5 #(.WIDTH(WIDTH), .FL(FL), .BL(BL)) arbi_E(.A(intf[28]), .B(intf[32]), .C(intf[36]), .D(intf[44]), .R(E_out)); + arbiter_withpacket_5 #(.WIDTH(WIDTH), .FL(FL), .BL(BL)) arbi_W(.A(intf[25]), .B(intf[29]), .C(intf[37]), .D(intf[41]), .R(W_out)); + arbiter_withpacket_5 #(.WIDTH(WIDTH), .FL(FL), .BL(BL)) arbi_P(.A(intf[27]), .B(intf[31]), .C(intf[35]), .D(intf[39]), .R(P_out)); + +endmodule + + + + + + + +/* +module data_generator_5_N(interface R); +parameter WIDTH = 34; +parameter FL = 4; +logic [WIDTH-1:0] SendValue; +initial begin + #5; +// SendValue = 8'b0100_0001; R.Send(SendValue); #FL; +// SendValue = 8'b0100_0101; R.Send(SendValue); #FL; +// SendValue = 8'b0100_0110; R.Send(SendValue); #FL; +// SendValue = 8'b0100_1001; #FL; R.Send(SendValue); +// SendValue = 8'b0100_0010; #FL; R.Send(SendValue); +end +endmodule +module data_generator_5_S(interface R); +parameter WIDTH = 34; +parameter FL = 4; +logic [WIDTH-1:0] SendValue; +initial begin +// SendValue = 8'b0110_0101; R.Send(SendValue); #FL; +// SendValue = 8'b0110_1000; #FL; R.Send(SendValue); +// SendValue = 8'b0110_0100; #FL; R.Send(SendValue); +// SendValue = 8'b0110_0000; #FL; R.Send(SendValue); +// SendValue = 8'b0110_0001; R.Send(SendValue); #FL; +end +endmodule +module data_generator_5_E(interface R); +parameter WIDTH = 34; +parameter FL = 4; +logic [WIDTH-1:0] SendValue; +initial begin +// SendValue = 8'b0100_0010; R.Send(SendValue); #FL; +// SendValue = 8'b1001_0110; R.Send(SendValue); #FL; +// SendValue = 8'b1001_0100; #FL; R.Send(SendValue); +// SendValue = 8'b1001_0000; #FL; R.Send(SendValue); +// SendValue = 8'b1001_0001; R.Send(SendValue); #FL; +end +endmodule +module data_generator_5_W(interface R); +parameter WIDTH = 34; +parameter FL = 4; +logic [WIDTH-1:0] SendValue; +initial begin + SendValue = 8'b0100_1010; R.Send(SendValue); #FL; +// SendValue = 8'b0001_0110; R.Send(SendValue); #FL; +// SendValue = 8'b0001_0100; #FL; R.Send(SendValue); +// SendValue = 8'b0001_1001; #FL; R.Send(SendValue); +// SendValue = 8'b0001_1010; #FL; R.Send(SendValue); +end +endmodule +module data_generator_5_P(interface R); +parameter WIDTH = 34; +parameter FL = 4; +logic [WIDTH-1:0] SendValue; +initial begin + #15; +// SendValue = 8'b0101_0000; R.Send(SendValue); #FL; +// SendValue = 8'b0100_0010; R.Send(SendValue); #FL; +// SendValue = 8'b0101_0100; #FL; R.Send(SendValue); +// SendValue = 8'b0101_1001; #FL; R.Send(SendValue); +// SendValue = 8'b0101_1010; #FL; R.Send(SendValue); +end +endmodule +module data_generator_5(interface R); +parameter WIDTH = 12; +parameter FL = 4; +logic [WIDTH-1:0] SendValue; +always begin + SendValue = $random() % (2**WIDTH);//2**WIDTH=MAX + R.Send(SendValue); + #FL; +end +endmodule +module data_bucket_5 (interface L); +parameter WIDTH = 12; +parameter BL = 2; +logic [WIDTH-1:0] ReceiveValue; +always begin + L.Receive(ReceiveValue); + #BL; +end +endmodule +//------------------------------------------------------------------------------------------------------------------------------------------------------- +module router_tb; + Channel #(.hsProtocol(P4PhaseBD),.WIDTH(34)) intf [59:20] (); + data_generator_5_N #(.WIDTH(8), .FL(10)) dg_N(.R(intf[55])); + data_generator_5_S #(.WIDTH(8), .FL(10)) dg_S(.R(intf[56])); + data_generator_5_E #(.WIDTH(8), .FL(10)) dg_E(.R(intf[58])); + data_generator_5_W #(.WIDTH(8), .FL(10)) dg_W(.R(intf[57])); + data_generator_5_P #(.WIDTH(8), .FL(10)) dg_P(.R(intf[59])); + packet_analyser_5 #(.WIDTH(8), .FL(2), .BL(2), .Xaddr(10), .Yaddr(00)) + pac_ana(.N_L(intf[55]), .N_ctrl(intf[50]), .N_R(intf[20]), + .S_L(intf[56]), .S_ctrl(intf[51]), .S_R(intf[21]), + .E_L(intf[58]), .E_ctrl(intf[53]), .E_R(intf[23]), + .W_L(intf[57]), .W_ctrl(intf[52]), .W_R(intf[22]), + .P_L(intf[59]), .P_ctrl(intf[54]), .P_R(intf[24])); + split_5 #(.WIDTH(8), .FL(2), .BL(2)) splt_N(.L(intf[20]), .Ctrl(intf[50]), .A(intf[25]), .B(intf[26]), .C(intf[27]), .D(intf[28])); + split_5 #(.WIDTH(8), .FL(2), .BL(2)) splt_S(.L(intf[21]), .Ctrl(intf[51]), .A(intf[29]), .B(intf[30]), .C(intf[31]), .D(intf[32])); + split_5 #(.WIDTH(8), .FL(2), .BL(2)) splt_E(.L(intf[23]), .Ctrl(intf[53]), .A(intf[37]), .B(intf[38]), .C(intf[39]), .D(intf[40])); + split_5 #(.WIDTH(8), .FL(2), .BL(2)) splt_W(.L(intf[22]), .Ctrl(intf[52]), .A(intf[33]), .B(intf[34]), .C(intf[35]), .D(intf[36])); + split_5 #(.WIDTH(8), .FL(2), .BL(2)) splt_P(.L(intf[24]), .Ctrl(intf[54]), .A(intf[41]), .B(intf[42]), .C(intf[43]), .D(intf[44])); + arbiter_withpacket_5 #(.WIDTH(8), .FL(2), .BL(2)) arbi_N(.A(intf[30]), .B(intf[34]), .C(intf[38]), .D(intf[42]), .R(intf[45])); + arbiter_withpacket_5 #(.WIDTH(8), .FL(2), .BL(2)) arbi_S(.A(intf[26]), .B(intf[33]), .C(intf[40]), .D(intf[43]), .R(intf[46])); + arbiter_withpacket_5 #(.WIDTH(8), .FL(2), .BL(2)) arbi_E(.A(intf[28]), .B(intf[32]), .C(intf[36]), .D(intf[44]), .R(intf[48])); + arbiter_withpacket_5 #(.WIDTH(8), .FL(2), .BL(2)) arbi_W(.A(intf[25]), .B(intf[29]), .C(intf[37]), .D(intf[41]), .R(intf[47])); + arbiter_withpacket_5 #(.WIDTH(8), .FL(2), .BL(2)) arbi_P(.A(intf[27]), .B(intf[31]), .C(intf[35]), .D(intf[39]), .R(intf[49])); + data_bucket_5 #(.WIDTH(8), .BL(10)) db_N(.L(intf[45])); + data_bucket_5 #(.WIDTH(8), .BL(10)) db_S(.L(intf[46])); + data_bucket_5 #(.WIDTH(8), .BL(10)) db_E(.L(intf[48])); + data_bucket_5 #(.WIDTH(8), .BL(10)) db_W(.L(intf[47])); + data_bucket_5 #(.WIDTH(8), .BL(10)) db_P(.L(intf[49])); +initial + #50 $stop; +endmodule +*/ \ No newline at end of file diff --git a/split.sv b/split.sv new file mode 100644 index 0000000..daf62aa --- /dev/null +++ b/split.sv @@ -0,0 +1,76 @@ +`timescale 1ns/1fs +import SystemVerilogCSP::*; + +module split_4(interface L, interface Ctrl, interface A, B, C, D); +parameter FL=4; +parameter BL=6; +parameter WIDTH=34; +logic [WIDTH-1:0]packet; +logic [1:0]controlPort; +always begin + fork + begin + L.Receive(packet); + #FL; + end + begin + Ctrl.Receive(controlPort); + #FL; + end + join + + if(controlPort==2'b00) begin + A.Send(packet); + #BL; end + else if(controlPort==2'b01) begin + B.Send(packet); + #BL; end + else if(controlPort==2'b10) begin + C.Send(packet); + #BL; end + else if(controlPort==2'b11) begin + D.Send(packet); + #BL; end +end +endmodule + + +module data_generator_4(interface R); +parameter WIDTH = 12; +parameter FL = 4; +logic [WIDTH-1:0] SendValue; +always begin + SendValue = $random() % (2**WIDTH);//2**WIDTH=MAX + #FL; + R.Send(SendValue); + //$display("dg send data=%d @ %t",SendValue,$time); +end +endmodule + + + +module data_bucket_4 (interface L); +parameter WIDTH = 12; +parameter BL = 2; +logic [WIDTH-1:0] ReceiveValue; +always begin + L.Receive(ReceiveValue); + #BL; +end +endmodule + + + + +module split_tb; + Channel #(.hsProtocol(P4PhaseBD),.WIDTH(34)) intf [5:0] (); + data_generator_4 #(.WIDTH(15), .FL(15)) dg_L(.R(intf[0])); + data_generator_4 #(.WIDTH(2), .FL(15)) dg_ctrl(.R(intf[1])); + split_4 #(.WIDTH(15), .FL(15), .BL(15)) splt(.L(intf[0]), .Ctrl(intf[1]), .A(intf[2]), .B(intf[3]), .C(intf[4]), .D(intf[5])); + data_bucket_4 #(.WIDTH(15), .BL(15)) dbA(.L(intf[2])); + data_bucket_4 #(.WIDTH(15), .BL(15)) dbB(.L(intf[3])); + data_bucket_4 #(.WIDTH(15), .BL(15)) dbC(.L(intf[4])); + data_bucket_4 #(.WIDTH(15), .BL(15)) dbD(.L(intf[5])); +initial + #800 $stop; +endmodule \ No newline at end of file