Уважаемые друзья, Jojo, Slawikg, Bogaev_Roman и все, кто помогает мне советами!
Огромное вам за советы человеческое СПАСИБО!
С Логиклоком я сейчас разбираюсь, и начал на мелкой кошке тренироваться.
По последним Вашим замечаниям мне показалось, что я могу что-то еще не учесть.
Вдруг вас не затруднит, пробегитесь, пожалуйста по тексту моего проекта, вдруг Вы сразу заметите что-то, что я делаю криво. Буду Вам очень-очень благодарен!
Урезал проект до минимума, оставив только самый сложный кусок, который и тормозит ужастно и должен на большой частоте работать.
Код
module ...
wire [13:0] MidData[0:2]; // приходят из еще одного модуля (выход от ФИФО на МЛАБах) и синхронизованы с Clk
wire [31:0] CommonTimers[0:54]; // приходят из еще одного модуля (каунтеры 55 ножек), тоже синхронизованы с Clk
wire Clk;
...
DATA_Aq DATA_Aq_module(Clk, MidData, GPIO1_D[25], GPIO1_D[24], GPIO1_D[23], GPIO1_D[29], GPIO1_D[28],
CommonTimers);
my_pll my_pll_module1(OSC1_50, Clk); // 8-ми кратный умножитель частоты, на выходе должно быть 400МГц
endmodule
module DATA_Aq(Clk, In, ClkOut, OutOn, Out, SP1, SP2, InputCounters);
parameter N=42;
parameter M=100;
parameter LSSH=3;
parameter MAXLOCBUF=(56>N*9+5)?56:N*9+5;
parameter IMPULSEBITS=14;
parameter IMPULSELEN=16*1024;
input Clk, ClkOut, OutOn, SP1, SP2;
input [13:0] In[0:2];
input [31:0] InputCounters[0:54];
output reg Out;
// Memory ////////////////////////////
reg signed [13:0] D[0:2][0:1];
reg signed [13:0] Data[0:2][0:M-1];
wire signed [31:0] ScalY[0:8][0:N-1];
reg signed [31:0] MiddleSum[0:2];
reg [31:0] LocBuf[0:MAXLOCBUF];
wire signed [31:0] ShortSumY[0:8][0:N-1];
reg signed [31+LSSH:0] LevelSumY[0:5];
reg signed [31:0] LevelSum[0:5], ShortSum[0:5];
reg [5:0] cmpres;
reg [2:0] cmpton;
reg cmpon;
reg InDataSW;
reg [255:0] OutData;
reg [7:0] OutDataLen;
reg [IMPULSEBITS-1:0] PosIn, PosOut;
reg [31:0] OutCounter;
reg [63:0] CurTimer, ImpulseTime, ReadImpulseTime;
reg [17:0] NewStatus;
reg [7:0] BlockLen;
reg [31:0] Counters[0:54];
reg [2:0] MemCounter;
reg MemClk;
wire [251:0] OutDataMem;
wire [251:0] InDataMem;
assign InDataMem[251:238]=Data[0][M-1];
assign InDataMem[237:224]=Data[1][M-1];
assign InDataMem[223:210]=Data[2][M-1];
assign InDataMem[209:196]=Data[0][M-2];
assign InDataMem[195:182]=Data[1][M-2];
assign InDataMem[181:168]=Data[2][M-2];
assign InDataMem[167:154]=Data[0][M-3];
assign InDataMem[153:140]=Data[1][M-3];
assign InDataMem[139:126]=Data[2][M-3];
assign InDataMem[125:112]=Data[0][M-4];
assign InDataMem[111: 98]=Data[1][M-4];
assign InDataMem[ 97: 84]=Data[2][M-4];
assign InDataMem[ 83: 70]=Data[0][M-5];
assign InDataMem[ 69: 56]=Data[1][M-5];
assign InDataMem[ 55: 42]=Data[2][M-5];
assign InDataMem[ 41: 28]=Data[0][M-6];
assign InDataMem[ 27: 14]=Data[1][M-6];
assign InDataMem[ 13: 0]=Data[2][M-6];
my_lmem my_lmem_module1(InDataMem[143: 0], PosIn, InDataSW, PosOut, ClkOut, 1, OutDataMem[143: 0]); // 16*M144
my_lmem2 my_lmem_module2(InDataMem[251:144], PosIn, InDataSW, PosOut, ClkOut, 1, OutDataMem[251:144]); // 216*M9K
// Generating modules
generate
genvar i, j, k;
for(i=0; i<N; i+=2) begin : aaa
for(j=0; j<3; j++) begin : bbb
for(k=0; k<3; k++) begin : ccc
MultOne MultOne_Module(Clk, D[j][0], D[j][1], Data[k][i], Data[k][i+1], InDataSW,
ScalY [j+3*k][i], ScalY [j+3*k][i+1],
ShortSumY[j+3*k][i], ShortSumY[j+3*k][i+1]);
end end end
endgenerate
// Initialization of variables
initial
begin
MemCounter=0;
MemClk=0;
cmpres=0;
InDataSW=0;
ImpulseTime=0;
ReadImpulseTime=0;
OutData=0;
OutDataLen=0;
PosIn=0;
PosOut=0;
NewStatus=0;
BlockLen=0;
CurTimer=0;
OutCounter=0;
end
// Reading Data from Channels ///////
always @(posedge Clk) // клок на 400МГц
begin
for(int i=0; i<2; i++)
for(int j=0; j<3; j++)
D[j][i]<=Data[j][i+InDataSW];
for(int j=0; j<3; j++)
Data[j][0]<=In[j];
for(int i=0; i<M-1; i++)
for(int j=0; j<3; j++)
Data[j][i+1]<=Data[j][i];
InDataSW<=~InDataSW;
end
always @(posedge MemClk) // программный делитель на 3 от клока на 200МГц, то есть 66.6666МГц
begin
CurTimer<=CurTimer+1;
if(PosIn)
PosIn<=PosIn+1;
else if(ReadImpulseTime==ImpulseTime && cmpon)
begin
ImpulseTime<=CurTimer;
PosIn<=PosIn+1;
for(int i=0; i<55; i++)
Counters[i]<=InputCounters[i];
end
end
always @(posedge InDataSW) // программный делитель на 2 от клока на 400МГц, то есть 200МГц
begin
for(int i=0; i<3; i++)
begin
ShortSum[i*2]<=ShortSumY[i][0];
ShortSum[i*2+1]<=ShortSumY[i][0]-ShortSumY[i][1];
MiddleSum[i]<=MiddleSum[i]+D[i][0]+D[i][1]-(MiddleSum[i]>>>17);
end
//
for(int i=0; i<6; i++)
cmpres[i]<=((ShortSum[i]>=LevelSum[i])?1:0);
cmpton<=(cmpres==6'h3f && BlockLen!=0)?{cmpton[1:0], 1'b1}:{cmpton[1:0], 1'b0};
//
if(MemCounter==2)
begin
MemCounter<=0;
MemClk<=1;
cmpon<=(cmpton==7)?1:0;
end
else
begin
MemCounter<=MemCounter+1;
MemClk<=0;
end
//
if(cmpres==6'h3f)
begin
for(int i=0; i<6; i++)
begin
LevelSumY[i]<=LevelSumY[i]-(LevelSumY[i]>>>LSSH)+ShortSum[i];
LevelSum[i]<=LevelSumY[i]>>>LSSH;
end
end
end
always @(posedge SP1)
begin
NewStatus<={NewStatus[16:0], SP2};
if(NewStatus[17:13]==5'b01010 && NewStatus[4:0]==5'b01010)
BlockLen<=NewStatus[12:5];
end
always @(posedge ClkOut) // медленный клок 15МГц для сбора данных с плиски, никак не синхронизован с теми клоками, которые выше, блок написан абы как, так как при этой скорости выжимать производительность не имеет смысла
begin
if(OutOn==0)
begin
begin
{OutData[254:0], Out}<=OutData;
if(OutDataLen>0) OutDataLen<=OutDataLen-1;
else
begin
////////////////////////////////
if(OutCounter==0)
begin
OutDataLen<=63;
if(ImpulseTime>ReadImpulseTime)
begin
OutCounter<=64-57;
OutData<={32'h0000ffff, 32'h0000ffff};
LocBuf[0]<=ImpulseTime[63:32];
LocBuf[1]<=ImpulseTime[31:0];
for(int i=0; i<55; i++)
LocBuf[i+2]<=Counters[i];
end
else
begin
OutCounter<=512-N*9-5;
OutData<={32'h0000ffff, 32'h0000aaaa};
LocBuf[0]<=CurTimer[63:32];
LocBuf[1]<=CurTimer[31:0];
for(int i=0; i<N*9; i++)
LocBuf[i+2]<=ScalY[i%9][i/9];
for(int i=0; i<3; i++)
LocBuf[i+N*9+2]<=MiddleSum[i];
end
end
////////////////////////////////
else if(OutCounter==63)
begin
OutCounter<=512;
OutData<=LocBuf[0];
end
////////////////////////////////
else if(OutCounter==511)
begin
OutCounter<=0;
OutData<=LocBuf[0];
end
////////////////////////////////
else if(OutCounter<511)
begin
OutDataLen<=31;
OutCounter<=OutCounter+1;
OutData<=LocBuf[0];
for(int i=1; i<MAXLOCBUF; i++)
LocBuf[i-1]<=LocBuf[i];
end
////////////////////////////////
else if(OutCounter<64*BlockLen+511)
begin
PosOut<=PosOut+1;
OutCounter<=OutCounter+1;
OutDataLen<=251;
OutData<=OutDataMem;
end
else
////////////////////////////////
begin
PosOut<=0;
OutCounter<=0;
OutDataLen<=251;
OutData<=OutDataMem;
ReadImpulseTime=ImpulseTime;
end
end
end
end
end
endmodule
module MultOne(Clk, A1, A2, B1, B2, SW, Res1, Res2, PRes1, PRes2);
parameter SHR=18;
parameter RSH=5;
input Clk, SW;
input signed [13:0] A1, A2, B1, B2;
output reg signed [31:0] Res1, Res2;
output reg signed [31:0] PRes1, PRes2;
reg signed [13:0] P1, P2, Q1, Q2;
reg signed [28:0] Sum;
reg signed [28:0] SumR0, SumR1, SumR2, SumDM0, SumDM1;
// reg signed [31:0] Mul1, Mul2;
reg signed [28+SHR:0] ScalX1, ScalX2;
reg signed [28+RSH:0] ScalZ1, ScalZ2;
reg signed [31:0] Z_Res1, Z_Res2;
reg signed [31:0] Z_PRes1, Z_PRes2;
my_madd my_madd_module(Clk, P1, Q1, P2, Q2, Sum); // мегафункция altmult_add
always @(posedge Clk) // частота 400МГц
begin
P1<=A1;
P2<=A2;
Q1<=B1;
Q2<=B2;
// Mul1<=P1*Q1; Mul2<=P2*Q2; Sum<=Mul1+Mul2;
SumR0<=Sum;
SumR1<=SumR0;
SumR2<=SumR1;
end
always @(posedge SW) // половина частоты Clk
begin
SumDM0<=SumR1;
SumDM1<=SumR2;
//
ScalX1<=ScalX1+SumDM0-(ScalX1>>>SHR);
ScalX2<=ScalX2+SumDM1-(ScalX2>>>SHR);
Z_Res1<=ScalX1[28+SHR:SHR-3];
Z_Res2<=ScalX2[28+SHR:SHR-3];
Res1<=Z_Res1;
Res2<=Z_Res2;
//
ScalZ1<=ScalZ1+SumDM0-(ScalZ1>>>RSH);
ScalZ2<=ScalZ2+SumDM1-(ScalZ2>>>RSH);
Z_PRes1<=ScalZ1[28+RSH:RSH-3];
Z_PRes2<=ScalZ2[28+RSH:RSH-3];
PRes1<=Z_PRes1;
PRes2<=Z_PRes2;
end
endmodule
а констрейны написаны в файле так:
Код
set_time_format -unit ns -decimal_places 3
#**************************************************************
# Create Clock
#**************************************************************
derive_clocks -period "1.0"
create_clock -name {GPIO1_D[29]} -period 1000. -waveform {0.0 500.} [get_ports {GPIO1_D[29]}]
create_clock -name {GPIO1_D[25]} -period 60. -waveform {0.0 30.} [get_ports {GPIO1_D[25]}]
########################
create_clock "DATA_Aq:DATA_Aq_module|InDataSW" -name {DATA_Aq:DATA_Aq_module|InDataSW} -period 4.8 -waveform {0.0 2.4}
create_clock "DATA_Aq:DATA_Aq_module|MemClk" -name {DATA_Aq:DATA_Aq_module|MemClk} -period 28.8 -waveform {0.0 14.4}
########################
derive_pll_clocks
#**************************************************************
# Create Clock
#**************************************************************
create_clock "OSC2_50" -name "CLK" -period 20
#**************************************************************
# Create Generated Clock
#**************************************************************
create_generated_clock -master_clock 20. -source "OSC1_50" -name "CLK_OUT" -multiply_by 8 -divide_by 1
create_generated_clock -master_clock 20. -source "OSC1_50" -name "Clk" -multiply_by 8 -divide_by 1 [get_ports {my_pll_module1|altpll_component|auto_generated|pll1|clk[0]}]
Спасибо!
ЗЫ несколько редактирований этого сообщения были вызваны глюком при набивке сообщения и желанием откоментарить текст для удобства восприятия