zynq-sandbox

old FPGA projects for ZYNQ
git clone http://frotz.net/git/zynq-sandbox.git
Log | Files | Refs | README

eth_capture.sv (5036B)


      1 // Copyright 2014 Brian Swetland <swetland@frotz.net>
      2 //
      3 // Licensed under the Apache License, Version 2.0 (the "License");
      4 // you may not use this file except in compliance with the License.
      5 // You may obtain a copy of the License at
      6 //
      7 //     http://www.apache.org/licenses/LICENSE-2.0
      8 //
      9 // Unless required by applicable law or agreed to in writing, software
     10 // distributed under the License is distributed on an "AS IS" BASIS,
     11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     12 // See the License for the specific language governing permissions and
     13 // limitations under the License.
     14 
     15 `timescale 1ns / 1ps
     16 
     17 module eth_capture(
     18 	// interface from eth_rmii_rx 
     19 	input clk50,
     20 	input rxsop,
     21 	input rxeop,
     22 	input [7:0]rxdata,
     23 	input rxvalid,
     24 
     25 	// interface to axi
     26 	input clk,
     27 	input reset,
     28 	input enable,
     29 	axi_ifc.master axi_dma
     30 	);
     31 
     32 parameter BASE_ADDR = 32'h10000000;
     33 
     34 wire active;
     35 sync_oneway sync_enable(
     36 	.txclk(clk),
     37 	.txdat(enable),
     38 	.rxclk(clk50),
     39 	.rxdat(active)
     40 	);
     41 
     42 wire [31:0]w_data;
     43 wire w_valid;
     44 wire w_eop;
     45 wire [11:0]bytecount;
     46 
     47 reg [63:0]clk50_count = 0;
     48 reg [63:0]rxtimestamp = 0;
     49 always @(posedge clk50) begin
     50 	clk50_count <= clk50_count + 1;
     51 	if (rxsop) begin
     52 		rxtimestamp <= clk50_count;
     53 	end
     54 end
     55 
     56 pkt_bytes_to_words cap0(
     57 	.clk(clk50),
     58 	.rxdata(rxdata),
     59 	.rxvalid(rxvalid & active),
     60 	.rxeop(rxeop & active),
     61 	.data(w_data),
     62 	.bytecount(bytecount),
     63 	.eop(w_eop),
     64 	.valid(w_valid)
     65 	);
     66 
     67 typedef enum { DATA, EOP0, EOP1, EOP2 } state_t;
     68 state_t state = DATA;
     69 state_t next_state;
     70 
     71 reg [20:0]cfifo_in = 0;
     72 reg [31:0]dfifo_in = 0;
     73 reg [20:0]next_cfifo_in;
     74 reg [31:0]next_dfifo_in;
     75 reg cfifo_wr = 0;
     76 reg dfifo_wr = 0;
     77 reg next_cfifo_wr;
     78 reg next_dfifo_wr;
     79 reg [3:0]dcount = 15;
     80 reg [3:0]next_dcount;
     81 
     82 // ADDR: window(10) packet(10) chunk(6) off(6)
     83 reg [9:0]dbase = 0;
     84 reg [9:0]next_dbase;
     85 reg [5:0]daddr = 1;
     86 reg [5:0]next_daddr;
     87 
     88 wire [3:0]dcount_plus_one = (dcount + 1);
     89 
     90 always_comb begin
     91 	next_state = state;
     92 	next_dcount = dcount;
     93 	next_daddr = daddr;
     94 	next_dbase = dbase;
     95 	next_cfifo_in = cfifo_in;
     96 	next_dfifo_in = dfifo_in;
     97 	next_cfifo_wr = 0;
     98 	next_dfifo_wr = 0;
     99 	case (state)
    100 	DATA: begin
    101 		if (w_valid) begin
    102 			next_dcount = dcount_plus_one;
    103 			next_dfifo_in = w_data;
    104 			next_dfifo_wr = 1;
    105 			if (dcount_plus_one == 15) begin
    106 				next_cfifo_in = { 1'b0, 4'd15, dbase, daddr };
    107 				next_cfifo_wr = 1;
    108 				next_daddr = daddr + 1;
    109 			end
    110 		end else if (w_eop) begin
    111 			next_state = EOP0;
    112 			next_dfifo_in = rxtimestamp[31:0];
    113 			next_dfifo_wr = 1;
    114 			if (dcount != 15) begin
    115 				next_cfifo_in = { 1'b0, dcount, dbase, daddr };
    116 				next_cfifo_wr = 1;
    117 			end
    118 		end
    119 	end
    120 	EOP0: begin
    121 		next_state = EOP1;
    122 		next_dfifo_in = rxtimestamp[63:32];
    123 		next_dfifo_wr = 1;
    124 	end
    125 	EOP1: begin
    126 		next_state = EOP2;
    127 		next_dfifo_in = { 20'h00000, bytecount };
    128 		next_dfifo_wr = 1;
    129 	end
    130 	EOP2: begin
    131 		next_state = DATA;
    132 		next_dcount = 15;
    133 		next_daddr = 1;
    134 		next_dbase = dbase + 1;
    135 		next_dfifo_in = 32'h00000001; // status
    136 		next_dfifo_wr = 1;
    137 		next_cfifo_in = { 1'b1, 4'd3, dbase, 6'd0 };
    138 		next_cfifo_wr = 1;
    139 	end
    140 	endcase
    141 end
    142 
    143 always_ff @(posedge clk50) begin
    144 	state <= next_state;
    145 	dcount <= next_dcount;
    146 	daddr <= next_daddr;
    147 	dbase <= next_dbase;
    148 	cfifo_in <= next_cfifo_in;
    149 	dfifo_in <= next_dfifo_in;
    150 	cfifo_wr <= next_cfifo_wr;
    151 	dfifo_wr <= next_dfifo_wr;
    152 end
    153 
    154 reg fifo_reset = 0;
    155 
    156 wire [31:0]dfifo_data;
    157 wire dfifo_rd;
    158 wire dfifo_empty;
    159 wire dfifo_active;
    160 
    161 wire [20:0]cfifo_data;
    162 reg cfifo_rd = 0;
    163 wire cfifo_empty;
    164 wire cfifo_active;
    165 
    166 // on reset request, assert fifo_reset until both fifos
    167 // have started the sequence (fifo_active=0)
    168 always @(posedge clk) begin
    169 	if (dfifo_active & cfifo_active) begin
    170 		if (reset) begin
    171 			fifo_reset <= 1;
    172 		end
    173 	end else if (~dfifo_active & ~cfifo_active) begin
    174 		fifo_reset <= 0;
    175 	end
    176 end
    177 
    178 // CMD:   wrstatus wrdata count(12)
    179 xilinx_async_fifo #(
    180 	.WIDTH(32)
    181 	) dfifo (
    182 	.wrclk(clk50),
    183 	.rdclk(clk),
    184 	.reset(fifo_reset),
    185 	.wr_data(dfifo_in),
    186 	.wr_en(dfifo_wr),
    187 	.rd_en(dfifo_rd),
    188 	.rd_data(dfifo_data),
    189 	.o_empty(dfifo_empty),
    190 	.o_ready(),
    191 	.o_active(dfifo_active)
    192 	);
    193 
    194 // CMD: burst(4) addr(16)  -- addr is A[21:6]
    195 
    196 xilinx_async_fifo #(
    197 	.WIDTH(21)
    198 	) cfifo ( 
    199 	.wrclk(clk50),
    200 	.rdclk(clk),
    201 	.reset(fifo_reset),
    202 	.wr_data(cfifo_in),
    203 	.wr_en(cfifo_wr),
    204 	.rd_en(cfifo_rd),
    205 	.rd_data(cfifo_data),
    206 	.o_empty(cfifo_empty),
    207 	.o_ready(),
    208 	.o_active(cfifo_active)
    209 	);
    210 
    211 reg [31:0]dma_base = BASE_ADDR;
    212 
    213 // status writes are 4 words at byte offset 48
    214 // data writes are always at byte offset 0
    215 wire [5:0]dma_byte = cfifo_data[20] ? 6'd48 : 6'd0;
    216 
    217 wire [31:0]dma_addr = { dma_base[31:22], cfifo_data[15:0], dma_byte };
    218 wire [3:0]dma_len = cfifo_data[19:16];
    219 wire dma_start = (~cfifo_empty) & (~dma_busy);
    220 wire dma_busy;
    221 
    222 always @(posedge clk) begin
    223 	if (cfifo_active & dfifo_active) begin
    224 		if (dma_start) begin
    225 			cfifo_rd <= 1;
    226 		end else begin
    227 			cfifo_rd <= 0;
    228 		end
    229 	end
    230 end
    231 
    232 axi_dma_writer dma0(
    233 	.clk(clk),
    234 	.m(axi_dma),
    235 	.addr(dma_addr),
    236 	.burstlen(dma_len),
    237 	.start(dma_start),
    238 	.busy(dma_busy),
    239 	.data(dfifo_data),
    240 	.advance(dfifo_rd)
    241 	);
    242 
    243 endmodule