|
|
|
|
|
|
|
|
|
|
module Dyna_Tree ( clk, glob_com, dataIn, dataOut );
|
module Dyna_Tree ( clk, glob_com, dataIn, dataOut );
|
|
|
parameter HBIT= 3;
|
parameter HBIT= 3;
|
parameter TREE_LEVEL= 4;
|
parameter TREE_LEVEL= 4;
|
parameter IMRIGHT= 0;
|
parameter IMRIGHT= 0;
|
|
|
input clk;
|
input clk;
|
input [1:0] glob_com;
|
input [1:0] glob_com;
|
|
|
output TPort dataOut;
|
output TPort dataOut;
|
input TPort dataIn;
|
input TPort dataIn;
|
|
|
|
|
TPort fromLeft;
|
TPort fromLeft;
|
TPort fromRight;
|
TPort fromRight;
|
|
|
Cell_DT_Inner #( HBIT, IMRIGHT ) inner ( clk, glob_com, dataIn, fromLeft, fromRight, dataOut );
|
Cell_DT_Inner #( HBIT, IMRIGHT ) inner ( clk, glob_com, dataIn, fromLeft, fromRight, dataOut );
|
|
|
generate
|
generate
|
if ( TREE_LEVEL >0 )
|
if ( TREE_LEVEL >0 )
|
begin
|
begin
|
Dyna_Tree #( HBIT, TREE_LEVEL-1, 0 ) leftSubTree ( clk, glob_com, dataOut, fromLeft );
|
Dyna_Tree #( HBIT, TREE_LEVEL-1, 0 ) leftSubTree ( clk, glob_com, dataOut, fromLeft );
|
Dyna_Tree #( HBIT, TREE_LEVEL-1, 1 ) rightSubTree ( clk, glob_com, dataOut, fromRight );
|
Dyna_Tree #( HBIT, TREE_LEVEL-1, 1 ) rightSubTree ( clk, glob_com, dataOut, fromRight );
|
end
|
end
|
else
|
else
|
begin
|
begin
|
assign fromLeft.msg =VMS_STOP;
|
assign fromLeft.msg =VMS_STOP;
|
assign fromRight.msg=VMS_STOP;
|
assign fromRight.msg=VMS_STOP;
|
end
|
end
|
endgenerate
|
endgenerate
|
|
|
|
|
endmodule
|
endmodule
|
|
|
|
|
|
|
|
|
|
|
|
|
typedef enum bit[3:0] { VK_EMPTY=4'h0,
|
typedef enum bit[3:0] { VK_EMPTY=4'h0,
|
VK_EOF,
|
|
VK_DUMMY1,
|
VK_DUMMY1,
|
VK_DUMMY2,
|
VK_DUMMY2,
|
VK_DUMMY3,
|
VK_DUMMY3,
|
|
|
VK_DUMMY4,
|
VK_DUMMY4,
|
VK_DUMMY5,
|
VK_TRANSIT,
|
VK_APPLY,
|
VK_APPLY,
|
VK_K,
|
VK_EOF,
|
VK_DUMMY6,
|
|
VK_DUMMY7,
|
VK_K[2]= 4'h8,
|
VK_DUMMY8,
|
|
VK_DUMMY9
|
VK_S[3]= 4'd12,
|
|
VK_DUMMY5
|
} VKind;
|
} VKind;
|
|
|
|
function logic [1:0] CH_NUM( logic [3:0] k );
|
|
CH_NUM = k[1:0];
|
|
endfunction
|
|
|
typedef enum bit[3:0] { VMS_EMPTY=4'h0,
|
typedef enum bit[3:0] { VMS_EMPTY=4'h0,
|
VMS_EOF,
|
|
VMS_READY,
|
VMS_READY,
|
VMS_WRITE,
|
VMS_PROCESS,
|
|
VMS_BOMB,
|
|
|
VMS_READ,
|
VMS_READ,
|
|
VMS_APPLY,
|
VMS_STOP // end of tree
|
VMS_STOP // end of tree
|
} VMeta;
|
} VMeta;
|
|
|
typedef enum bit[1:0]{ TO_PARENT=2'h0,
|
typedef enum bit[1:0]{ TO_PARENT=2'h0,
|
TO_CHILDREN,
|
TO_CHILDREN,
|
TO_LEFT,
|
TO_LEFT,
|
TO_RIGHT
|
TO_RIGHT
|
} VTarget;
|
} VTarget;
|
|
|
typedef struct{
|
typedef struct{
|
bit [3:0] msg;
|
bit [3:0] msg;
|
bit [1:0] tgt;
|
bit [1:0] tgt;
|
} TPort;
|
} TPort;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
module Cell_DT_Inner ( clk, glob_com, i_fromParent, i_fromLeft, i_fromRight, message );
|
module Cell_DT_Inner ( clk, glob_com, i_fromParent, i_fromLeft, i_fromRight, message );
|
parameter HBIT= 7;
|
parameter HBIT= 7;
|
parameter IMRIGHT= 0;
|
parameter IMRIGHT= 0;
|
|
|
input clk;
|
input clk;
|
input [1:0] glob_com;
|
input [1:0] glob_com;
|
|
|
input TPort i_fromParent;
|
input TPort i_fromParent;
|
input TPort i_fromLeft;
|
input TPort i_fromLeft;
|
input TPort i_fromRight;
|
input TPort i_fromRight;
|
|
|
wire [HBIT:0] fromParent= ((IMRIGHT==0) && ( i_fromParent.tgt == TO_CHILDREN || i_fromParent.tgt == TO_LEFT )) ||
|
wire [HBIT:0] fromParent= ((IMRIGHT==0) && ( i_fromParent.tgt == TO_CHILDREN || i_fromParent.tgt == TO_LEFT )) ||
|
((IMRIGHT==1) && ( i_fromParent.tgt == TO_CHILDREN || i_fromParent.tgt == TO_RIGHT ))
|
((IMRIGHT==1) && ( i_fromParent.tgt == TO_CHILDREN || i_fromParent.tgt == TO_RIGHT ))
|
? i_fromParent.msg : 4'h0;
|
? i_fromParent.msg : 4'h0;
|
|
|
wire [HBIT:0] fromLeft= ( i_fromLeft.tgt == TO_PARENT ) ? i_fromLeft.msg : 4'h0;
|
wire [HBIT:0] fromLeft= ( i_fromLeft.tgt == TO_PARENT ) ? i_fromLeft.msg : 4'h0;
|
wire [HBIT:0] fromRight= ( i_fromRight.tgt == TO_PARENT ) ? i_fromRight.msg : 4'h0;
|
wire [HBIT:0] fromRight= ( i_fromRight.tgt == TO_PARENT ) ? i_fromRight.msg : 4'h0;
|
|
|
reg [HBIT:0] value;
|
reg [HBIT:0] value;
|
output TPort message;
|
output TPort message;
|
VMeta state;
|
VMeta state;
|
reg [3:0] step;
|
reg [3:0] step;
|
|
|
always@(posedge clk )
|
always@(posedge clk )
|
begin
|
begin
|
case( glob_com )
|
case( glob_com )
|
0: // working mode
|
0: // working mode
|
begin
|
begin
|
case( state )
|
case( state )
|
VMS_EMPTY: // sleeping
|
VMS_EMPTY: // sleeping
|
begin
|
begin
|
value <= fromParent==VK_APPLY || fromParent==VK_K ? fromParent : VK_DUMMY9; // write self
|
if ( !value )
|
case( fromParent )
|
begin // writing left
|
VK_EMPTY:; // still sleeping
|
value <= fromParent;//==VK_APPLY || fromParent==VK_EMPTY || fromParent==VK_K0 ? fromParent : VK_DUMMY5; // write self
|
VK_APPLY: // write subtrees
|
if ( fromParent && CH_NUM( fromParent )==0 )
|
state <= VMS_WRITE;
|
|
default: // i'm a leaf
|
|
begin
|
begin
|
message.msg <= VMS_READY;
|
message.msg <= VMS_READY;
|
message.tgt <= TO_PARENT;
|
message.tgt <= TO_PARENT;
|
state <= VMS_READY;
|
state <= VMS_READY;
|
end
|
end
|
endcase
|
|
end
|
end
|
|
else if ( CH_NUM( value )!=0 && ~fromLeft[0] )
|
VMS_WRITE:
|
|
begin
|
|
case( step )
|
|
0: // writing left
|
|
if ( fromLeft == VMS_EMPTY )
|
|
begin // write left
|
begin // write left
|
message.msg <= fromParent;
|
message.msg <= fromParent;
|
message.tgt <= TO_LEFT;
|
message.tgt <= TO_LEFT;
|
end
|
end
|
else
|
else if ( CH_NUM( value )==2 && ~fromRight[0] )
|
begin // begin writing right
|
begin // begin writing right
|
message.msg <= fromParent;
|
message.msg <= fromParent;
|
message.tgt <= TO_RIGHT;
|
message.tgt <= TO_RIGHT;
|
step <= step+4'h1;
|
|
end
|
|
1: // writing right
|
|
if ( fromRight == VMS_EMPTY )
|
|
begin // write right
|
|
message.msg <= fromParent;
|
|
message.tgt <= TO_RIGHT;
|
|
end
|
end
|
else
|
else
|
begin // job well done, notify parent
|
begin
|
message.msg <= VMS_READY;
|
message.msg <= VMS_READY;
|
message.tgt <= TO_PARENT;
|
message.tgt <= TO_PARENT;
|
state <= VMS_READY;
|
state <= VMS_READY;
|
step <= 0;
|
|
end
|
end
|
endcase
|
|
end
|
end
|
|
|
VMS_READ:
|
VMS_READ:
|
begin
|
begin
|
case( step )
|
if ( message.msg == VK_EOF )
|
0:
|
|
if ( value != VK_APPLY )
|
|
begin
|
begin
|
message.msg <= VK_EOF; // leaf's report
|
message.msg <= VMS_READY; // end read 2
|
message.tgt <= TO_PARENT;
|
|
state <= VMS_READY;
|
state <= VMS_READY;
|
end
|
end
|
else if ( fromLeft==VMS_READY )
|
// else if ( message.msg == VMS_READY && value != VK_TRANSIT )
|
|
// begin
|
|
// message.msg <= value; // read self
|
|
// message.tgt <= TO_PARENT;
|
|
// end
|
|
else if ( CH_NUM( value )==0 )
|
begin
|
begin
|
message.msg <= VMS_READ; // begin read left
|
message.msg <= VK_EOF; // end read 1.1
|
message.tgt <= TO_LEFT;
|
|
step <= 4'h1;
|
|
end
|
end
|
else
|
else if ( ~step[0] && fromLeft == VMS_READY )
|
message.msg <= VK_EMPTY; // wait for left
|
|
1:
|
|
case( fromLeft )
|
|
VK_EMPTY:;
|
|
VK_EOF:
|
|
begin
|
begin
|
step <= 4'h2;
|
message.msg <= VMS_READ; // command left
|
message.msg <= VK_EMPTY;
|
message.tgt <= TO_LEFT;
|
end
|
end
|
default: // transfer left
|
else if ( ~step[0] && fromLeft != VK_EOF )
|
begin
|
begin
|
message.msg <= fromLeft;
|
message.msg <= fromLeft; // transfer left
|
message.tgt <= TO_PARENT;
|
message.tgt <= TO_PARENT;
|
end
|
end
|
endcase
|
else if ( CH_NUM( value )==1 )
|
2: // begin read right
|
|
if ( fromRight==VMS_READY )
|
|
begin
|
begin
|
message.msg <= VMS_READ;
|
message.msg <= VK_EOF; // end read 1.2
|
message.tgt <= TO_RIGHT;
|
|
step <= 4'h3;
|
|
end
|
end
|
else
|
else if ( fromRight == VMS_READY )
|
message.msg <= VK_EMPTY; // wait for right
|
|
3:
|
|
case( fromRight )
|
|
VK_EMPTY:;
|
|
VK_EOF:
|
|
begin
|
begin
|
message.msg <= fromRight;
|
message.msg <= VMS_READ; // command right
|
state <= VMS_READY;
|
message.tgt <= TO_RIGHT;
|
step <= 0;
|
step[0] <= 1;
|
end
|
end
|
default: // transfer right
|
else if ( fromRight != VK_EOF )
|
begin
|
begin
|
message.msg <= fromRight;
|
message.msg <= fromRight; // transfer right
|
message.tgt <= TO_PARENT;
|
message.tgt <= TO_PARENT;
|
end
|
end
|
endcase
|
else
|
endcase
|
begin
|
|
message.msg <= VK_EOF; // end read 1.3
|
|
step[0] <= 0;
|
|
end
|
|
|
|
|
end
|
end
|
|
|
VMS_READY:
|
VMS_READY:
|
begin
|
begin
|
case( fromParent )
|
case( fromParent )
|
|
VMS_BOMB: // clear
|
|
begin
|
|
message.msg <= VMS_BOMB;
|
|
message.tgt <= TO_CHILDREN;
|
|
state <= VMS_EMPTY;
|
|
value <= VK_EMPTY;
|
|
end
|
VMS_READ: // read self
|
VMS_READ: // read self
|
begin
|
begin
|
|
if ( value != VK_TRANSIT )
|
|
begin
|
message.msg <= value;
|
message.msg <= value;
|
message.tgt <= TO_PARENT;
|
message.tgt <= TO_PARENT;
|
|
end
|
state <= VMS_READ;
|
state <= VMS_READ;
|
end
|
end
|
|
VMS_APPLY: // apply string from parent to itself
|
|
begin
|
|
if ( CH_NUM( value )!=0 )
|
|
begin
|
|
message.msg <= VMS_APPLY;
|
|
message.tgt <= TO_CHILDREN;
|
|
end
|
|
begin
|
|
case( value )
|
|
VK_K0,
|
|
VK_S0,
|
|
VK_S1:
|
|
begin // add argument
|
|
value[1:0] <= value[1:0] +1; // K0 -> K1, S0 -> S1, S1 -> S2
|
|
state <= VMS_EMPTY; // WRITE
|
|
end
|
|
VK_K1: // K main
|
|
begin
|
|
value <= VK_TRANSIT;
|
|
state <= VMS_READY;
|
|
message.msg <= VMS_BOMB;
|
|
message.tgt <= TO_RIGHT;
|
|
end
|
|
VK_S2: // S main
|
|
begin
|
|
state <= VMS_APPLY;
|
|
end
|
|
endcase
|
|
end
|
|
end
|
default:
|
default:
|
begin
|
begin
|
message.msg <= VMS_READY;
|
message.msg <= VMS_READY;
|
message.tgt <= TO_PARENT;
|
message.tgt <= TO_PARENT;
|
end
|
end
|
endcase
|
endcase
|
end
|
end
|
|
|
|
VMS_APPLY:
|
|
if ( fromParent != VK_EOF )
|
|
begin
|
|
message.msg <= fromParent; // Sxyz -> `(_`_xz) (_`_yz)
|
|
message.tgt <= TO_CHILDREN;
|
|
end
|
|
else
|
|
begin
|
|
message.msg <= VK_EMPTY;
|
|
state <= VMS_READY;
|
|
value <= VK_APPLY; // Sxyz -> _`_ (`xz) (`yz)
|
|
end
|
endcase
|
endcase
|
end
|
end
|
default: // reset mode
|
default: // reset mode
|
begin
|
begin
|
state <= VMS_EMPTY;
|
state <= VMS_EMPTY;
|
|
value <= VK_EMPTY;
|
message.msg <= VMS_EMPTY;
|
message.msg <= VMS_EMPTY;
|
step <= 0;
|
step <= 0;
|
end
|
end
|
endcase
|
endcase
|
end
|
end
|
|
|
endmodule
|
endmodule
|
|
|
|
|
|
|
|
|