|
|
  |
Через некоторое время перестает работать проект, Машина состояний впадает в неопределенное состояние |
|
|
|
Mar 23 2015, 14:15
|
Частый гость
 
Группа: Свой
Сообщений: 150
Регистрация: 20-08-04
Пользователь №: 529

|
Вообщем возникла такая проблема и уже не пойму в какую сторону копать: Ниже код передатчика от MAC. Запускаю, некоторое время все работает, но по непонятным причинам, через несколько сотен посылок, код перестает работать. Конкретно проблема возникает в том что машина состояний state_Tx уходит в неопределенное состояние, то есть становится равной НУЛЮ (смотрел в Signal Tap). А в нормальном режиме он хоть чему нибудь должна быть равна. Еще добавил default в case , при заходе в который state_Tx должна стать равной RESET, но не помогло. Так же когда state_Tx становиться равным нулю, начинают увеличиваться rdaddress , он доходит до 0x3F и начинает с нуля. И data_count, считает до 0x3ff. Также обновляется temp_CRC32. До этого при некоторых вариантах компиляции проекта все работало отлично. Стоит чего либо поменять, начинает работать нестабильно. Уже не знаю что может вызывать такой эффект. Может кто свежим взглядом посмотрит и направит на путь истинный. Кстати с констрейнами я плохо дружу. Попытался прописать клоки, но результат вроде как стал хуже. Теперь при различных компиляциях вообще не работает нормально (при подключеном stp и без него). Основная проблема в том что я не могу понять, почему state_Tx становиться равным НУЛЮ ? Подскажите, в какую сторону дальше грести.
------ SDC файл ---- Код create_clock -name {altera_reserved_tck} -period 100.000 -waveform { 0.000 50.000 } [get_ports {altera_reserved_tck}] create_clock -name {CLOCK_50} -period 20.000 -waveform { 0.000 10.000 } [get_ports {CLOCK_50}] create_clock -name {CLOCK2_50} -period 20.000 -waveform { 0.000 10.000 } [get_ports {CLOCK2_50}] create_clock -name {CLOCK3_50} -period 20.000 -waveform { 0.000 10.000 } [get_ports {CLOCK3_50}] create_clock -name {PHY_RX_CLOCK} -period 8.000 -waveform { 0.000 4.000 } [get_ports { ENET0_RX_CLK }] create_clock -name {PHY_TX_CLOCK} -period 8.000 -waveform { 0.000 4.000 } [get_ports { ENET0_TX_CLK }] - это пин с PHY контроллера
#************************************************************** # Create Generated Clock #**************************************************************
create_generated_clock -name {PHY_TX_CLOCK_2} -source [get_ports {ENET0_TX_CLK}] -duty_cycle 50.000 -multiply_by 1 -divide_by 2 -master_clock {PHY_TX_CLOCK} [get_nets {gen_tx_clock_2}] Кусок из верхнего уровня, который генерит PHY_TX_CLOCK_2 Код GLOBAL tx_clk_inst1 (.in( !ENET0_TX_CLK ), .out(PHY_TX_CLOCK)); // Делает линию PHY_TX_CLOCK глобальной тактовой
// generate PHY_TX_CLOCK/2 for 100T wire PHY_TX_CLOCK_2; reg gen_tx_clock_2; always @ (posedge PHY_TX_CLOCK) gen_tx_clock_2 <= ~gen_tx_clock_2;
GLOBAL tx_clk_inst2 (.in( gen_tx_clock_2 ), .out(PHY_TX_CLOCK_2)); // Глобальная линия для TX_CLK/2 CODE module Tx_MAC ( Tx_clock, Tx_clock_2, IF_rst, Send_ARP,ping_reply, PHY_Tx_data, PHY_Tx_rdused, ping_data, LED, Tx_fifo_rdreq, Tx_CTL, ARP_sent, ping_sent, TD, DHCP_discover, DHCP_discover_sent, This_MAC,SIADDR, DHCP_request, DHCP_request_sent, METIS_discovery, PC_IP, PC_MAC, Port, This_IP, METIS_discover_sent, ARP_PC_MAC, ARP_PC_IP, Ping_PC_MAC, Ping_PC_IP, Length, speed_100T, Tx_reset, run, wide_spectrum, IP_valid, printf, IP_lease, DHCP_IP, DHCP_MAC, DHCP_request_renew, DHCP_request_renew_sent, erase_done, erase_done_ACK, send_more, send_more_ACK, Hermes_serialno, sp_fifo_rddata, sp_fifo_rdreq, sp_fifo_rdempty, sp_fifo_rdused, have_sp_data, AssignIP, pll_data, send_pll_data, send_pll_data_ACK ); input Tx_clock; // 25MHz for 100T input Tx_clock_2; // clock/2 input IF_rst; // reset signal input Send_ARP; // high to send ARP response input ping_reply; // high to send ping response input [7:0]PHY_Tx_data; // data to send to PHY input [10:0]PHY_Tx_rdused; // data available in Tx fifo input [7:0]ping_data[0:59]; // data to send back input DHCP_discover; // high when requested input [47:0]This_MAC; // MAC address of this Metis board input [31:0]SIADDR; // IP address of server that provided IP address input DHCP_request; // high when request required input METIS_discovery; // high when reply required input [31:0]PC_IP; // IP address of the PC we are connecting to input [47:0]PC_MAC; // MAC address of the PC we are connecting to input [15:0]Port; // Port on the PC we are sending to input [31:0]This_IP; // IP address provided by PC or DHCP at start up input [47:0]ARP_PC_MAC; // MAC address of PC requesting ARP input [31:0]ARP_PC_IP; // IP address of PC requesting ARP input [47:0]Ping_PC_MAC; // MAC address of PC requesting ping input [31:0]Ping_PC_IP; // IP address of PC requesting ping input [15:0]Length; // Lenght of packet - used by ping input speed_100T; // high for 100T,low for 1000T ************ check input Tx_reset; // high to prevent I&Q data being sent input run; // high to enable data to be sent input wide_spectrum; // high to enable wide spectrum data to be sent input IP_valid; // high when we have a valid IP address input printf; // high when we want to send debug data input [31:0]IP_lease; // *** test data - IP lease time in seconds input [31:0]DHCP_IP; // IP address of DHCP server input [47:0]DHCP_MAC; // MAC address of DHCP server input DHCP_request_renew; // set when renew required input erase_done; // set when we what to tell the PC we have completed the EPCS16 erase input send_more; // set when we want the next block of 256 bytes for the EPCS16 input [7:0]Hermes_serialno; // Hermes code version input [7:0]sp_fifo_rddata; // raw ACD data from Mercury for wide bandscope input sp_fifo_rdempty; // SP_fifo read empty input [12:0]sp_fifo_rdused; // SP_fifo contents input have_sp_data; // high when sp_fifo is full. input [31:0]AssignIP; // IP address read from EEPROM
input [7:0] pll_data [0:32]; // Массив регистров pll input send_pll_data; output send_pll_data_ACK;
output LED; // show MAC is doing something! output Tx_fifo_rdreq; // high to indicate read from Tx fifo required output Tx_CTL; // high to enable write to PHY output ARP_sent; // high indicates ARP has been sent output ping_sent; // high indicates ping reply has been sent output [3:0]TD; // nibble to send to PHY output DHCP_discover_sent; // high when has been sent output DHCP_request_sent; // high when has been sent output METIS_discover_sent; // high when has been sent ** pulse output DHCP_request_renew_sent; // high when has been sent output erase_done_ACK; // set when we have sent erase of EPCS16 complete to PC output send_more_ACK; // set when we confirm we have requested more EPCS data from PC output sp_fifo_rdreq; // SP_fifo read require signal
// HPSDR specific parameter HPSDR_frame = 8'h01; // HPSDR Frame type parameter HPSDR_IP_frame = 8'h03; // Read IP Frame type // parameter end_point = 8'h06; // HPSDR end point - 6 to indicate fifo write parameter Type_1 = 8'hEF; // Ethernet Frame type parameter Type_2 = 8'hFE; localparam TxPort = 16'd1024; // Metis 'from' port //localparam IP_MAC = 48'h00_22_33_44_55_66; // MAC address used for setting and reading IP address
localparam RESET = 1, UDP = 2, // METIS_DISCOVERY = 4, ARP = 8, PING1 = 16, PING2 = 32, // DHCP_DISCOVER = 64, // DHCP_REQUEST = 128, // DHCP_REQUEST_RENEW = 256, // PRINTF = 512, // SPECTRUM = 1024, // SENDIP = 11, CRC = 2048, // TEST_PACKET = 4096, PLL_DATA = 8192;
wire [7:0]ping_data[0:59]; // data to send back wire [31:0] CRC32; // holds 802.3 CRC result reg [31:0] temp_CRC32 = 0;
reg [31:0] sequence_number = 0; reg [31:0] spec_seq_number = 0;
reg sp_fifo_rdreq; reg DHCP_request_sent; reg Tx_fifo_rdreq; reg METIS_discover_sent; reg DHCP_discover_sent;
reg [15:0] state_Tx; // state for FX2 reg [10:0] data_count; reg [10:0] sp_data_count; reg reset_CRC; reg [7:0] Tx_data; reg [4:0] gap_count; reg ARP_sent; // true when we have replied to an ARP request reg LED; // Test LED reg erase_done_ACK; // set when we have sent erase of EPCS16 complete to PC reg send_more_ACK; // set when we confirm we have requested more EPCS data from PC reg [31:0]Discovery_IP; // IP address of PC doing Discovery reg [47:0]Discovery_MAC; // MAC address of PC doing Discovery reg [15:0]Discovery_Port; // Port Address of PC doing Discovery
reg [7:0]end_point; // USB end point equivalent 8'h06 for IQ data and 8'h04 for Spectrum reg [4:0]IP_count; // holds shift count when sending IP to PHY TX fifo
wire [15:0]DHCP_length; wire [15:0]UDP_DHCP_length;
wire [15:0]DHCP_req_length; wire [15:0]UDP_DHCP_req_length;
wire [15:0]DHCP_req_renew_length; wire [15:0]UDP_DHCP_req_renew_length;
reg [9:0] rdaddress; reg [7:0] pkt_data; reg [7:0] ck_count; reg [31:0]ping_check_temp; reg [15:0]ping_check_sum; reg ping_sent; reg [8:0] zero_count; reg [3:0]interframe; reg xprintf; reg DHCP_request_renew_sent; reg Metis_discover_sent; reg [7:0] frame; // HPSDR frame type; 0x02 for Discovery reply, // 0x03 for EPCS16 erase complete and // 0x04 for send next 256 bytes for EPCS16 program reg [31:0]temp_IP; // holds IP address from EEPROM whilst we are shifting
reg [4:0]PHY_state; reg sync_Tx_CTL; reg [3:0] sync_TD;
assign Reset = IF_rst; // Set reset signal to IF_rst
// calculate the IP checksum, big-endian style // The 0xC935 is fixed and made up of the 16 bit add of the header data. *** this will need changing if we change payload size **** // i.e. 0x4500 + 0x0424 + 0x8011 = 0xC935 // then add the IPsource and IPDesitination in 16 bits using 1's complement and then complement
// calculate the UDP/IP checksum wire [31:0]IPchecksum1; wire [31:0]IPchecksum2; wire [15:0]IPchecksum3;
assign IPchecksum1 = 32'h0000C935 + This_IP[31:16] + This_IP[15:0] + PC_IP[31:16] + PC_IP[15:0]; assign IPchecksum2 = ((IPchecksum1 & 32'h0000FFFF) + (IPchecksum1 >> 16)); // 1's complement add, shift the higher order bits and add assign IPchecksum3 = ~((IPchecksum2 & 32'h0000FFFF) + (IPchecksum2 >> 16)); // again, then complement
// calculate the UDP/IP checksum for Metis discovery wire [31:0]DISchecksum1; wire [31:0]DISchecksum2; wire [15:0]DISchecksum3;
assign DISchecksum1 = 32'h00004500 + 32'h00000058 + 32'h00008011 + This_IP[31:16] + This_IP[15:0] + Discovery_IP[31:16] + Discovery_IP[15:0]; assign DISchecksum2 = ((DISchecksum1 & 32'h0000FFFF) + (DISchecksum1 >> 16)); // 1's complement add, shift the higher order bits and add assign DISchecksum3 = ~((DISchecksum2 & 32'h0000FFFF) + (DISchecksum2 >> 16)); // again, then complement
// calculate the IP checksum for ICMP (ping) wire [31:0]ICMPchecksum1; wire [31:0]ICMPchecksum2; wire [15:0]ICMPchecksum3;
assign ICMPchecksum1 = 32'h00004500 + Length + 32'h00008001 + This_IP[31:16] + This_IP[15:0] + Ping_PC_IP[31:16] + Ping_PC_IP[15:0]; assign ICMPchecksum2 = ((ICMPchecksum1 & 32'h0000FFFF) + (ICMPchecksum1 >> 16)); // 1's complement add, shift the higher order bits and add assign ICMPchecksum3 = ~((ICMPchecksum2 & 32'h0000FFFF) + (ICMPchecksum2 >> 16)); // again, then complement
// calculate the IP checksum for DHCP discovery wire [31:0]DHCPchecksum1; wire [31:0]DHCPchecksum2; wire [15:0]DHCPchecksum3;
assign DHCPchecksum1 = 32'h00004500 + UDP_DHCP_length + 32'h00008011 + 32'h0000FFFF + 32'h0000FFFF; assign DHCPchecksum2 = ((DHCPchecksum1 & 32'h0000FFFF) + (DHCPchecksum1 >> 16)); // 1's complement add, shift the higher order bits and add assign DHCPchecksum3 = ~((DHCPchecksum2 & 32'h0000FFFF) + (DHCPchecksum2 >> 16)); // again, then complement
// calculate IP checksum for DHCP request wire [31:0]DHCP_req_checksum1; wire [31:0]DHCP_req_checksum2; wire [15:0]DHCP_req_checksum3;
assign DHCP_req_checksum1 = 32'h00004500 + UDP_DHCP_req_length + 32'h00008011 + 32'h0000FFFF + 32'h0000FFFF; assign DHCP_req_checksum2 = ((DHCP_req_checksum1 & 32'h0000FFFF) + (DHCP_req_checksum1 >> 16)); // 1's complement add, shift the higher order bits and add assign DHCP_req_checksum3 = ~((DHCP_req_checksum2 & 32'h0000FFFF) + (DHCP_req_checksum2 >> 16)); // again, then complement
// calculate IP checksum for DHCP request renew wire [31:0]DHCP_req_renew_checksum1; wire [31:0]DHCP_req_renew_checksum2; wire [15:0]DHCP_req_renew_checksum3;
assign DHCP_req_renew_checksum1 = 32'h00004500 + UDP_DHCP_req_renew_length + 32'h00008011 + This_IP[31:16] + This_IP[15:0] + DHCP_IP[31:16] + DHCP_IP[15:0]; assign DHCP_req_renew_checksum2 = ((DHCP_req_renew_checksum1 & 32'h0000FFFF) + (DHCP_req_renew_checksum1 >> 16)); // 1's complement add, shift the higher order bits and add assign DHCP_req_renew_checksum3 = ~((DHCP_req_renew_checksum2 & 32'h0000FFFF) + (DHCP_req_renew_checksum2 >> 16)); // again, then complement
always @ * case(rdaddress) //---------- UDP/IP packet -------- // Ethernet preamble 0 : pkt_data <= 8'h55; 1 : pkt_data <= 8'h55; 2 : pkt_data <= 8'h55; 3 : pkt_data <= 8'h55; 4 : pkt_data <= 8'h55; 5 : pkt_data <= 8'h55; 6 : pkt_data <= 8'h55; 7 : pkt_data <= 8'hD5; // Ethernet header 8 : pkt_data <= PC_MAC[47:40]; 9 : pkt_data <= PC_MAC[39:32]; 10: pkt_data <= PC_MAC[31:24]; 11: pkt_data <= PC_MAC[23:16]; 12: pkt_data <= PC_MAC[15:8]; 13: pkt_data <= PC_MAC[7:0]; 14: pkt_data <= This_MAC[47:40]; 15: pkt_data <= This_MAC[39:32]; 16: pkt_data <= This_MAC[31:24]; 17: pkt_data <= This_MAC[23:16]; 18: pkt_data <= This_MAC[15:8]; 19: pkt_data <= This_MAC[7:0]; 20: pkt_data <= 8'h08; 21: pkt_data <= 8'h00; // IP header 22: pkt_data <= 8'h45; // Version 23: pkt_data <= 8'h00; // Type of service 24: pkt_data <= 8'h04; // length ***** CHANGE CHECKSUM IF LENGTH CHANGES *****
вырезал кусок ....
858: pkt_data <= 8'h00; 859: pkt_data <= 8'h00; default: pkt_data <= 0; endcase
// to calculate length; 8 + (end - DHCP_start + 1) + nulls + 202
assign DHCP_length = 16'd8 + (16'd367 - 16'd350 + 16'd1) + 16'd24 + 16'd202; // 8 + 244 assign UDP_DHCP_length = DHCP_length + 16'd20;
assign DHCP_req_length = 16'd8 + (16'd479 - 16'd450 + 16'd1) + 16'd24 + 16'd202; // 8 + 256 assign UDP_DHCP_req_length = DHCP_req_length + 16'd20;
assign DHCP_req_renew_length = 16'd8 + (16'd779 - 16'd750 + 16'd1) + 16'd12 + 16'd202; // 8 + 244 assign UDP_DHCP_req_renew_length = DHCP_req_renew_length + 16'd20;
always @ (negedge Tx_clock_2 or posedge Reset) // clock at half speed since we read bytes but write nibbles begin if (Reset) begin state_Tx <= RESET; end else begin case(state_Tx)
RESET: begin LED <= 1'b0; sync_Tx_CTL <= 1'b0; data_count <= 0; reset_CRC <= 0; rdaddress <= 0; ARP_sent <= 0; ping_sent <= 0; ping_check_temp <= 0; // reset ping check sum calculation ck_count <= 0; zero_count <= 0; DHCP_discover_sent <= 0; DHCP_request_sent <= 0; METIS_discover_sent <= 0; DHCP_request_renew_sent <= 0; interframe <= 0; erase_done_ACK <= 0; send_more_ACK <= 0; IP_count <= 0; if (IF_rst) state_Tx <= RESET; else begin if (run == 1'b0) begin sequence_number <= 0; // reset sequence numbers when not running. spec_seq_number <= 0; end //--------
if (Send_ARP) begin // Pending ARP request rdaddress <= 100; // point to start of ARP table state_Tx <= ARP; end else if (ping_reply)begin rdaddress <= 200; // point to ping checksum code state_Tx <= PING1; end
else if (send_pll_data) begin rdaddress <= 0; state_Tx <= PLL_DATA; end
else state_Tx <= RESET; end end
// start sending UDP/IP data UDP: begin end_point <= 8'h06; // USB I&Q equivalent end point - EP6 if (rdaddress != 58) // keep sending until we reach the end of the fixed data begin Tx_data <= pkt_data; sync_Tx_CTL <= 1'b1; // enable write to PHY rdaddress <= rdaddress + 1'd1; state_Tx <= UDP; end else // read the Tx fifo data begin if (data_count < 1024) begin Tx_data <= PHY_Tx_data; data_count <= data_count + 1'd1; // increment loop counter state_Tx <= UDP; end else begin temp_CRC32 <= CRC32; // grab the CRC data since it will change next clock pulse Tx_data <= CRC32[7:0]; // send CRC32 to PHY rdaddress <= 58; // point to end of CRC table sequence_number <= sequence_number + 1'b1; // increment sequence number state_Tx <= CRC; end end // done, so now add the remainder of the CRC32 if (rdaddress == 57) Tx_fifo_rdreq <= 1'b1; // enable read from Tx_fifo on next clock if (data_count == 1023) Tx_fifo_rdreq <= 1'b0; // stop reading from Tx_fifo if (rdaddress == 7) reset_CRC <= 1'b1; // start CRC32 generation else reset_CRC <= 1'b0; end
// respond to pending ARP request, just read straight through the table ARP: begin if (rdaddress != 150) begin sync_Tx_CTL <= 1'b1; // enable write to PHY Tx_data <= pkt_data; rdaddress <= rdaddress + 1'd1; state_Tx <= ARP; end else if (zero_count < 18)begin // send 18 x 0x00s Tx_data <= 8'h00; zero_count <= zero_count + 1'b1; state_Tx <= ARP; end else begin ARP_sent <= 1'b1; // set APR sent flag temp_CRC32 <= CRC32; // grab the CRC data since it will change next clock pulse Tx_data <= CRC32[7:0]; // send CRC32 to PHY rdaddress <= 58; // point to end of CRC table state_Tx <= CRC; end if (rdaddress == 107) reset_CRC <= 1'b1; // start CRC32 generation else reset_CRC <= 1'b0; end
// Calculate ping checksum. Ping data is in bytes, convert to 16 bits then // sum, apply one's complement then complement PING1: begin if (ck_count != (Length - 24)) begin // add all the ping data as 16 bits, ping_check_temp <= ping_check_temp + {16'b0,ping_data[ck_count], ping_data[ck_count + 1]}; ck_count <= ck_count + 8'd2; // get next two bytes state_Tx <= PING1; end else if (ping_check_temp >> 16 != 0) begin // do one's complement ping_check_temp <= ((ping_check_temp & 32'h0000FFFF) + (ping_check_temp >> 16)); state_Tx <= PING1; end else begin // complement and move to next state ping_check_sum <= ~ping_check_temp[15:0]; state_Tx <= PING2; end end // respond to ping PING2: begin if (rdaddress != 246) // keep sending until we reach the end of the fixed data begin Tx_data <= pkt_data; sync_Tx_CTL <= 1'b1; // enable write to PHY rdaddress <= rdaddress + 1'b1; state_Tx <= PING2; end else if (data_count < (Length - 24)) begin // send contents of ping_data in bytes Tx_data <= ping_data[data_count]; data_count <= data_count + 1'd1; // increment loop counter state_Tx <= PING2; end else begin ping_sent <= 1'b1; // set ping sent flag temp_CRC32 <= CRC32; // grab the CRC data since it will change next clock pulse Tx_data <= CRC32[7:0]; // send CRC32 to PHY rdaddress <= 58; // point to end of CRC table state_Tx <= CRC; end if (rdaddress == 207) reset_CRC <= 1'b1; // start CRC32 generation else reset_CRC <= 1'b0; end // send raw data PLL_DATA: begin if (rdaddress != 58) // keep sending until we reach the end of the fixed data begin // but skip sequence number Tx_data <= pkt_data; sync_Tx_CTL <= 1'b1; // enable write to PHY rdaddress <= rdaddress + 1'd1; state_Tx <= PLL_DATA; end else // read the Tx fifo data begin if (sp_data_count == 0) begin // Первым должны передать код команды Tx_data <= 8'h80; // Код 0x80 - пакет состояния PLL sp_data_count <= sp_data_count + 1'b1; // increment loop counter state_Tx <= PLL_DATA; end else if (sp_data_count <=33) begin // отправляем массив данных Tx_data <= pll_data[sp_data_count-1]; sp_data_count <= sp_data_count + 1'b1; // increment loop counter state_Tx <= PLL_DATA; end else if (sp_data_count != 1024) begin // заполняем оставшееся место Tx_data <= 8'h55; sp_data_count <= sp_data_count + 1'b1; // increment loop counter state_Tx <= PLL_DATA; end else begin sp_data_count <= 0; // reset data counter for next time temp_CRC32 <= CRC32; // grab the CRC data since it will change next clock pulse Tx_data <= CRC32[7:0]; // send CRC32 to PHY rdaddress <= 58; // point to end of CRC table sequence_number <= sequence_number + 1'b1; // increment sequence number state_Tx <= CRC; end end // done, so now add the remainder of the CRC32 if (rdaddress == 7) reset_CRC <= 1'b1; // start CRC32 generation else reset_CRC <= 1'b0; end // add remainder of CRC32 CRC: begin if (rdaddress != 61) begin Tx_data <= pkt_data; rdaddress <= rdaddress + 1'b1; state_Tx <= CRC; end else begin sync_Tx_CTL <= 1'b0; // disable PHY write if (interframe == 10) begin // delay between frames should be 960/96nS min state_Tx <= RESET; // send complete, loop back to start end else interframe <= interframe + 1'b1; end end
default: state_Tx <= RESET;
endcase end end
//------------------------------ // 802.3 CRC32 Calculation //-------------------------------
CRC32 CRC32_inst(.rst(reset_CRC),.clk(Tx_clock_2), .data(Tx_data), .crc(CRC32));
//----------------------------------------------------------- // Send data to PHY //-----------------------------------------------------------
// Data to send is in Tx_data in bytes. // For 100T, when sync_Tx_CTL is true we alternate sending low and high nibbles
always @ (negedge Tx_clock or posedge Reset) begin if (Reset) PHY_state <=0; else case (PHY_state) // send low nibble 0: begin if (sync_Tx_CTL) begin sync_TD <= Tx_data[3:0]; PHY_state <= 1'b1; end else PHY_state <= 0; end // now send high nibble 1: begin sync_TD <= Tx_data[7:4]; PHY_state <= 0; end
endcase end
// sync data to PHY on Tx clock, clock PHY on ~Tx_clock so we clock in middle of data
always @ (posedge Tx_clock) begin TD <= sync_TD; Tx_CTL <= sync_Tx_CTL; end
reg [3:0]TD; reg Tx_CTL;
endmodule
|
|
|
|
|
Mar 23 2015, 15:07
|
Знающий
   
Группа: Свой
Сообщений: 572
Регистрация: 17-11-05
Из: СПб, Россия
Пользователь №: 10 965

|
Цитата(Digi @ Mar 23 2015, 17:15)  Основная проблема в том что я не могу понять, почему state_Tx становиться равным НУЛЮ ? Подскажите, в какую сторону дальше грести. Асинхронщина какая-нибудь. Внутри замысловато перемежаются posedge и negedge двух клоков, причем один взят с триггера-делителя... Если тайминг аналайзер говорит, что все хорошо, то можно, конечно поверить, но я бы был начеку. Или сброс асинхронный приходит откуда-нибудь из логики не подсинхронизированный к клоку.
|
|
|
|
|
Mar 23 2015, 15:32
|
Гуру
     
Группа: Модераторы
Сообщений: 4 011
Регистрация: 8-09-05
Из: спб
Пользователь №: 8 369

|
Цитата(Digi @ Mar 23 2015, 17:15)  Вообще ужасает многоразрядность всего, чего только можно. А "равно 0" - из-за длинных цепей логики... Я вот для МАСа успевал считать CRC по-тетрадно при передаче и при приеме. Проверка адреса вообще делается на последовательном коде, тоже в темпе приема. На кой черт так загружать кристалл? Ведь пока один пакет передается, а это не менее 64 бита + пауза + преамбула - вот все это время можно потратить на обработку пакетов... Тетрадами, байтами, но никак не 32-х битовыми словами...
--------------------
www.iosifk.narod.ru
|
|
|
|
|
Mar 23 2015, 18:14
|
Частый гость
 
Группа: Свой
Сообщений: 150
Регистрация: 20-08-04
Пользователь №: 529

|
К своему стыду, признаюсь, в данном проекте с констрейнами у меня полный ступор. Я и до этого с ними не дружил, в силу неполного понимания процесса их описания. Может направите меня в более менее доступное разъяснение, как с ними работать. По поводу кривизны проекта: за основу был взят опенсорсный проект, я его модифицировал до нужного мне функционала. Torpeda, из CLOCK*_50 - используется только CLOCK_50, остальные я ухитрился автоматом прописать. PHY_RX_CLOCK и PHY_TX_CLOCK - в принципе друг с другом синхронны, но сдвинуты по фазе, так как берутся с разных источников (выходов PHY). bogaev_roman, time quest ничего разумного не скажет, потому что констрейны прописаны криво. Цитата Асинхронщина какая-нибудь. Внутри замысловато перемежаются posedge и negedge двух клоков, причем один взят с триггера-делителя... Если тайминг аналайзер говорит, что все хорошо, то можно, конечно поверить, но я бы был начеку. Или сброс асинхронный приходит откуда-нибудь из логики не подсинхронизированный к клоку. alexadmin, сброс в процессе работы не приходит. Но почему машина состояний вываливается и не отрабатывается default ?
|
|
|
|
|
Mar 24 2015, 07:48
|
Профессионал
    
Группа: Свой
Сообщений: 1 088
Регистрация: 20-10-09
Из: Химки
Пользователь №: 53 082

|
Цитата(Digi @ Mar 23 2015, 21:14)  time quest ничего разумного не скажет, потому что констрейны прописаны криво. timequest, как минимум, скажет какие клоки Вы обконстрейнили зря, какие по его мнению сигналы являются клоками и на них не заданы временные ограничения и, если есть правильно заданные ограничения - есть ли временные ошибки по ним. По поводу как правильно работать с timequest у des00 очень хорошо описано в статьях, например, здесь http://embedders.org/category/tags/timequest
|
|
|
|
|
Mar 24 2015, 10:02
|
Частый гость
 
Группа: Свой
Сообщений: 150
Регистрация: 20-08-04
Пользователь №: 529

|
Добавил вот такую конструкцию. Из нее видно, что машина находится в состоянии PLL_DATA, но в самой машине в секции PLL_DATA ничего не выполняется. Пошел разбираться с временным анализом. Код always @ (negedge Tx_clock_2 ) begin case (state_Tx)
RESET: begin tx_debug[3:0] = 1; end UDP: begin tx_debug[3:0] = 2; end ARP: begin tx_debug[3:0] = 3; end PING1: begin tx_debug[3:0] = 4; end
PING2: begin tx_debug[3:0] = 5; end
CRC: begin tx_debug[3:0] = 6; end
PLL_DATA: begin tx_debug[3:0] = 7; end default: begin tx_debug[3:0] = 8; end endcase
end Проблема скрывалась в многочисленных проверках sp_data_count в состоянии PLL_DATA. Изменил конструкцию и все заработало.
|
|
|
|
|
Apr 13 2015, 12:35
|
Участник

Группа: Участник
Сообщений: 29
Регистрация: 30-01-07
Из: Петербург
Пользователь №: 24 875

|
Цитата(Digi @ Mar 23 2015, 17:15)  ... Запускаю, некоторое время все работает, но по непонятным причинам, через несколько сотен посылок, код перестает работать. Конкретно проблема возникает в том что машина состояний state_Tx уходит в неопределенное состояние, обычно это происходит из-за того, что одно из воздействий на машину асинхронно. Ищите воздействие и синхронизируйте... например Send_ARP, ping_reply, send_pll_data - первое что приходит в голову.
Сообщение отредактировал D Mike - Apr 13 2015, 12:42
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|