URL
https://opencores.org/ocsvn/seqalign/seqalign/trunk
Subversion Repositories seqalign
Compare Revisions
- This comparison shows the changes necessary to convert path
/
- from Rev 1 to Rev 2
- ↔ Reverse comparison
Rev 1 → Rev 2
/seqalign/trunk/sw_gen_testbench.v
0,0 → 1,160
module sw_gen_testbench; |
/*(clk, |
rst, |
i_targ_length, |
target, |
i_vld, |
i_data, |
o_vld, |
m_result |
);*/ |
|
localparam |
SCORE_WIDTH = 11, |
N_A = 2'b00, //nucleotide "A" |
N_G = 2'b01, //nucleotide "G" |
N_T = 2'b10, //nucleotide "T" |
N_C = 2'b11, //nucleotide "C" |
INS = 1, //insertion penalty |
DEL = 1, //deletion penalty |
TB_UP = 2'b00, //"UP" traceback pointer |
TB_DIAG = 2'b01, //"DIAG" traceback pointer |
TB_LEFT = 2'b10; //"LEFT" traceback pointer |
|
parameter LOGLENGTH=3; //log2(total number of comparison blocks instantiated) |
parameter LENGTH = 4; //total number of comparison blocks instantiated - target length must be less than this |
|
reg rst; |
reg clk; |
reg i_local; |
reg [1:0] i_data; |
|
wire [LOGLENGTH-1:0] i_targ_length; //this is the (length_of_the_actual_target_string - 1) (must be less than the max length value - 0=1 block, 1=2 blocks, etc) |
wire [(LENGTH*2-1):0] target; //this is the actual target sequence - target[1:0] goes into block0, target[3:2] goes into block1, etc. |
|
wire o_vld; |
wire [SCORE_WIDTH-1:0] m_result; |
wire [SCORE_WIDTH-1:0] i_result; |
wire [SCORE_WIDTH-1:0] h_result; |
wire [2*(LENGTH-1)+1:0] data; |
|
reg i_vld; //master valid signal at start of chain |
wire vld[LENGTH-1:0]; |
wire reset[LENGTH-1:0]; |
|
//wire [SCORE_WIDTH*(LENGTH-1)+SCORE_WIDTH-1:0] right; |
wire [SCORE_WIDTH-1:0] right_m [LENGTH-1:0]; |
wire [SCORE_WIDTH-1:0] right_i [LENGTH-1:0]; |
wire [SCORE_WIDTH-1:0] high [LENGTH-1:0]; |
wire [LENGTH-1:0] gap; |
|
//wire [LENGTH-1:0] done; |
|
reg [SCORE_WIDTH-1:0] final_score; |
|
|
|
assign o_vld = vld[3]; |
//assign m_result = right[i_targ_length]; |
|
assign target={N_G,N_C,N_C,N_C}; |
//assign i_targ_length = 3; |
genvar i; |
|
assign i_targ_length = 2'b11; |
assign m_result = right_m[LENGTH-1]; |
assign i_result = right_i[LENGTH-1]; |
assign h_result = high[LENGTH-1]; |
|
generate |
for (i=0; i < LENGTH; i = i + 1) |
begin: pe_block |
if (i == 0) //first module in auto-generated chain |
sw_pe_affine #(.LENGTH(LENGTH), .LOGLENGTH(LOGLENGTH)) |
pe0 (.clk(clk), |
.i_rst(rst), |
.o_rst(reset[i]), |
.i_data(i_data[1:0]), |
.i_preload(target[1:0]), |
.i_left_m(11'b10000000000), |
.i_left_i(11'b10000000000), |
.i_lgap(1'b0), |
.i_vld(i_vld), |
.i_local(i_local), |
.o_right_m(right_m[i]), |
.o_right_i(right_i[i]), |
.i_high(11'b10000000000), |
.o_high(high[i]), |
.o_rgap(gap[i]), |
.o_vld(vld[i]), |
.o_data(data[2*i+1:2*i]), |
.start(1'b1)); |
//.done(done[i])); |
else //modules other than first one |
sw_pe_affine #(.LENGTH(LENGTH), .LOGLENGTH(LOGLENGTH)) |
pe1 (.clk(clk), |
.i_rst(reset[i-1]), |
.o_rst(reset[i]), |
.i_data(data[2*(i-1)+1:(i-1)*2]), |
.i_preload(target[i*2+1:i*2]), |
.i_left_m(right_m[i-1]), |
.i_left_i(right_i[i-1]), |
.i_lgap(gap[i-1]), |
.i_vld(vld[i-1]), |
.i_local(i_local), |
.o_right_m(right_m[i]), |
.o_right_i(right_i[i]), |
.i_high(high[i-1]), |
.o_high(high[i]), |
.o_rgap(gap[i]), |
.o_vld(vld[i]), |
.o_data(data[2*(i)+1:2*(i)]), |
.start(1'b0)); |
// .done(done[i])); |
|
end |
|
endgenerate |
|
|
|
|
initial |
begin |
$dumpfile("sw_gen_testbench.dump"); |
$dumpvars (0,sw_gen_testbench); |
rst <= 1'b1; |
clk <= 1'b0; |
i_vld <= 1'b0; |
i_data <= 2'b00; |
i_local <= 1'b1; |
#22 |
rst <= 1'b0; |
#100 |
i_data <= N_G; |
i_vld <= 1'b1; |
#20 |
i_data <= N_G; |
#20 |
i_data <= N_G; |
#20 |
i_data <= N_C; |
#20 |
i_vld <= 1'b0; |
#200 |
$finish(); |
|
end |
|
always |
begin |
#10 clk <= ~clk; |
end |
|
|
|
|
|
|
|
endmodule |
/seqalign/trunk/sw_pe_affine.v
0,0 → 1,178
module sw_pe_affine(clk, |
i_rst, |
o_rst, |
i_data, |
i_preload, |
i_left_m, |
i_left_i, |
i_high, |
i_vld, |
i_local, |
o_right_m, |
o_right_i, |
o_high, |
o_vld, |
o_data, |
start); |
|
localparam |
SCORE_WIDTH = 11, |
N_A = 2'b00, //nucleotide "A" |
N_G = 2'b01, //nucleotide "G" |
N_T = 2'b10, //nucleotide "T" |
N_C = 2'b11, //nucleotide "C" |
INS_START = 3, //insertion penalty |
INS_CONT = 1, |
DEL_START = 3, //deletion penalty |
DEL_CONT = 1, |
TB_UP = 2'b00, //"UP" traceback pointer |
TB_DIAG = 2'b01, //"DIAG" traceback pointer |
TB_LEFT = 2'b10, //"LEFT" traceback pointer |
GOPEN = 12, |
GEXT = 4; |
|
input wire clk; |
input wire i_rst; |
output reg o_rst; |
input wire [1:0] i_data; //sequence being streamed in |
input wire [1:0] i_preload; //fixed character assigned to this node |
input wire [SCORE_WIDTH-1:0] i_left_m; //connection to left neighbor cell for M matrix |
input wire [SCORE_WIDTH-1:0] i_left_i; //connection to left neighbor cell for I matrix |
input wire i_vld; //valid data coming from neighbor |
input wire i_local; //=1 if local alignment, =0 if global alignment |
input wire start; //designate that you're on the left edge of the array |
input wire [SCORE_WIDTH-1:0] i_high; //input of highest score from neighbor |
output reg [SCORE_WIDTH-1:0] o_right_m; //output of score from t-1 for M matrix |
output reg [SCORE_WIDTH-1:0] o_right_i; //output of score for t-1 for I matrix |
output reg [SCORE_WIDTH-1:0] o_high; //output of currently highest score |
|
output reg o_vld; //tells neighbor data is valid |
output reg [1:0] o_data; |
|
|
|
parameter LENGTH=48; |
parameter LOGLENGTH = 6; |
|
reg [1:0] state; //just state counter |
|
reg [SCORE_WIDTH-1:0] l_diag_score_m; |
reg [SCORE_WIDTH-1:0] l_diag_score_i; |
|
wire [SCORE_WIDTH-1:0] right_m_nxt; |
wire [SCORE_WIDTH-1:0] right_i_nxt; |
wire [SCORE_WIDTH-1:0] left_open; |
wire [SCORE_WIDTH-1:0] left_ext; |
wire [SCORE_WIDTH-1:0] up_open; |
wire [SCORE_WIDTH-1:0] up_ext; |
wire [SCORE_WIDTH-1:0] left_max; |
wire [SCORE_WIDTH-1:0] up_max; |
wire [SCORE_WIDTH-1:0] rightmax; |
wire [SCORE_WIDTH-1:0] start_left; |
|
reg [SCORE_WIDTH-1:0] match; |
wire [SCORE_WIDTH-1:0] max_score_a; |
wire [SCORE_WIDTH-1:0] max_score_b; |
wire [SCORE_WIDTH-1:0] left_score; |
wire [SCORE_WIDTH-1:0] up_score; |
wire [SCORE_WIDTH-1:0] diag_score; |
wire [SCORE_WIDTH-1:0] neutral_score; |
|
wire [SCORE_WIDTH-1:0] left_score_b; |
|
|
//compute new score options |
|
assign neutral_score = 11'b10000000000; |
|
assign start_left = (state==2'b01) ? (l_diag_score_m - GOPEN) : (l_diag_score_m - GEXT); |
|
assign left_open = i_left_m - GOPEN; |
assign left_ext = i_left_i - GEXT; |
assign up_open = o_right_m - GOPEN; |
assign up_ext = o_right_i - GEXT; |
assign left_max = start ? start_left : ((left_open > left_ext) ? left_open : left_ext); |
assign up_max = (up_open > up_ext) ? up_open : up_ext; |
|
assign right_m_nxt = match + ((l_diag_score_m > l_diag_score_i) ? l_diag_score_m : l_diag_score_i); //next m score |
assign right_i_nxt = (left_max > up_max) ? left_max : up_max; |
|
|
|
|
always@(posedge clk) |
o_rst <= i_rst; |
|
always@* |
case({i_data[1:0],i_preload[1:0]}) |
//this is the match-score lookup table: +5 for a match, -4 for a mismatch |
{N_A,N_A}:match = 11'b101; //+5 |
{N_A,N_G}:match = 11'h7fc; //-4 |
{N_A,N_T}:match = 11'h7fc; |
{N_A,N_C}:match = 11'h7fc; |
{N_G,N_A}:match = 11'h7fc; |
{N_G,N_G}:match = 11'b101; |
{N_G,N_T}:match = 11'h7fc; |
{N_G,N_C}:match = 11'h7fc; |
{N_T,N_A}:match = 11'h7fc; |
{N_T,N_G}:match = 11'h7fc; |
{N_T,N_T}:match = 11'b101; |
{N_T,N_C}:match = 11'h7fc; |
{N_C,N_A}:match = 11'h7fc; |
{N_C,N_G}:match = 11'h7fc; |
{N_C,N_T}:match = 11'h7fc; |
{N_C,N_C}:match = 11'b101; |
endcase |
|
//just propagate the valid signal |
always@(posedge clk) |
if (i_rst==1'b1) |
o_vld <= 1'b0; |
else |
o_vld <= i_vld; |
|
|
//This continuously calculates the highest score to pass through the block |
assign rightmax = (right_m_nxt > right_i_nxt) ? right_m_nxt : right_i_nxt; |
|
|
always@(posedge clk) |
begin |
if (i_rst==1'b1) |
o_high <= neutral_score; //reset to "0" |
else if (i_vld==1'b1) |
o_high <= (o_high > rightmax) ? ( (o_high > i_high) ? o_high : i_high) : ((rightmax > i_high) ? rightmax : i_high); |
end |
|
|
always@(posedge clk) begin |
if (i_rst==1'b1) begin |
//This is where we initialize the matrix |
o_right_m <= i_local ? neutral_score : (i_left_m - (start ? GOPEN : GEXT)); //init m matrix |
o_right_i <= i_local ? neutral_score : (i_left_i - (start ? GOPEN : GEXT)); //init i matrix |
o_data[1:0] <= 2'b00; |
l_diag_score_m <= start ? neutral_score : (i_local ? neutral_score : i_left_m); |
l_diag_score_i <= start ? neutral_score : (i_local ? neutral_score : i_left_i); |
end |
else if (i_vld==1'b1) begin |
o_data[1:0] <= i_data[1:0]; |
o_right_m <= (i_local ? ((right_m_nxt > neutral_score) ? right_m_nxt : neutral_score) : right_m_nxt); |
o_right_i <= (i_local ? ((right_i_nxt > neutral_score) ? right_i_nxt : neutral_score) : right_i_nxt); |
l_diag_score_m <= start ? (i_local ? neutral_score : (l_diag_score_m - GEXT)) : i_left_m ; |
l_diag_score_i <= start ? (i_local ? neutral_score : (l_diag_score_i - GEXT)) : i_left_i ; |
end |
end |
|
always@(posedge clk) begin |
if (i_rst) |
state <= 2'b00; |
else begin |
case(state[1:0]) |
2'b00:state[1:0] <= 2'b01; //reset state |
2'b01:if (i_vld==1'b1) state[1:0] <= 2'b10; //INIT state |
2'b10:if (i_vld==1'b0) state[1:0] <= 2'b01; //SCORE state - i_vld must be held high from the start of the query sequence to the end of it |
2'b11:if (i_rst) state[1:0] <= 2'b00; //END state |
endcase |
end |
end |
endmodule |
seqalign/trunk/sw_pe_affine.v
Property changes :
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Index: seqalign/trunk/README.txt
===================================================================
--- seqalign/trunk/README.txt (nonexistent)
+++ seqalign/trunk/README.txt (revision 2)
@@ -0,0 +1,26 @@
+This is the initial release of the code.
+
+sw_pe_affine.v is the module of the 'processing elements' that
+make up the systolic array.
+
+sw_gen_affine.v is the 'top level' file that instantiates an
+array of PEs. It is fairly easily configurable to make the array
+shorter or longer (by modifying the LENGTH and LOGLENGTH local params).
+
+sw_gen_testbench.v is a small testbench which instantiates a 4-PE
+array and compares two 4 x 4 DNA sequences.
+
+sw_gen_affine should be instantiated by the toplevel block of your design,
+along with the custom interface glue necessary to connect them.
+
+To operate the block, a query value (a packed array containing encoded 2-bit
+nucleotides) and length (in nucleotides) should be set as inputs. Then, a reset
+pulse should be sent down the array. Then, the i_vld (valid) signal should be
+held high as the comparison string is clocked in, two bits at a time, until
+the string is completed and the i_vld signal is lowered. When the o_vld signal
+goes low, the array is done processing and the result is ready. If the "local"
+bit is high, the result will be on the "o_high" output of the last element. If
+the "local" bit is low (global alignment mode), the valid result will be the
+higher of the two "o_right_*" outputs of the last element.
+
+Happy Sequencing!
Index: seqalign/trunk/sw_gen_affine.v
===================================================================
--- seqalign/trunk/sw_gen_affine.v (nonexistent)
+++ seqalign/trunk/sw_gen_affine.v (revision 2)
@@ -0,0 +1,101 @@
+module sw_gen_affine(clk,
+ rst,
+ i_query_length,
+ i_local,
+ query,
+ i_vld,
+ i_data,
+ o_vld,
+ m_result
+ );
+
+localparam
+ SCORE_WIDTH = 11,
+ N_A = 2'b00, //nucleotide "A"
+ N_G = 2'b01, //nucleotide "G"
+ N_T = 2'b10, //nucleotide "T"
+ N_C = 2'b11, //nucleotide "C"
+ INS = 1, //insertion penalty
+ DEL = 1, //deletion penalty
+ TB_UP = 2'b00, //"UP" traceback pointer
+ TB_DIAG = 2'b01, //"DIAG" traceback pointer
+ TB_LEFT = 2'b10; //"LEFT" traceback pointer
+
+parameter LOGLENGTH=6; //log2(total number of comparison blocks instantiated)
+//parameter LENGTH = 1 << LOGLENGTH; //total number of comparison blocks instantiated - query length must be less than this
+parameter LENGTH = 48;
+
+input wire rst;
+input wire clk;
+input wire [1:0] i_data;
+input wire i_local; //=1 if local alignment, =0 if global alignment
+input wire [LOGLENGTH-1:0] i_query_length; //this is the (length_of_the_actual_query_string - 1) (must be less than the max length value - 0=1 block, 1=2 blocks, etc)
+input wire [(LENGTH*2-1):0] query; //this is the actual query sequence - query[1:0] goes into block0, query [3:2] goes into block1, etc.
+
+output wire o_vld;
+output wire [SCORE_WIDTH-1:0] m_result;
+
+wire [2*(LENGTH-1)+1:0] data;
+
+input wire i_vld; //master valid signal at start of chain
+wire vld[LENGTH-1:0];
+
+wire [SCORE_WIDTH-1:0] right_m[LENGTH-1:0]; //the 'match' matrix cell value array
+wire [SCORE_WIDTH-1:0] right_i[LENGTH-1:0]; //the 'indel' matrix cell value array
+wire [SCORE_WIDTH-1:0] high_score [LENGTH-1:0]; //the 'current highest score' array
+wire [LENGTH-1:0] gap;
+wire [LENGTH-1:0] reset;
+
+
+assign o_vld = vld[i_query_length];
+assign m_result = i_local ? high_score[i_query_length] : ((right_m[i_query_length] > right_i[i_query_length]) ? right_m[i_query_length] : right_i[i_query_length]);
+
+//assign query={N_A,N_G,N_T,N_T};
+
+genvar i;
+generate
+for (i=0; i < LENGTH; i = i + 1)
+ begin: pe_block
+ if (i == 0) //first processing element in auto-generated chain
+ begin: pe_block0
+ sw_pe_affine pe0(.clk(clk),
+ .i_rst(rst),
+ .o_rst(reset[i]),
+ .i_data(i_data[1:0]),
+ .i_preload(query[1:0]),
+ .i_left_m(11'b10000000000),
+ .i_left_i(11'b10000000000),
+ .i_vld(i_vld),
+ .i_local(i_local),
+ .i_high(11'b0),
+ .o_right_m(right_m[i]),
+ .o_right_i(right_i[i]),
+ .o_high(high_score[i]),
+ .o_vld(vld[i]),
+ .o_data(data[2*i+1:2*i]),
+ .start(1'b1));
+ end
+ else //processing elements other than first one
+ begin: pe_block1
+ sw_pe_affine pe1(.clk(clk),
+ .i_rst(reset[i-1]),
+ .o_rst(reset[i]),
+ .i_data(data[2*(i-1)+1:(i-1)*2]),
+ .i_preload(query[i*2+1:i*2]),
+ .i_left_m(right_m[i-1]),
+ .i_left_i(right_i[i-1]),
+ .i_local(i_local),
+ .i_vld(vld[i-1]),
+ .i_high(high_score[i-1]),
+ .o_right_m(right_m[i]),
+ .o_right_i(right_i[i]),
+ .o_high(high_score[i]),
+ .o_vld(vld[i]),
+ .o_data(data[2*(i)+1:2*(i)]),
+ .start(1'b0));
+ end
+ end
+endgenerate
+
+
+endmodule
\ No newline at end of file
seqalign/trunk/sw_gen_affine.v
Property changes :
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property