I am a beginner at Verilog and FPGA programming. My background is C/C++ software development.
I am developing a FPGA module which would basically read Ethernet network packets and then interact with a process running in software. As a start I wrote a packet snooper module, which would dump the next packet in its memory when a signal is enabled.
When I read the dumped packet using Avalon-MM interface with my module, the first 4 bytes seem to be corrupted. Further bytes are as expected.
In my test case, the first 4 bytes of dumped memory are always 0x76696365
I then modified my code to copy the first 4 bytes of the packet to a separate register. When I queried this register, I get the expected value, which is equal to 0xf531a in my test. But still, offset 0 of the packet dump memory is 0x76696365.
I am pasting the verilog code for your reference. Any suggestions on how to debug this issue?
module packet_snooper #(
parameter MAC_ERROR_WIDTH = 6,
parameter MAC_DATA_WIDTH = 32, // 32 or 64
parameter CSR_ADDRESS_BITS = 12,
parameter CSR_DATABUS_WIDTH = 32
) (
input mac_clk,
input app_clk,
input reset_n_mac,
input reset_n_app,
// Avalon-ST interface from the MAC (can be 32-bits at 312.5MHz or 64-bits at 156.25Mhz)
input stream_in_startofpacket,
input stream_in_endofpacket,
input stream_in_valid,
output stream_in_ready,
input [MAC_DATA_WIDTH-1:0] stream_in_data,
input [2-1:0] stream_in_empty,
input [MAC_ERROR_WIDTH-1:0] stream_in_error,
// out
output stream_out_startofpacket,
output stream_out_endofpacket,
output stream_out_valid,
input stream_out_ready,
output [MAC_DATA_WIDTH-1:0] stream_out_data,
output [2-1:0] stream_out_empty,
output [MAC_ERROR_WIDTH-1:0] stream_out_error,
// Avalon-MM bus
input [CSR_ADDRESS_BITS-1:0] avs_csr_address,
input avs_csr_read,
input avs_csr_write,
input [CSR_DATABUS_WIDTH-1:0] avs_csr_writedata,
output reg [CSR_DATABUS_WIDTH-1:0] avs_csr_readdata,
output avs_csr_waitrequest
);
parameter CSR_MODULE_ID = 32'h20001001;
parameter CSR_REG_LOAD_PACKET = 10'd1;
parameter CSR_REG_PACKET_LEN = 10'd2;
parameter CSR_REG_DEBUG = 10'd3;
parameter CSR_REG_DEBUG_NUM_SOP = 10'd4;
parameter CSR_REG_PKT_BUF_BASE = 10'd5;
parameter PKT_BUFFER_BYTES = 2048;
reg dump_next_packet;
reg [2:0] resync_dnp;
reg resync_dnp_rising_edge;
reg resync_dnp_rising_edge_hold;
reg dump_pkt;
wire valid_dump;
reg [3:0] debug_sop;
reg [3:0] debug_eop;
reg [3:0] debug_ready;
reg [3:0] debug_valid;
reg [3:0] debug_ready_valid;
wire [31:0] debug_register;
reg [31:0] sop;
reg [31:0] num_sop;
reg [MAC_DATA_WIDTH-1:0] pkt_buffer [9:0]; //((PKT_BUFFER_BYTES<<3)/MAC_DATA_WIDTH):0
reg [31:0] pkt_len;
//passthrough data
assign stream_out_startofpacket = stream_in_startofpacket;
assign stream_out_endofpacket = stream_in_endofpacket;
assign stream_out_valid = stream_in_valid;
assign stream_in_ready = stream_out_ready;
assign stream_out_data = stream_in_data;
assign stream_out_empty = stream_in_empty;
assign stream_out_error = stream_in_error;
assign avs_csr_waitrequest = 0;
assign debug_register = {12'h0, debug_ready_valid, debug_valid, debug_ready, debug_sop, debug_eop};
always @ (posedge mac_clk) begin //{
if(~reset_n_mac) begin
debug_ready <= 0;
debug_valid <= 0;
debug_ready_valid <= 0;
debug_sop <= 0;
debug_eop <= 0;
end
else begin
if (stream_out_ready)
debug_ready <= debug_ready + 1;
if (stream_in_valid)
debug_valid <= debug_valid + 1;
if (stream_in_valid && stream_out_ready)
debug_ready_valid <= debug_ready_valid + 1;
if (stream_in_valid && stream_in_startofpacket)
debug_sop <= debug_sop + 1;
if (stream_in_valid && stream_in_endofpacket)
debug_eop <= debug_eop + 1;
end
end //}
always @ (posedge mac_clk) begin //{
if(~reset_n_mac) begin
pkt_len <= 0;
num_sop <= 0;
end
else if(stream_in_valid && stream_out_ready) begin //{
if (valid_dump) begin //{
if (stream_in_startofpacket) begin
pkt_len <= 1;
pkt_buffer[0] <= stream_in_data;
sop <= stream_in_data;
num_sop <= num_sop + 1;
end
else begin
pkt_len <= pkt_len + 1;
pkt_buffer[pkt_len] <= stream_in_data; /* TODO: Handle stream_in_empty */
end
end //}
end //}
end //}
//read registers
always @ (posedge app_clk) begin //{
if (avs_csr_read) begin //{
case(avs_csr_address)
9'h0 : avs_csr_readdata <= CSR_MODULE_ID;
CSR_REG_LOAD_PACKET : avs_csr_readdata <= dump_next_packet;
CSR_REG_PACKET_LEN : avs_csr_readdata <= (pkt_len << $clog2(MAC_DATA_WIDTH/8));
CSR_REG_DEBUG : avs_csr_readdata <= sop;
CSR_REG_DEBUG_NUM_SOP: avs_csr_readdata <= num_sop;
default : //{
avs_csr_readdata <= pkt_buffer[avs_csr_address[9:0] - CSR_REG_PKT_BUF_BASE]; //TODO: handle 64-bit width
//}
endcase
end //}
end //}
// write reg
always @ (posedge app_clk) begin //{
if(~reset_n_app) begin //{
dump_next_packet <= 0;
end //}
else if(avs_csr_write) begin //{
case(avs_csr_address)
CSR_REG_LOAD_PACKET : dump_next_packet <= avs_csr_writedata;
endcase
end //}
end //}
/* Synchronize dump_next_packet with mac_clk */
always @(posedge mac_clk) begin //{
resync_dnp <= {dump_next_packet, resync_dnp[2:1]};
resync_dnp_rising_edge <= resync_dnp[1] & !resync_dnp[0];
end //}
/* Hold the edge till current packet dump is complete */
always @ (posedge mac_clk) begin //{
if(~reset_n_mac)
resync_dnp_rising_edge_hold <= 0;
else if(dump_pkt & stream_in_endofpacket & stream_in_valid)
resync_dnp_rising_edge_hold <= 0;
else if(resync_dnp_rising_edge)
resync_dnp_rising_edge_hold <= 1;
end //}
always @ (posedge mac_clk) begin //{
if(~reset_n_mac)
dump_pkt <= 0;
else if(dump_pkt & stream_in_endofpacket & stream_in_valid)
dump_pkt <= 0;
else if(resync_dnp_rising_edge_hold & stream_in_startofpacket & stream_in_valid)
dump_pkt <= 1;
end //}
assign valid_dump = stream_in_valid & (dump_pkt || (stream_in_startofpacket & resync_dnp_rising_edge_hold));
endmodule
Best Answer
multiple always blocks with different clocks creates problem sometimes, so avoid using multiple clocking signals in the same module and make separate module for different clocks as far as possible.hope your problem get solved..