diff --git a/addins/sparse-checkout b/addins/sparse-checkout index f1743725c..74cc3f25a 100644 --- a/addins/sparse-checkout +++ b/addins/sparse-checkout @@ -2,6 +2,7 @@ rtl/eth_mac_mii_fifo.sv rtl/eth_mac_mii.sv rtl/mii_phy_if.sv rtl/ssio_ddr_in.sv +rtl/ssio_sdr_in.sv rtl/eth_mac_1g.sv rtl/axis_gmii_rx.sv rtl/lfsr.sv diff --git a/addins/verilog-ethernet b/addins/verilog-ethernet index 13c33ff1a..43990ab4f 160000 --- a/addins/verilog-ethernet +++ b/addins/verilog-ethernet @@ -1 +1 @@ -Subproject commit 13c33ff1a82348691a40d78cf2bab10cbf4f76b2 +Subproject commit 43990ab4fd0c8d34dbc1be5cd8d4f3ed3e33f853 diff --git a/fpga/constraints/small-debug.xdc b/fpga/constraints/small-debug.xdc index 10d64c126..ce824620b 100644 --- a/fpga/constraints/small-debug.xdc +++ b/fpga/constraints/small-debug.xdc @@ -32,30 +32,25 @@ set_property PROBE_TYPE DATA_AND_TRIGGER [get_debug_ports u_ila_0/probe2] connect_debug_port u_ila_0/probe2 [get_nets [list wallypipelinedsoc/core/InstrValidM ]] create_debug_port u_ila_0 probe -set_property port_width 4 [get_debug_ports u_ila_0/probe3] +set_property port_width 1 [get_debug_ports u_ila_0/probe3] set_property PROBE_TYPE DATA_AND_TRIGGER [get_debug_ports u_ila_0/probe3] -connect_debug_port u_ila_0/probe3 [get_nets [list {ethernet/eth_mac_1g_mii_inst/mii_phy_if_inst/mac_mii_txd[0]} {ethernet/eth_mac_1g_mii_inst/mii_phy_if_inst/mac_mii_txd[1]} {ethernet/eth_mac_1g_mii_inst/mii_phy_if_inst/mac_mii_txd[2]} {ethernet/eth_mac_1g_mii_inst/mii_phy_if_inst/mac_mii_txd[3]} ]] +connect_debug_port u_ila_0/probe3 [get_nets [list {RvviAxiRlast}]] create_debug_port u_ila_0 probe -set_property port_width 4 [get_debug_ports u_ila_0/probe4] +set_property port_width 1 [get_debug_ports u_ila_0/probe4] set_property PROBE_TYPE DATA_AND_TRIGGER [get_debug_ports u_ila_0/probe4] -connect_debug_port u_ila_0/probe4 [get_nets [list {packetizer/CurrState[0]} {packetizer/CurrState[1]} {packetizer/CurrState[2]} {packetizer/CurrState[3]}]] +connect_debug_port u_ila_0/probe4 [get_nets [list {RvviAxiRvalid}]] create_debug_port u_ila_0 probe -set_property port_width 1 [get_debug_ports u_ila_0/probe5] +set_property port_width 4 [get_debug_ports u_ila_0/probe5] set_property PROBE_TYPE DATA_AND_TRIGGER [get_debug_ports u_ila_0/probe5] -connect_debug_port u_ila_0/probe5 [get_nets [list {ethernet/eth_mac_1g_mii_inst/mii_phy_if_inst/mac_mii_tx_en} ]] +connect_debug_port u_ila_0/probe5 [get_nets [list {packetizer/CurrState[0]} {packetizer/CurrState[1]} {packetizer/CurrState[2]} {packetizer/CurrState[3]}]] create_debug_port u_ila_0 probe set_property port_width 64 [get_debug_ports u_ila_0/probe6] set_property PROBE_TYPE DATA_AND_TRIGGER [get_debug_ports u_ila_0/probe6] connect_debug_port u_ila_0/probe6 [get_nets [list {wallypipelinedsoc/core/PCM[0]} {wallypipelinedsoc/core/PCM[1]} {wallypipelinedsoc/core/PCM[2]} {wallypipelinedsoc/core/PCM[3]} {wallypipelinedsoc/core/PCM[4]} {wallypipelinedsoc/core/PCM[5]} {wallypipelinedsoc/core/PCM[6]} {wallypipelinedsoc/core/PCM[7]} {wallypipelinedsoc/core/PCM[8]} {wallypipelinedsoc/core/PCM[9]} {wallypipelinedsoc/core/PCM[10]} {wallypipelinedsoc/core/PCM[11]} {wallypipelinedsoc/core/PCM[12]} {wallypipelinedsoc/core/PCM[13]} {wallypipelinedsoc/core/PCM[14]} {wallypipelinedsoc/core/PCM[15]} {wallypipelinedsoc/core/PCM[16]} {wallypipelinedsoc/core/PCM[17]} {wallypipelinedsoc/core/PCM[18]} {wallypipelinedsoc/core/PCM[19]} {wallypipelinedsoc/core/PCM[20]} {wallypipelinedsoc/core/PCM[21]} {wallypipelinedsoc/core/PCM[22]} {wallypipelinedsoc/core/PCM[23]} {wallypipelinedsoc/core/PCM[24]} {wallypipelinedsoc/core/PCM[25]} {wallypipelinedsoc/core/PCM[26]} {wallypipelinedsoc/core/PCM[27]} {wallypipelinedsoc/core/PCM[28]} {wallypipelinedsoc/core/PCM[29]} {wallypipelinedsoc/core/PCM[30]} {wallypipelinedsoc/core/PCM[31]} {wallypipelinedsoc/core/PCM[32]} {wallypipelinedsoc/core/PCM[33]} {wallypipelinedsoc/core/PCM[34]} {wallypipelinedsoc/core/PCM[35]} {wallypipelinedsoc/core/PCM[36]} {wallypipelinedsoc/core/PCM[37]} {wallypipelinedsoc/core/PCM[38]} {wallypipelinedsoc/core/PCM[39]} {wallypipelinedsoc/core/PCM[40]} {wallypipelinedsoc/core/PCM[41]} {wallypipelinedsoc/core/PCM[42]} {wallypipelinedsoc/core/PCM[43]} {wallypipelinedsoc/core/PCM[44]} {wallypipelinedsoc/core/PCM[45]} {wallypipelinedsoc/core/PCM[46]} {wallypipelinedsoc/core/PCM[47]} {wallypipelinedsoc/core/PCM[48]} {wallypipelinedsoc/core/PCM[49]} {wallypipelinedsoc/core/PCM[50]} {wallypipelinedsoc/core/PCM[51]} {wallypipelinedsoc/core/PCM[52]} {wallypipelinedsoc/core/PCM[53]} {wallypipelinedsoc/core/PCM[54]} {wallypipelinedsoc/core/PCM[55]} {wallypipelinedsoc/core/PCM[56]} {wallypipelinedsoc/core/PCM[57]} {wallypipelinedsoc/core/PCM[58]} {wallypipelinedsoc/core/PCM[59]} {wallypipelinedsoc/core/PCM[60]} {wallypipelinedsoc/core/PCM[61]} {wallypipelinedsoc/core/PCM[62]} {wallypipelinedsoc/core/PCM[63]} ]] -#create_debug_port u_ila_0 probe -#set_property port_width 1 [get_debug_ports u_ila_0/probe7] -#set_property PROBE_TYPE DATA_AND_TRIGGER [get_debug_ports u_ila_0/probe7] -#connect_debug_port u_ila_0/probe7 [get_nets [list {IlaTrigger} ]] - create_debug_port u_ila_0 probe set_property port_width 1 [get_debug_ports u_ila_0/probe7] set_property PROBE_TYPE DATA_AND_TRIGGER [get_debug_ports u_ila_0/probe7] @@ -81,16 +76,6 @@ set_property port_width 3 [get_debug_ports u_ila_0/probe11] set_property PROBE_TYPE DATA_AND_TRIGGER [get_debug_ports u_ila_0/probe11] connect_debug_port u_ila_0/probe11 [get_nets [list {triggergen/CurrState[0]} {triggergen/CurrState[1]} {triggergen/CurrState[2]}]] -create_debug_port u_ila_0 probe -set_property port_width 1 [get_debug_ports u_ila_0/probe12] -set_property PROBE_TYPE DATA_AND_TRIGGER [get_debug_ports u_ila_0/probe12] -connect_debug_port u_ila_0/probe12 [get_nets [list {RvviAxiRlast}]] - -create_debug_port u_ila_0 probe -set_property port_width 1 [get_debug_ports u_ila_0/probe13] -set_property PROBE_TYPE DATA_AND_TRIGGER [get_debug_ports u_ila_0/probe13] -connect_debug_port u_ila_0/probe13 [get_nets [list {RvviAxiRvalid}]] - # the debug hub has issues with the clocks from the mmcm so lets give up an connect to the 100Mhz input clock. #connect_debug_port dbg_hub/clk [get_nets default_100mhz_clk] diff --git a/fpga/generator/Makefile b/fpga/generator/Makefile index df4ed0e2a..c23e22ee0 100644 --- a/fpga/generator/Makefile +++ b/fpga/generator/Makefile @@ -51,6 +51,8 @@ PreProcessFiles: $(MAKE) -C ../../sim deriv rm -rf ../src/CopiedFiles_do_not_add_to_repo/ cp -r ../../src/ ../src/CopiedFiles_do_not_add_to_repo/ + cp -r ../../addins/verilog-ethernet/*/*.sv ../src/CopiedFiles_do_not_add_to_repo/rvvi + cp -r ../../addins/verilog-ethernet/*/*/*/*.sv ../src/CopiedFiles_do_not_add_to_repo/rvvi mkdir ../src/CopiedFiles_do_not_add_to_repo/config/ cp ../../config/deriv/fpga/config.vh ../src/CopiedFiles_do_not_add_to_repo/config/ ./insert_debug_comment.sh diff --git a/src/rvvi/axis_adapter.sv b/src/rvvi/axis_adapter.sv deleted file mode 100644 index 8807a03b7..000000000 --- a/src/rvvi/axis_adapter.sv +++ /dev/null @@ -1,324 +0,0 @@ -/* - -Copyright (c) 2014-2023 Alex Forencich - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - -*/ - -// Language: Verilog 2001 - -`resetall -`default_nettype none - -/* - * AXI4-Stream bus width adapter - */ -module axis_adapter # -( - // Width of input AXI stream interface in bits - parameter S_DATA_WIDTH = 8, - // Propagate tkeep signal on input interface - // If disabled, tkeep assumed to be 1'b1 - parameter S_KEEP_ENABLE = (S_DATA_WIDTH>8), - // tkeep signal width (words per cycle) on input interface - parameter S_KEEP_WIDTH = ((S_DATA_WIDTH+7)/8), - // Width of output AXI stream interface in bits - parameter M_DATA_WIDTH = 8, - // Propagate tkeep signal on output interface - // If disabled, tkeep assumed to be 1'b1 - parameter M_KEEP_ENABLE = (M_DATA_WIDTH>8), - // tkeep signal width (words per cycle) on output interface - parameter M_KEEP_WIDTH = ((M_DATA_WIDTH+7)/8), - // Propagate tid signal - parameter ID_ENABLE = 0, - // tid signal width - parameter ID_WIDTH = 8, - // Propagate tdest signal - parameter DEST_ENABLE = 0, - // tdest signal width - parameter DEST_WIDTH = 8, - // Propagate tuser signal - parameter USER_ENABLE = 1, - // tuser signal width - parameter USER_WIDTH = 1 -) -( - input wire clk, - input wire rst, - - /* - * AXI input - */ - input wire [S_DATA_WIDTH-1:0] s_axis_tdata, - input wire [S_KEEP_WIDTH-1:0] s_axis_tkeep, - input wire s_axis_tvalid, - output wire s_axis_tready, - input wire s_axis_tlast, - input wire [ID_WIDTH-1:0] s_axis_tid, - input wire [DEST_WIDTH-1:0] s_axis_tdest, - input wire [USER_WIDTH-1:0] s_axis_tuser, - - /* - * AXI output - */ - output wire [M_DATA_WIDTH-1:0] m_axis_tdata, - output wire [M_KEEP_WIDTH-1:0] m_axis_tkeep, - output wire m_axis_tvalid, - input wire m_axis_tready, - output wire m_axis_tlast, - output wire [ID_WIDTH-1:0] m_axis_tid, - output wire [DEST_WIDTH-1:0] m_axis_tdest, - output wire [USER_WIDTH-1:0] m_axis_tuser -); - -// force keep width to 1 when disabled -localparam S_BYTE_LANES = S_KEEP_ENABLE ? S_KEEP_WIDTH : 1; -localparam M_BYTE_LANES = M_KEEP_ENABLE ? M_KEEP_WIDTH : 1; - -// bus byte sizes (must be identical) -localparam S_BYTE_SIZE = S_DATA_WIDTH / S_BYTE_LANES; -localparam M_BYTE_SIZE = M_DATA_WIDTH / M_BYTE_LANES; - -// bus width assertions -initial begin - if (S_BYTE_SIZE * S_BYTE_LANES != S_DATA_WIDTH) begin - $error("Error: input data width not evenly divisible (instance %m)"); - $finish; - end - - if (M_BYTE_SIZE * M_BYTE_LANES != M_DATA_WIDTH) begin - $error("Error: output data width not evenly divisible (instance %m)"); - $finish; - end - - if (S_BYTE_SIZE != M_BYTE_SIZE) begin - $error("Error: byte size mismatch (instance %m)"); - $finish; - end -end - -generate - -if (M_BYTE_LANES == S_BYTE_LANES) begin : bypass - // same width; bypass - - assign s_axis_tready = m_axis_tready; - - assign m_axis_tdata = s_axis_tdata; - assign m_axis_tkeep = M_KEEP_ENABLE ? s_axis_tkeep : {M_KEEP_WIDTH{1'b1}}; - assign m_axis_tvalid = s_axis_tvalid; - assign m_axis_tlast = s_axis_tlast; - assign m_axis_tid = ID_ENABLE ? s_axis_tid : {ID_WIDTH{1'b0}}; - assign m_axis_tdest = DEST_ENABLE ? s_axis_tdest : {DEST_WIDTH{1'b0}}; - assign m_axis_tuser = USER_ENABLE ? s_axis_tuser : {USER_WIDTH{1'b0}}; - -end else if (M_BYTE_LANES > S_BYTE_LANES) begin : upsize - // output is wider; upsize - - // required number of segments in wider bus - localparam SEG_COUNT = M_BYTE_LANES / S_BYTE_LANES; - // data width and keep width per segment - localparam SEG_DATA_WIDTH = M_DATA_WIDTH / SEG_COUNT; - localparam SEG_KEEP_WIDTH = M_BYTE_LANES / SEG_COUNT; - - reg [$clog2(SEG_COUNT)-1:0] seg_reg = 0; - - reg [S_DATA_WIDTH-1:0] s_axis_tdata_reg = {S_DATA_WIDTH{1'b0}}; - reg [S_KEEP_WIDTH-1:0] s_axis_tkeep_reg = {S_KEEP_WIDTH{1'b0}}; - reg s_axis_tvalid_reg = 1'b0; - reg s_axis_tlast_reg = 1'b0; - reg [ID_WIDTH-1:0] s_axis_tid_reg = {ID_WIDTH{1'b0}}; - reg [DEST_WIDTH-1:0] s_axis_tdest_reg = {DEST_WIDTH{1'b0}}; - reg [USER_WIDTH-1:0] s_axis_tuser_reg = {USER_WIDTH{1'b0}}; - - reg [M_DATA_WIDTH-1:0] m_axis_tdata_reg = {M_DATA_WIDTH{1'b0}}; - reg [M_KEEP_WIDTH-1:0] m_axis_tkeep_reg = {M_KEEP_WIDTH{1'b0}}; - reg m_axis_tvalid_reg = 1'b0; - reg m_axis_tlast_reg = 1'b0; - reg [ID_WIDTH-1:0] m_axis_tid_reg = {ID_WIDTH{1'b0}}; - reg [DEST_WIDTH-1:0] m_axis_tdest_reg = {DEST_WIDTH{1'b0}}; - reg [USER_WIDTH-1:0] m_axis_tuser_reg = {USER_WIDTH{1'b0}}; - - assign s_axis_tready = !s_axis_tvalid_reg; - - assign m_axis_tdata = m_axis_tdata_reg; - assign m_axis_tkeep = M_KEEP_ENABLE ? m_axis_tkeep_reg : {M_KEEP_WIDTH{1'b1}}; - assign m_axis_tvalid = m_axis_tvalid_reg; - assign m_axis_tlast = m_axis_tlast_reg; - assign m_axis_tid = ID_ENABLE ? m_axis_tid_reg : {ID_WIDTH{1'b0}}; - assign m_axis_tdest = DEST_ENABLE ? m_axis_tdest_reg : {DEST_WIDTH{1'b0}}; - assign m_axis_tuser = USER_ENABLE ? m_axis_tuser_reg : {USER_WIDTH{1'b0}}; - - always @(posedge clk) begin - m_axis_tvalid_reg <= m_axis_tvalid_reg && !m_axis_tready; - - if (!m_axis_tvalid_reg || m_axis_tready) begin - // output register empty - - if (seg_reg == 0) begin - m_axis_tdata_reg[seg_reg*SEG_DATA_WIDTH +: SEG_DATA_WIDTH] <= s_axis_tvalid_reg ? s_axis_tdata_reg : s_axis_tdata; - m_axis_tkeep_reg <= s_axis_tvalid_reg ? s_axis_tkeep_reg : s_axis_tkeep; - end else begin - m_axis_tdata_reg[seg_reg*SEG_DATA_WIDTH +: SEG_DATA_WIDTH] <= s_axis_tdata; - m_axis_tkeep_reg[seg_reg*SEG_KEEP_WIDTH +: SEG_KEEP_WIDTH] <= s_axis_tkeep; - end - m_axis_tlast_reg <= s_axis_tvalid_reg ? s_axis_tlast_reg : s_axis_tlast; - m_axis_tid_reg <= s_axis_tvalid_reg ? s_axis_tid_reg : s_axis_tid; - m_axis_tdest_reg <= s_axis_tvalid_reg ? s_axis_tdest_reg : s_axis_tdest; - m_axis_tuser_reg <= s_axis_tvalid_reg ? s_axis_tuser_reg : s_axis_tuser; - - if (s_axis_tvalid_reg) begin - // consume data from buffer - s_axis_tvalid_reg <= 1'b0; - - if (s_axis_tlast_reg || seg_reg == SEG_COUNT-1) begin - seg_reg <= 0; - m_axis_tvalid_reg <= 1'b1; - end else begin - seg_reg <= seg_reg + 1; - end - end else if (s_axis_tvalid) begin - // data direct from input - if (s_axis_tlast || seg_reg == SEG_COUNT-1) begin - seg_reg <= 0; - m_axis_tvalid_reg <= 1'b1; - end else begin - seg_reg <= seg_reg + 1; - end - end - end else if (s_axis_tvalid && s_axis_tready) begin - // store input data in skid buffer - s_axis_tdata_reg <= s_axis_tdata; - s_axis_tkeep_reg <= s_axis_tkeep; - s_axis_tvalid_reg <= 1'b1; - s_axis_tlast_reg <= s_axis_tlast; - s_axis_tid_reg <= s_axis_tid; - s_axis_tdest_reg <= s_axis_tdest; - s_axis_tuser_reg <= s_axis_tuser; - end - - if (rst) begin - seg_reg <= 0; - s_axis_tvalid_reg <= 1'b0; - m_axis_tvalid_reg <= 1'b0; - end - end - -end else begin : downsize - // output is narrower; downsize - - // required number of segments in wider bus - localparam SEG_COUNT = S_BYTE_LANES / M_BYTE_LANES; - // data width and keep width per segment - localparam SEG_DATA_WIDTH = S_DATA_WIDTH / SEG_COUNT; - localparam SEG_KEEP_WIDTH = S_BYTE_LANES / SEG_COUNT; - - reg [S_DATA_WIDTH-1:0] s_axis_tdata_reg = {S_DATA_WIDTH{1'b0}}; - reg [S_KEEP_WIDTH-1:0] s_axis_tkeep_reg = {S_KEEP_WIDTH{1'b0}}; - reg s_axis_tvalid_reg = 1'b0; - reg s_axis_tlast_reg = 1'b0; - reg [ID_WIDTH-1:0] s_axis_tid_reg = {ID_WIDTH{1'b0}}; - reg [DEST_WIDTH-1:0] s_axis_tdest_reg = {DEST_WIDTH{1'b0}}; - reg [USER_WIDTH-1:0] s_axis_tuser_reg = {USER_WIDTH{1'b0}}; - - reg [M_DATA_WIDTH-1:0] m_axis_tdata_reg = {M_DATA_WIDTH{1'b0}}; - reg [M_KEEP_WIDTH-1:0] m_axis_tkeep_reg = {M_KEEP_WIDTH{1'b0}}; - reg m_axis_tvalid_reg = 1'b0; - reg m_axis_tlast_reg = 1'b0; - reg [ID_WIDTH-1:0] m_axis_tid_reg = {ID_WIDTH{1'b0}}; - reg [DEST_WIDTH-1:0] m_axis_tdest_reg = {DEST_WIDTH{1'b0}}; - reg [USER_WIDTH-1:0] m_axis_tuser_reg = {USER_WIDTH{1'b0}}; - - assign s_axis_tready = !s_axis_tvalid_reg; - - assign m_axis_tdata = m_axis_tdata_reg; - assign m_axis_tkeep = M_KEEP_ENABLE ? m_axis_tkeep_reg : {M_KEEP_WIDTH{1'b1}}; - assign m_axis_tvalid = m_axis_tvalid_reg; - assign m_axis_tlast = m_axis_tlast_reg; - assign m_axis_tid = ID_ENABLE ? m_axis_tid_reg : {ID_WIDTH{1'b0}}; - assign m_axis_tdest = DEST_ENABLE ? m_axis_tdest_reg : {DEST_WIDTH{1'b0}}; - assign m_axis_tuser = USER_ENABLE ? m_axis_tuser_reg : {USER_WIDTH{1'b0}}; - - always @(posedge clk) begin - m_axis_tvalid_reg <= m_axis_tvalid_reg && !m_axis_tready; - - if (!m_axis_tvalid_reg || m_axis_tready) begin - // output register empty - - m_axis_tdata_reg <= s_axis_tvalid_reg ? s_axis_tdata_reg : s_axis_tdata; - m_axis_tkeep_reg <= s_axis_tvalid_reg ? s_axis_tkeep_reg : s_axis_tkeep; - m_axis_tlast_reg <= 1'b0; - m_axis_tid_reg <= s_axis_tvalid_reg ? s_axis_tid_reg : s_axis_tid; - m_axis_tdest_reg <= s_axis_tvalid_reg ? s_axis_tdest_reg : s_axis_tdest; - m_axis_tuser_reg <= s_axis_tvalid_reg ? s_axis_tuser_reg : s_axis_tuser; - - if (s_axis_tvalid_reg) begin - // buffer has data; shift out from buffer - s_axis_tdata_reg <= s_axis_tdata_reg >> SEG_DATA_WIDTH; - s_axis_tkeep_reg <= s_axis_tkeep_reg >> SEG_KEEP_WIDTH; - - m_axis_tvalid_reg <= 1'b1; - - if ((s_axis_tkeep_reg >> SEG_KEEP_WIDTH) == 0) begin - s_axis_tvalid_reg <= 1'b0; - m_axis_tlast_reg <= s_axis_tlast_reg; - end - end else if (s_axis_tvalid && s_axis_tready) begin - // buffer is empty; store from input - s_axis_tdata_reg <= s_axis_tdata >> SEG_DATA_WIDTH; - s_axis_tkeep_reg <= s_axis_tkeep >> SEG_KEEP_WIDTH; - s_axis_tlast_reg <= s_axis_tlast; - s_axis_tid_reg <= s_axis_tid; - s_axis_tdest_reg <= s_axis_tdest; - s_axis_tuser_reg <= s_axis_tuser; - - m_axis_tvalid_reg <= 1'b1; - - if ((s_axis_tkeep >> SEG_KEEP_WIDTH) == 0) begin - s_axis_tvalid_reg <= 1'b0; - m_axis_tlast_reg <= s_axis_tlast; - end else begin - s_axis_tvalid_reg <= 1'b1; - end - end - end else if (s_axis_tvalid && s_axis_tready) begin - // store input data - s_axis_tdata_reg <= s_axis_tdata; - s_axis_tkeep_reg <= s_axis_tkeep; - s_axis_tvalid_reg <= 1'b1; - s_axis_tlast_reg <= s_axis_tlast; - s_axis_tid_reg <= s_axis_tid; - s_axis_tdest_reg <= s_axis_tdest; - s_axis_tuser_reg <= s_axis_tuser; - end - - if (rst) begin - s_axis_tvalid_reg <= 1'b0; - m_axis_tvalid_reg <= 1'b0; - end - end - -end - -endgenerate - -endmodule - -`resetall diff --git a/src/rvvi/axis_async_fifo.sv b/src/rvvi/axis_async_fifo.sv deleted file mode 100644 index 1d8b6244f..000000000 --- a/src/rvvi/axis_async_fifo.sv +++ /dev/null @@ -1,909 +0,0 @@ -/* - -Copyright (c) 2014-2023 Alex Forencich - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - -*/ - -// Language: Verilog 2001 - -`resetall -`default_nettype none - -/* - * AXI4-Stream asynchronous FIFO - */ -module axis_async_fifo # -( - // FIFO depth in words - // KEEP_WIDTH words per cycle if KEEP_ENABLE set - // Rounded up to nearest power of 2 cycles - parameter DEPTH = 4096, - // Width of AXI stream interfaces in bits - parameter DATA_WIDTH = 8, - // Propagate tkeep signal - // If disabled, tkeep assumed to be 1'b1 - parameter KEEP_ENABLE = (DATA_WIDTH>8), - // tkeep signal width (words per cycle) - parameter KEEP_WIDTH = ((DATA_WIDTH+7)/8), - // Propagate tlast signal - parameter LAST_ENABLE = 1, - // Propagate tid signal - parameter ID_ENABLE = 0, - // tid signal width - parameter ID_WIDTH = 8, - // Propagate tdest signal - parameter DEST_ENABLE = 0, - // tdest signal width - parameter DEST_WIDTH = 8, - // Propagate tuser signal - parameter USER_ENABLE = 1, - // tuser signal width - parameter USER_WIDTH = 1, - // number of RAM pipeline registers - parameter RAM_PIPELINE = 1, - // use output FIFO - // When set, the RAM read enable and pipeline clock enables are removed - parameter OUTPUT_FIFO_ENABLE = 0, - // Frame FIFO mode - operate on frames instead of cycles - // When set, m_axis_tvalid will not be deasserted within a frame - // Requires LAST_ENABLE set - parameter FRAME_FIFO = 0, - // tuser value for bad frame marker - parameter USER_BAD_FRAME_VALUE = 1'b1, - // tuser mask for bad frame marker - parameter USER_BAD_FRAME_MASK = 1'b1, - // Drop frames larger than FIFO - // Requires FRAME_FIFO set - parameter DROP_OVERSIZE_FRAME = FRAME_FIFO, - // Drop frames marked bad - // Requires FRAME_FIFO and DROP_OVERSIZE_FRAME set - parameter DROP_BAD_FRAME = 0, - // Drop incoming frames when full - // When set, s_axis_tready is always asserted - // Requires FRAME_FIFO and DROP_OVERSIZE_FRAME set - parameter DROP_WHEN_FULL = 0, - // Mark incoming frames as bad frames when full - // When set, s_axis_tready is always asserted - // Requires FRAME_FIFO to be clear - parameter MARK_WHEN_FULL = 0, - // Enable pause request input - parameter PAUSE_ENABLE = 0, - // Pause between frames - parameter FRAME_PAUSE = FRAME_FIFO -) -( - /* - * AXI input - */ - input wire s_clk, - input wire s_rst, - input wire [DATA_WIDTH-1:0] s_axis_tdata, - input wire [KEEP_WIDTH-1:0] s_axis_tkeep, - input wire s_axis_tvalid, - output wire s_axis_tready, - input wire s_axis_tlast, - input wire [ID_WIDTH-1:0] s_axis_tid, - input wire [DEST_WIDTH-1:0] s_axis_tdest, - input wire [USER_WIDTH-1:0] s_axis_tuser, - - /* - * AXI output - */ - input wire m_clk, - input wire m_rst, - output wire [DATA_WIDTH-1:0] m_axis_tdata, - output wire [KEEP_WIDTH-1:0] m_axis_tkeep, - output wire m_axis_tvalid, - input wire m_axis_tready, - output wire m_axis_tlast, - output wire [ID_WIDTH-1:0] m_axis_tid, - output wire [DEST_WIDTH-1:0] m_axis_tdest, - output wire [USER_WIDTH-1:0] m_axis_tuser, - - /* - * Pause - */ - input wire s_pause_req, - output wire s_pause_ack, - input wire m_pause_req, - output wire m_pause_ack, - - /* - * Status - */ - output wire [$clog2(DEPTH):0] s_status_depth, - output wire [$clog2(DEPTH):0] s_status_depth_commit, - output wire s_status_overflow, - output wire s_status_bad_frame, - output wire s_status_good_frame, - output wire [$clog2(DEPTH):0] m_status_depth, - output wire [$clog2(DEPTH):0] m_status_depth_commit, - output wire m_status_overflow, - output wire m_status_bad_frame, - output wire m_status_good_frame -); - -parameter ADDR_WIDTH = (KEEP_ENABLE && KEEP_WIDTH > 1) ? $clog2(DEPTH/KEEP_WIDTH) : $clog2(DEPTH); - -parameter OUTPUT_FIFO_ADDR_WIDTH = RAM_PIPELINE < 2 ? 3 : $clog2(RAM_PIPELINE*2+7); - -// check configuration -initial begin - if (FRAME_FIFO && !LAST_ENABLE) begin - $error("Error: FRAME_FIFO set requires LAST_ENABLE set (instance %m)"); - $finish; - end - - if (DROP_OVERSIZE_FRAME && !FRAME_FIFO) begin - $error("Error: DROP_OVERSIZE_FRAME set requires FRAME_FIFO set (instance %m)"); - $finish; - end - - if (DROP_BAD_FRAME && !(FRAME_FIFO && DROP_OVERSIZE_FRAME)) begin - $error("Error: DROP_BAD_FRAME set requires FRAME_FIFO and DROP_OVERSIZE_FRAME set (instance %m)"); - $finish; - end - - if (DROP_WHEN_FULL && !(FRAME_FIFO && DROP_OVERSIZE_FRAME)) begin - $error("Error: DROP_WHEN_FULL set requires FRAME_FIFO and DROP_OVERSIZE_FRAME set (instance %m)"); - $finish; - end - - if ((DROP_BAD_FRAME || MARK_WHEN_FULL) && (USER_BAD_FRAME_MASK & {USER_WIDTH{1'b1}}) == 0) begin - $error("Error: Invalid USER_BAD_FRAME_MASK value (instance %m)"); - $finish; - end - - if (MARK_WHEN_FULL && FRAME_FIFO) begin - $error("Error: MARK_WHEN_FULL is not compatible with FRAME_FIFO (instance %m)"); - $finish; - end - - if (MARK_WHEN_FULL && !LAST_ENABLE) begin - $error("Error: MARK_WHEN_FULL set requires LAST_ENABLE set (instance %m)"); - $finish; - end -end - -localparam KEEP_OFFSET = DATA_WIDTH; -localparam LAST_OFFSET = KEEP_OFFSET + (KEEP_ENABLE ? KEEP_WIDTH : 0); -localparam ID_OFFSET = LAST_OFFSET + (LAST_ENABLE ? 1 : 0); -localparam DEST_OFFSET = ID_OFFSET + (ID_ENABLE ? ID_WIDTH : 0); -localparam USER_OFFSET = DEST_OFFSET + (DEST_ENABLE ? DEST_WIDTH : 0); -localparam WIDTH = USER_OFFSET + (USER_ENABLE ? USER_WIDTH : 0); - -function [ADDR_WIDTH:0] bin2gray(input [ADDR_WIDTH:0] b); - bin2gray = b ^ (b >> 1); -endfunction - -function [ADDR_WIDTH:0] gray2bin(input [ADDR_WIDTH:0] g); - integer i; - for (i = 0; i <= ADDR_WIDTH; i = i + 1) begin - gray2bin[i] = ^(g >> i); - end -endfunction - -reg [ADDR_WIDTH:0] wr_ptr_reg = {ADDR_WIDTH+1{1'b0}}; -reg [ADDR_WIDTH:0] wr_ptr_commit_reg = {ADDR_WIDTH+1{1'b0}}; -reg [ADDR_WIDTH:0] wr_ptr_gray_reg = {ADDR_WIDTH+1{1'b0}}; -reg [ADDR_WIDTH:0] wr_ptr_sync_commit_reg = {ADDR_WIDTH+1{1'b0}}; -reg [ADDR_WIDTH:0] rd_ptr_reg = {ADDR_WIDTH+1{1'b0}}; -reg [ADDR_WIDTH:0] rd_ptr_gray_reg = {ADDR_WIDTH+1{1'b0}}; -reg [ADDR_WIDTH:0] wr_ptr_conv_reg = {ADDR_WIDTH+1{1'b0}}; -reg [ADDR_WIDTH:0] rd_ptr_conv_reg = {ADDR_WIDTH+1{1'b0}}; - -reg [ADDR_WIDTH:0] wr_ptr_temp; -reg [ADDR_WIDTH:0] rd_ptr_temp; - -(* SHREG_EXTRACT = "NO" *) -reg [ADDR_WIDTH:0] wr_ptr_gray_sync1_reg = {ADDR_WIDTH+1{1'b0}}; -(* SHREG_EXTRACT = "NO" *) -reg [ADDR_WIDTH:0] wr_ptr_gray_sync2_reg = {ADDR_WIDTH+1{1'b0}}; -(* SHREG_EXTRACT = "NO" *) -reg [ADDR_WIDTH:0] wr_ptr_commit_sync_reg = {ADDR_WIDTH+1{1'b0}}; -(* SHREG_EXTRACT = "NO" *) -reg [ADDR_WIDTH:0] rd_ptr_gray_sync1_reg = {ADDR_WIDTH+1{1'b0}}; -(* SHREG_EXTRACT = "NO" *) -reg [ADDR_WIDTH:0] rd_ptr_gray_sync2_reg = {ADDR_WIDTH+1{1'b0}}; - -reg wr_ptr_update_valid_reg = 1'b0; -reg wr_ptr_update_reg = 1'b0; -(* SHREG_EXTRACT = "NO" *) -reg wr_ptr_update_sync1_reg = 1'b0; -(* SHREG_EXTRACT = "NO" *) -reg wr_ptr_update_sync2_reg = 1'b0; -(* SHREG_EXTRACT = "NO" *) -reg wr_ptr_update_sync3_reg = 1'b0; -(* SHREG_EXTRACT = "NO" *) -reg wr_ptr_update_ack_sync1_reg = 1'b0; -(* SHREG_EXTRACT = "NO" *) -reg wr_ptr_update_ack_sync2_reg = 1'b0; - -(* SHREG_EXTRACT = "NO" *) -reg s_rst_sync1_reg = 1'b1; -(* SHREG_EXTRACT = "NO" *) -reg s_rst_sync2_reg = 1'b1; -(* SHREG_EXTRACT = "NO" *) -reg s_rst_sync3_reg = 1'b1; -(* SHREG_EXTRACT = "NO" *) -reg m_rst_sync1_reg = 1'b1; -(* SHREG_EXTRACT = "NO" *) -reg m_rst_sync2_reg = 1'b1; -(* SHREG_EXTRACT = "NO" *) -reg m_rst_sync3_reg = 1'b1; - -(* ramstyle = "no_rw_check" *) -reg [WIDTH-1:0] mem[(2**ADDR_WIDTH)-1:0]; -reg mem_read_data_valid_reg = 1'b0; - -(* shreg_extract = "no" *) -reg [WIDTH-1:0] m_axis_pipe_reg[RAM_PIPELINE+1-1:0]; -reg [RAM_PIPELINE+1-1:0] m_axis_tvalid_pipe_reg = 0; - -// full when first TWO MSBs do NOT match, but rest matches -// (gray code equivalent of first MSB different but rest same) -wire full = wr_ptr_gray_reg == (rd_ptr_gray_sync2_reg ^ {2'b11, {ADDR_WIDTH-1{1'b0}}}); -// empty when pointers match exactly -wire empty = FRAME_FIFO ? (rd_ptr_reg == wr_ptr_commit_sync_reg) : (rd_ptr_gray_reg == wr_ptr_gray_sync2_reg); -// overflow within packet -wire full_wr = wr_ptr_reg == (wr_ptr_commit_reg ^ {1'b1, {ADDR_WIDTH{1'b0}}}); - -// control signals -reg write; -reg read; -reg store_output; - -reg s_frame_reg = 1'b0; -reg m_frame_reg = 1'b0; - -reg drop_frame_reg = 1'b0; -reg mark_frame_reg = 1'b0; -reg send_frame_reg = 1'b0; -reg overflow_reg = 1'b0; -reg bad_frame_reg = 1'b0; -reg good_frame_reg = 1'b0; - -reg m_drop_frame_reg = 1'b0; -reg m_terminate_frame_reg = 1'b0; - -reg [ADDR_WIDTH:0] s_depth_reg = 0; -reg [ADDR_WIDTH:0] s_depth_commit_reg = 0; -reg [ADDR_WIDTH:0] m_depth_reg = 0; -reg [ADDR_WIDTH:0] m_depth_commit_reg = 0; - -reg overflow_sync1_reg = 1'b0; -reg overflow_sync2_reg = 1'b0; -reg overflow_sync3_reg = 1'b0; -reg overflow_sync4_reg = 1'b0; -reg bad_frame_sync1_reg = 1'b0; -reg bad_frame_sync2_reg = 1'b0; -reg bad_frame_sync3_reg = 1'b0; -reg bad_frame_sync4_reg = 1'b0; -reg good_frame_sync1_reg = 1'b0; -reg good_frame_sync2_reg = 1'b0; -reg good_frame_sync3_reg = 1'b0; -reg good_frame_sync4_reg = 1'b0; - -assign s_axis_tready = (FRAME_FIFO ? (!full || (full_wr && DROP_OVERSIZE_FRAME) || DROP_WHEN_FULL) : (!full || MARK_WHEN_FULL)) && !s_rst_sync3_reg; - -wire [WIDTH-1:0] s_axis; - -generate - assign s_axis[DATA_WIDTH-1:0] = s_axis_tdata; - if (KEEP_ENABLE) assign s_axis[KEEP_OFFSET +: KEEP_WIDTH] = s_axis_tkeep; - if (LAST_ENABLE) assign s_axis[LAST_OFFSET] = s_axis_tlast | mark_frame_reg; - if (ID_ENABLE) assign s_axis[ID_OFFSET +: ID_WIDTH] = s_axis_tid; - if (DEST_ENABLE) assign s_axis[DEST_OFFSET +: DEST_WIDTH] = s_axis_tdest; - if (USER_ENABLE) assign s_axis[USER_OFFSET +: USER_WIDTH] = mark_frame_reg ? USER_BAD_FRAME_VALUE : s_axis_tuser; -endgenerate - -wire [WIDTH-1:0] m_axis = m_axis_pipe_reg[RAM_PIPELINE+1-1]; - -wire m_axis_tready_pipe; -wire m_axis_tvalid_pipe = m_axis_tvalid_pipe_reg[RAM_PIPELINE+1-1]; - -wire [DATA_WIDTH-1:0] m_axis_tdata_pipe = m_axis[DATA_WIDTH-1:0]; -wire [KEEP_WIDTH-1:0] m_axis_tkeep_pipe = KEEP_ENABLE ? m_axis[KEEP_OFFSET +: KEEP_WIDTH] : {KEEP_WIDTH{1'b1}}; -wire m_axis_tlast_pipe = LAST_ENABLE ? m_axis[LAST_OFFSET] | m_terminate_frame_reg : 1'b1; -wire [ID_WIDTH-1:0] m_axis_tid_pipe = ID_ENABLE ? m_axis[ID_OFFSET +: ID_WIDTH] : {ID_WIDTH{1'b0}}; -wire [DEST_WIDTH-1:0] m_axis_tdest_pipe = DEST_ENABLE ? m_axis[DEST_OFFSET +: DEST_WIDTH] : {DEST_WIDTH{1'b0}}; -wire [USER_WIDTH-1:0] m_axis_tuser_pipe = USER_ENABLE ? (m_terminate_frame_reg ? USER_BAD_FRAME_VALUE : m_axis[USER_OFFSET +: USER_WIDTH]) : {USER_WIDTH{1'b0}}; - -wire m_axis_tready_out; -wire m_axis_tvalid_out; - -wire [DATA_WIDTH-1:0] m_axis_tdata_out; -wire [KEEP_WIDTH-1:0] m_axis_tkeep_out; -wire m_axis_tlast_out; -wire [ID_WIDTH-1:0] m_axis_tid_out; -wire [DEST_WIDTH-1:0] m_axis_tdest_out; -wire [USER_WIDTH-1:0] m_axis_tuser_out; - -wire pipe_ready; - -assign s_status_depth = (KEEP_ENABLE && KEEP_WIDTH > 1) ? {s_depth_reg, {$clog2(KEEP_WIDTH){1'b0}}} : s_depth_reg; -assign s_status_depth_commit = (KEEP_ENABLE && KEEP_WIDTH > 1) ? {s_depth_commit_reg, {$clog2(KEEP_WIDTH){1'b0}}} : s_depth_commit_reg; -assign s_status_overflow = overflow_reg; -assign s_status_bad_frame = bad_frame_reg; -assign s_status_good_frame = good_frame_reg; - -assign m_status_depth = (KEEP_ENABLE && KEEP_WIDTH > 1) ? {m_depth_reg, {$clog2(KEEP_WIDTH){1'b0}}} : m_depth_reg; -assign m_status_depth_commit = (KEEP_ENABLE && KEEP_WIDTH > 1) ? {m_depth_commit_reg, {$clog2(KEEP_WIDTH){1'b0}}} : m_depth_commit_reg; -assign m_status_overflow = overflow_sync3_reg ^ overflow_sync4_reg; -assign m_status_bad_frame = bad_frame_sync3_reg ^ bad_frame_sync4_reg; -assign m_status_good_frame = good_frame_sync3_reg ^ good_frame_sync4_reg; - -// reset synchronization -always @(posedge m_clk or posedge m_rst) begin - if (m_rst) begin - s_rst_sync1_reg <= 1'b1; - end else begin - s_rst_sync1_reg <= 1'b0; - end -end - -always @(posedge s_clk) begin - s_rst_sync2_reg <= s_rst_sync1_reg; - s_rst_sync3_reg <= s_rst_sync2_reg; -end - -always @(posedge s_clk or posedge s_rst) begin - if (s_rst) begin - m_rst_sync1_reg <= 1'b1; - end else begin - m_rst_sync1_reg <= 1'b0; - end -end - -always @(posedge m_clk) begin - m_rst_sync2_reg <= m_rst_sync1_reg; - m_rst_sync3_reg <= m_rst_sync2_reg; -end - -// Write logic -always @(posedge s_clk) begin - overflow_reg <= 1'b0; - bad_frame_reg <= 1'b0; - good_frame_reg <= 1'b0; - - if (FRAME_FIFO && wr_ptr_update_valid_reg) begin - // have updated pointer to sync - if (wr_ptr_update_reg == wr_ptr_update_ack_sync2_reg) begin - // no sync in progress; sync update - wr_ptr_update_valid_reg <= 1'b0; - wr_ptr_sync_commit_reg <= wr_ptr_commit_reg; - wr_ptr_update_reg <= !wr_ptr_update_ack_sync2_reg; - end - end - - if (s_axis_tready && s_axis_tvalid && LAST_ENABLE) begin - // track input frame status - s_frame_reg <= !s_axis_tlast; - end - - if (s_rst_sync3_reg && LAST_ENABLE) begin - // if sink side is reset during transfer, drop partial frame - if (s_frame_reg && !(s_axis_tready && s_axis_tvalid && s_axis_tlast)) begin - drop_frame_reg <= 1'b1; - end - if (s_axis_tready && s_axis_tvalid && !s_axis_tlast) begin - drop_frame_reg <= 1'b1; - end - end - - if (FRAME_FIFO) begin - // frame FIFO mode - if (s_axis_tready && s_axis_tvalid) begin - // transfer in - if ((full && DROP_WHEN_FULL) || (full_wr && DROP_OVERSIZE_FRAME) || drop_frame_reg) begin - // full, packet overflow, or currently dropping frame - // drop frame - drop_frame_reg <= 1'b1; - if (s_axis_tlast) begin - // end of frame, reset write pointer - wr_ptr_temp = wr_ptr_commit_reg; - wr_ptr_reg <= wr_ptr_temp; - wr_ptr_gray_reg <= bin2gray(wr_ptr_temp); - drop_frame_reg <= 1'b0; - overflow_reg <= 1'b1; - end - end else begin - mem[wr_ptr_reg[ADDR_WIDTH-1:0]] <= s_axis; - wr_ptr_temp = wr_ptr_reg + 1; - wr_ptr_reg <= wr_ptr_temp; - wr_ptr_gray_reg <= bin2gray(wr_ptr_temp); - if (s_axis_tlast || (!DROP_OVERSIZE_FRAME && (full_wr || send_frame_reg))) begin - // end of frame or send frame - send_frame_reg <= !s_axis_tlast; - if (s_axis_tlast && DROP_BAD_FRAME && USER_BAD_FRAME_MASK & ~(s_axis_tuser ^ USER_BAD_FRAME_VALUE)) begin - // bad packet, reset write pointer - wr_ptr_temp = wr_ptr_commit_reg; - wr_ptr_reg <= wr_ptr_temp; - wr_ptr_gray_reg <= bin2gray(wr_ptr_temp); - bad_frame_reg <= 1'b1; - end else begin - // good packet or packet overflow, update write pointer - wr_ptr_temp = wr_ptr_reg + 1; - wr_ptr_reg <= wr_ptr_temp; - wr_ptr_commit_reg <= wr_ptr_temp; - wr_ptr_gray_reg <= bin2gray(wr_ptr_temp); - - if (wr_ptr_update_reg == wr_ptr_update_ack_sync2_reg) begin - // no sync in progress; sync update - wr_ptr_update_valid_reg <= 1'b0; - wr_ptr_sync_commit_reg <= wr_ptr_temp; - wr_ptr_update_reg <= !wr_ptr_update_ack_sync2_reg; - end else begin - // sync in progress; flag it for later - wr_ptr_update_valid_reg <= 1'b1; - end - - good_frame_reg <= s_axis_tlast; - end - end - end - end else if (s_axis_tvalid && full_wr && FRAME_FIFO && !DROP_OVERSIZE_FRAME) begin - // data valid with packet overflow - // update write pointer - send_frame_reg <= 1'b1; - wr_ptr_temp = wr_ptr_reg; - wr_ptr_reg <= wr_ptr_temp; - wr_ptr_commit_reg <= wr_ptr_temp; - wr_ptr_gray_reg <= bin2gray(wr_ptr_temp); - - if (wr_ptr_update_reg == wr_ptr_update_ack_sync2_reg) begin - // no sync in progress; sync update - wr_ptr_update_valid_reg <= 1'b0; - wr_ptr_sync_commit_reg <= wr_ptr_temp; - wr_ptr_update_reg <= !wr_ptr_update_ack_sync2_reg; - end else begin - // sync in progress; flag it for later - wr_ptr_update_valid_reg <= 1'b1; - end - end - end else begin - // normal FIFO mode - if (s_axis_tready && s_axis_tvalid) begin - if (drop_frame_reg && LAST_ENABLE) begin - // currently dropping frame - if (s_axis_tlast) begin - // end of frame - if (!full && mark_frame_reg && MARK_WHEN_FULL) begin - // terminate marked frame - mark_frame_reg <= 1'b0; - mem[wr_ptr_reg[ADDR_WIDTH-1:0]] <= s_axis; - wr_ptr_temp = wr_ptr_reg + 1; - wr_ptr_reg <= wr_ptr_temp; - wr_ptr_commit_reg <= wr_ptr_temp; - wr_ptr_gray_reg <= bin2gray(wr_ptr_temp); - end - // end of frame, clear drop flag - drop_frame_reg <= 1'b0; - overflow_reg <= 1'b1; - end - end else if ((full || mark_frame_reg) && MARK_WHEN_FULL) begin - // full or marking frame - // drop frame; mark if this isn't the first cycle - drop_frame_reg <= 1'b1; - mark_frame_reg <= mark_frame_reg || s_frame_reg; - if (s_axis_tlast) begin - drop_frame_reg <= 1'b0; - overflow_reg <= 1'b1; - end - end else begin - // transfer in - mem[wr_ptr_reg[ADDR_WIDTH-1:0]] <= s_axis; - wr_ptr_temp = wr_ptr_reg + 1; - wr_ptr_reg <= wr_ptr_temp; - wr_ptr_commit_reg <= wr_ptr_temp; - wr_ptr_gray_reg <= bin2gray(wr_ptr_temp); - end - end else if ((!full && !drop_frame_reg && mark_frame_reg) && MARK_WHEN_FULL) begin - // terminate marked frame - mark_frame_reg <= 1'b0; - mem[wr_ptr_reg[ADDR_WIDTH-1:0]] <= s_axis; - wr_ptr_temp = wr_ptr_reg + 1; - wr_ptr_reg <= wr_ptr_temp; - wr_ptr_commit_reg <= wr_ptr_temp; - wr_ptr_gray_reg <= bin2gray(wr_ptr_temp); - end - end - - if (s_rst_sync3_reg) begin - wr_ptr_reg <= {ADDR_WIDTH+1{1'b0}}; - wr_ptr_commit_reg <= {ADDR_WIDTH+1{1'b0}}; - wr_ptr_gray_reg <= {ADDR_WIDTH+1{1'b0}}; - wr_ptr_sync_commit_reg <= {ADDR_WIDTH+1{1'b0}}; - - wr_ptr_update_valid_reg <= 1'b0; - wr_ptr_update_reg <= 1'b0; - end - - if (s_rst) begin - wr_ptr_reg <= {ADDR_WIDTH+1{1'b0}}; - wr_ptr_commit_reg <= {ADDR_WIDTH+1{1'b0}}; - wr_ptr_gray_reg <= {ADDR_WIDTH+1{1'b0}}; - wr_ptr_sync_commit_reg <= {ADDR_WIDTH+1{1'b0}}; - - wr_ptr_update_valid_reg <= 1'b0; - wr_ptr_update_reg <= 1'b0; - - s_frame_reg <= 1'b0; - - drop_frame_reg <= 1'b0; - mark_frame_reg <= 1'b0; - send_frame_reg <= 1'b0; - overflow_reg <= 1'b0; - bad_frame_reg <= 1'b0; - good_frame_reg <= 1'b0; - end -end - -// Write-side status -always @(posedge s_clk) begin - rd_ptr_conv_reg <= gray2bin(rd_ptr_gray_sync2_reg); - s_depth_reg <= wr_ptr_reg - rd_ptr_conv_reg; - s_depth_commit_reg <= wr_ptr_commit_reg - rd_ptr_conv_reg; -end - -// pointer synchronization -always @(posedge s_clk) begin - rd_ptr_gray_sync1_reg <= rd_ptr_gray_reg; - rd_ptr_gray_sync2_reg <= rd_ptr_gray_sync1_reg; - wr_ptr_update_ack_sync1_reg <= wr_ptr_update_sync3_reg; - wr_ptr_update_ack_sync2_reg <= wr_ptr_update_ack_sync1_reg; - - if (s_rst) begin - rd_ptr_gray_sync1_reg <= {ADDR_WIDTH+1{1'b0}}; - rd_ptr_gray_sync2_reg <= {ADDR_WIDTH+1{1'b0}}; - wr_ptr_update_ack_sync1_reg <= 1'b0; - wr_ptr_update_ack_sync2_reg <= 1'b0; - end -end - -always @(posedge m_clk) begin - wr_ptr_gray_sync1_reg <= wr_ptr_gray_reg; - wr_ptr_gray_sync2_reg <= wr_ptr_gray_sync1_reg; - if (FRAME_FIFO && wr_ptr_update_sync2_reg ^ wr_ptr_update_sync3_reg) begin - wr_ptr_commit_sync_reg <= wr_ptr_sync_commit_reg; - end - wr_ptr_update_sync1_reg <= wr_ptr_update_reg; - wr_ptr_update_sync2_reg <= wr_ptr_update_sync1_reg; - wr_ptr_update_sync3_reg <= wr_ptr_update_sync2_reg; - - if (FRAME_FIFO && m_rst_sync3_reg) begin - wr_ptr_gray_sync1_reg <= {ADDR_WIDTH+1{1'b0}}; - end - - if (m_rst) begin - wr_ptr_gray_sync1_reg <= {ADDR_WIDTH+1{1'b0}}; - wr_ptr_gray_sync2_reg <= {ADDR_WIDTH+1{1'b0}}; - wr_ptr_commit_sync_reg <= {ADDR_WIDTH+1{1'b0}}; - wr_ptr_update_sync1_reg <= 1'b0; - wr_ptr_update_sync2_reg <= 1'b0; - wr_ptr_update_sync3_reg <= 1'b0; - end -end - -// status synchronization -always @(posedge s_clk) begin - overflow_sync1_reg <= overflow_sync1_reg ^ overflow_reg; - bad_frame_sync1_reg <= bad_frame_sync1_reg ^ bad_frame_reg; - good_frame_sync1_reg <= good_frame_sync1_reg ^ good_frame_reg; - - if (s_rst) begin - overflow_sync1_reg <= 1'b0; - bad_frame_sync1_reg <= 1'b0; - good_frame_sync1_reg <= 1'b0; - end -end - -always @(posedge m_clk) begin - overflow_sync2_reg <= overflow_sync1_reg; - overflow_sync3_reg <= overflow_sync2_reg; - overflow_sync4_reg <= overflow_sync3_reg; - bad_frame_sync2_reg <= bad_frame_sync1_reg; - bad_frame_sync3_reg <= bad_frame_sync2_reg; - bad_frame_sync4_reg <= bad_frame_sync3_reg; - good_frame_sync2_reg <= good_frame_sync1_reg; - good_frame_sync3_reg <= good_frame_sync2_reg; - good_frame_sync4_reg <= good_frame_sync3_reg; - - if (m_rst) begin - overflow_sync2_reg <= 1'b0; - overflow_sync3_reg <= 1'b0; - overflow_sync4_reg <= 1'b0; - bad_frame_sync2_reg <= 1'b0; - bad_frame_sync3_reg <= 1'b0; - bad_frame_sync4_reg <= 1'b0; - good_frame_sync2_reg <= 1'b0; - good_frame_sync3_reg <= 1'b0; - good_frame_sync4_reg <= 1'b0; - end -end - -// Read logic -integer j; - -always @(posedge m_clk) begin - if (m_axis_tready_pipe) begin - // output ready; invalidate stage - m_axis_tvalid_pipe_reg[RAM_PIPELINE+1-1] <= 1'b0; - m_terminate_frame_reg <= 1'b0; - end - - for (j = RAM_PIPELINE+1-1; j > 0; j = j - 1) begin - if (m_axis_tready_pipe || ((~m_axis_tvalid_pipe_reg) >> j)) begin - // output ready or bubble in pipeline; transfer down pipeline - m_axis_tvalid_pipe_reg[j] <= m_axis_tvalid_pipe_reg[j-1]; - m_axis_pipe_reg[j] <= m_axis_pipe_reg[j-1]; - m_axis_tvalid_pipe_reg[j-1] <= 1'b0; - end - end - - if (m_axis_tready_pipe || ~m_axis_tvalid_pipe_reg) begin - // output ready or bubble in pipeline; read new data from FIFO - m_axis_tvalid_pipe_reg[0] <= 1'b0; - m_axis_pipe_reg[0] <= mem[rd_ptr_reg[ADDR_WIDTH-1:0]]; - if (!empty && !m_rst_sync3_reg && !m_drop_frame_reg && pipe_ready) begin - // not empty, increment pointer - m_axis_tvalid_pipe_reg[0] <= 1'b1; - rd_ptr_temp = rd_ptr_reg + 1; - rd_ptr_reg <= rd_ptr_temp; - rd_ptr_gray_reg <= rd_ptr_temp ^ (rd_ptr_temp >> 1); - end - end - - if (m_axis_tvalid_pipe && LAST_ENABLE) begin - // track output frame status - if (m_axis_tlast_pipe && m_axis_tready_pipe) begin - m_frame_reg <= 1'b0; - end else begin - m_frame_reg <= 1'b1; - end - end - - if (m_drop_frame_reg && (OUTPUT_FIFO_ENABLE ? pipe_ready : m_axis_tready_pipe || !m_axis_tvalid_pipe) && LAST_ENABLE) begin - // terminate frame - // (only for frame transfers interrupted by source reset) - m_axis_tvalid_pipe_reg[RAM_PIPELINE+1-1] <= 1'b1; - m_terminate_frame_reg <= 1'b1; - m_drop_frame_reg <= 1'b0; - end - - if (m_rst_sync3_reg && LAST_ENABLE) begin - // if source side is reset during transfer, drop partial frame - - // empty output pipeline, except for last stage - if (RAM_PIPELINE > 0) begin - m_axis_tvalid_pipe_reg[RAM_PIPELINE+1-2:0] <= 0; - end - - if (m_frame_reg && (!m_axis_tvalid_pipe || (m_axis_tvalid_pipe && !m_axis_tlast_pipe)) && - !(m_drop_frame_reg || m_terminate_frame_reg)) begin - // terminate frame - m_drop_frame_reg <= 1'b1; - end - end - - if (m_rst_sync3_reg) begin - rd_ptr_reg <= {ADDR_WIDTH+1{1'b0}}; - rd_ptr_gray_reg <= {ADDR_WIDTH+1{1'b0}}; - end - - if (m_rst) begin - rd_ptr_reg <= {ADDR_WIDTH+1{1'b0}}; - rd_ptr_gray_reg <= {ADDR_WIDTH+1{1'b0}}; - m_axis_tvalid_pipe_reg <= 0; - m_frame_reg <= 1'b0; - m_drop_frame_reg <= 1'b0; - m_terminate_frame_reg <= 1'b0; - end -end - -// Read-side status -always @(posedge m_clk) begin - wr_ptr_conv_reg <= gray2bin(wr_ptr_gray_sync2_reg); - m_depth_reg <= wr_ptr_conv_reg - rd_ptr_reg; - m_depth_commit_reg <= FRAME_FIFO ? wr_ptr_commit_sync_reg - rd_ptr_reg : wr_ptr_conv_reg - rd_ptr_reg; -end - -generate - -if (!OUTPUT_FIFO_ENABLE) begin - - assign pipe_ready = 1'b1; - - assign m_axis_tready_pipe = m_axis_tready_out; - assign m_axis_tvalid_out = m_axis_tvalid_pipe; - - assign m_axis_tdata_out = m_axis_tdata_pipe; - assign m_axis_tkeep_out = m_axis_tkeep_pipe; - assign m_axis_tlast_out = m_axis_tlast_pipe; - assign m_axis_tid_out = m_axis_tid_pipe; - assign m_axis_tdest_out = m_axis_tdest_pipe; - assign m_axis_tuser_out = m_axis_tuser_pipe; - -end else begin : output_fifo - - // output datapath logic - reg [DATA_WIDTH-1:0] m_axis_tdata_reg = {DATA_WIDTH{1'b0}}; - reg [KEEP_WIDTH-1:0] m_axis_tkeep_reg = {KEEP_WIDTH{1'b0}}; - reg m_axis_tvalid_reg = 1'b0; - reg m_axis_tlast_reg = 1'b0; - reg [ID_WIDTH-1:0] m_axis_tid_reg = {ID_WIDTH{1'b0}}; - reg [DEST_WIDTH-1:0] m_axis_tdest_reg = {DEST_WIDTH{1'b0}}; - reg [USER_WIDTH-1:0] m_axis_tuser_reg = {USER_WIDTH{1'b0}}; - - reg [OUTPUT_FIFO_ADDR_WIDTH+1-1:0] out_fifo_wr_ptr_reg = 0; - reg [OUTPUT_FIFO_ADDR_WIDTH+1-1:0] out_fifo_rd_ptr_reg = 0; - reg out_fifo_half_full_reg = 1'b0; - - wire out_fifo_full = out_fifo_wr_ptr_reg == (out_fifo_rd_ptr_reg ^ {1'b1, {OUTPUT_FIFO_ADDR_WIDTH{1'b0}}}); - wire out_fifo_empty = out_fifo_wr_ptr_reg == out_fifo_rd_ptr_reg; - - (* ram_style = "distributed", ramstyle = "no_rw_check, mlab" *) - reg [DATA_WIDTH-1:0] out_fifo_tdata[2**OUTPUT_FIFO_ADDR_WIDTH-1:0]; - (* ram_style = "distributed", ramstyle = "no_rw_check, mlab" *) - reg [KEEP_WIDTH-1:0] out_fifo_tkeep[2**OUTPUT_FIFO_ADDR_WIDTH-1:0]; - (* ram_style = "distributed", ramstyle = "no_rw_check, mlab" *) - reg out_fifo_tlast[2**OUTPUT_FIFO_ADDR_WIDTH-1:0]; - (* ram_style = "distributed", ramstyle = "no_rw_check, mlab" *) - reg [ID_WIDTH-1:0] out_fifo_tid[2**OUTPUT_FIFO_ADDR_WIDTH-1:0]; - (* ram_style = "distributed", ramstyle = "no_rw_check, mlab" *) - reg [DEST_WIDTH-1:0] out_fifo_tdest[2**OUTPUT_FIFO_ADDR_WIDTH-1:0]; - (* ram_style = "distributed", ramstyle = "no_rw_check, mlab" *) - reg [USER_WIDTH-1:0] out_fifo_tuser[2**OUTPUT_FIFO_ADDR_WIDTH-1:0]; - - assign pipe_ready = !out_fifo_half_full_reg; - - assign m_axis_tready_pipe = 1'b1; - - assign m_axis_tdata_out = m_axis_tdata_reg; - assign m_axis_tkeep_out = KEEP_ENABLE ? m_axis_tkeep_reg : {KEEP_WIDTH{1'b1}}; - assign m_axis_tvalid_out = m_axis_tvalid_reg; - assign m_axis_tlast_out = LAST_ENABLE ? m_axis_tlast_reg : 1'b1; - assign m_axis_tid_out = ID_ENABLE ? m_axis_tid_reg : {ID_WIDTH{1'b0}}; - assign m_axis_tdest_out = DEST_ENABLE ? m_axis_tdest_reg : {DEST_WIDTH{1'b0}}; - assign m_axis_tuser_out = USER_ENABLE ? m_axis_tuser_reg : {USER_WIDTH{1'b0}}; - - always @(posedge m_clk) begin - m_axis_tvalid_reg <= m_axis_tvalid_reg && !m_axis_tready_out; - - out_fifo_half_full_reg <= $unsigned(out_fifo_wr_ptr_reg - out_fifo_rd_ptr_reg) >= 2**(OUTPUT_FIFO_ADDR_WIDTH-1); - - if (!out_fifo_full && m_axis_tvalid_pipe) begin - out_fifo_tdata[out_fifo_wr_ptr_reg[OUTPUT_FIFO_ADDR_WIDTH-1:0]] <= m_axis_tdata_pipe; - out_fifo_tkeep[out_fifo_wr_ptr_reg[OUTPUT_FIFO_ADDR_WIDTH-1:0]] <= m_axis_tkeep_pipe; - out_fifo_tlast[out_fifo_wr_ptr_reg[OUTPUT_FIFO_ADDR_WIDTH-1:0]] <= m_axis_tlast_pipe; - out_fifo_tid[out_fifo_wr_ptr_reg[OUTPUT_FIFO_ADDR_WIDTH-1:0]] <= m_axis_tid_pipe; - out_fifo_tdest[out_fifo_wr_ptr_reg[OUTPUT_FIFO_ADDR_WIDTH-1:0]] <= m_axis_tdest_pipe; - out_fifo_tuser[out_fifo_wr_ptr_reg[OUTPUT_FIFO_ADDR_WIDTH-1:0]] <= m_axis_tuser_pipe; - out_fifo_wr_ptr_reg <= out_fifo_wr_ptr_reg + 1; - end - - if (!out_fifo_empty && (!m_axis_tvalid_reg || m_axis_tready_out)) begin - m_axis_tdata_reg <= out_fifo_tdata[out_fifo_rd_ptr_reg[OUTPUT_FIFO_ADDR_WIDTH-1:0]]; - m_axis_tkeep_reg <= out_fifo_tkeep[out_fifo_rd_ptr_reg[OUTPUT_FIFO_ADDR_WIDTH-1:0]]; - m_axis_tvalid_reg <= 1'b1; - m_axis_tlast_reg <= out_fifo_tlast[out_fifo_rd_ptr_reg[OUTPUT_FIFO_ADDR_WIDTH-1:0]]; - m_axis_tid_reg <= out_fifo_tid[out_fifo_rd_ptr_reg[OUTPUT_FIFO_ADDR_WIDTH-1:0]]; - m_axis_tdest_reg <= out_fifo_tdest[out_fifo_rd_ptr_reg[OUTPUT_FIFO_ADDR_WIDTH-1:0]]; - m_axis_tuser_reg <= out_fifo_tuser[out_fifo_rd_ptr_reg[OUTPUT_FIFO_ADDR_WIDTH-1:0]]; - out_fifo_rd_ptr_reg <= out_fifo_rd_ptr_reg + 1; - end - - if (m_rst) begin - out_fifo_wr_ptr_reg <= 0; - out_fifo_rd_ptr_reg <= 0; - m_axis_tvalid_reg <= 1'b0; - end - end - -end - -if (PAUSE_ENABLE) begin : pause - - // Pause logic - reg pause_reg = 1'b0; - reg pause_frame_reg = 1'b0; - - reg s_pause_req_sync1_reg; - reg s_pause_req_sync2_reg; - reg s_pause_req_sync3_reg; - reg s_pause_ack_sync1_reg; - reg s_pause_ack_sync2_reg; - reg s_pause_ack_sync3_reg; - - always @(posedge s_clk) begin - s_pause_req_sync1_reg <= s_pause_req; - s_pause_ack_sync2_reg <= s_pause_ack_sync1_reg; - s_pause_ack_sync3_reg <= s_pause_ack_sync2_reg; - end - - always @(posedge m_clk) begin - s_pause_req_sync2_reg <= s_pause_req_sync1_reg; - s_pause_req_sync3_reg <= s_pause_req_sync2_reg; - s_pause_ack_sync1_reg <= pause_reg; - end - - assign m_axis_tready_out = m_axis_tready && !pause_reg; - assign m_axis_tvalid = m_axis_tvalid_out && !pause_reg; - - assign m_axis_tdata = m_axis_tdata_out; - assign m_axis_tkeep = m_axis_tkeep_out; - assign m_axis_tlast = m_axis_tlast_out; - assign m_axis_tid = m_axis_tid_out; - assign m_axis_tdest = m_axis_tdest_out; - assign m_axis_tuser = m_axis_tuser_out; - - assign s_pause_ack = s_pause_ack_sync3_reg; - assign m_pause_ack = pause_reg; - - always @(posedge m_clk) begin - if (FRAME_PAUSE) begin - if (pause_reg) begin - // paused; update pause status - pause_reg <= m_pause_req || s_pause_req_sync3_reg; - end else if (m_axis_tvalid_out) begin - // frame transfer; set frame bit - pause_frame_reg <= 1'b1; - if (m_axis_tready && m_axis_tlast) begin - // end of frame; clear frame bit and update pause status - pause_frame_reg <= 1'b0; - pause_reg <= m_pause_req || s_pause_req_sync3_reg; - end - end else if (!pause_frame_reg) begin - // idle; update pause status - pause_reg <= m_pause_req || s_pause_req_sync3_reg; - end - end else begin - pause_reg <= m_pause_req || s_pause_req_sync3_reg; - end - - if (m_rst) begin - pause_frame_reg <= 1'b0; - pause_reg <= 1'b0; - end - end - -end else begin - - assign m_axis_tready_out = m_axis_tready; - assign m_axis_tvalid = m_axis_tvalid_out; - - assign m_axis_tdata = m_axis_tdata_out; - assign m_axis_tkeep = m_axis_tkeep_out; - assign m_axis_tlast = m_axis_tlast_out; - assign m_axis_tid = m_axis_tid_out; - assign m_axis_tdest = m_axis_tdest_out; - assign m_axis_tuser = m_axis_tuser_out; - - assign s_pause_ack = 1'b0; - assign m_pause_ack = 1'b0; - -end - -endgenerate - -endmodule - -`resetall diff --git a/src/rvvi/axis_async_fifo_adapter.sv b/src/rvvi/axis_async_fifo_adapter.sv deleted file mode 100644 index d1e71b9fc..000000000 --- a/src/rvvi/axis_async_fifo_adapter.sv +++ /dev/null @@ -1,377 +0,0 @@ -/* - -Copyright (c) 2019 Alex Forencich - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - -*/ - -// Language: Verilog 2001 - -`resetall -`default_nettype none - -/* - * AXI4-Stream asynchronous FIFO with width converter - */ -module axis_async_fifo_adapter # -( - // FIFO depth in words - // KEEP_WIDTH words per cycle if KEEP_ENABLE set - // Rounded up to nearest power of 2 cycles - parameter DEPTH = 4096, - // Width of input AXI stream interface in bits - parameter S_DATA_WIDTH = 8, - // Propagate tkeep signal on input interface - // If disabled, tkeep assumed to be 1'b1 - parameter S_KEEP_ENABLE = (S_DATA_WIDTH>8), - // tkeep signal width (words per cycle) on input interface - parameter S_KEEP_WIDTH = ((S_DATA_WIDTH+7)/8), - // Width of output AXI stream interface in bits - parameter M_DATA_WIDTH = 8, - // Propagate tkeep signal on output interface - // If disabled, tkeep assumed to be 1'b1 - parameter M_KEEP_ENABLE = (M_DATA_WIDTH>8), - // tkeep signal width (words per cycle) on output interface - parameter M_KEEP_WIDTH = ((M_DATA_WIDTH+7)/8), - // Propagate tid signal - parameter ID_ENABLE = 0, - // tid signal width - parameter ID_WIDTH = 8, - // Propagate tdest signal - parameter DEST_ENABLE = 0, - // tdest signal width - parameter DEST_WIDTH = 8, - // Propagate tuser signal - parameter USER_ENABLE = 1, - // tuser signal width - parameter USER_WIDTH = 1, - // number of RAM pipeline registers in FIFO - parameter RAM_PIPELINE = 1, - // use output FIFO - // When set, the RAM read enable and pipeline clock enables are removed - parameter OUTPUT_FIFO_ENABLE = 0, - // Frame FIFO mode - operate on frames instead of cycles - // When set, m_axis_tvalid will not be deasserted within a frame - // Requires LAST_ENABLE set - parameter FRAME_FIFO = 0, - // tuser value for bad frame marker - parameter USER_BAD_FRAME_VALUE = 1'b1, - // tuser mask for bad frame marker - parameter USER_BAD_FRAME_MASK = 1'b1, - // Drop frames larger than FIFO - // Requires FRAME_FIFO set - parameter DROP_OVERSIZE_FRAME = FRAME_FIFO, - // Drop frames marked bad - // Requires FRAME_FIFO and DROP_OVERSIZE_FRAME set - parameter DROP_BAD_FRAME = 0, - // Drop incoming frames when full - // When set, s_axis_tready is always asserted - // Requires FRAME_FIFO and DROP_OVERSIZE_FRAME set - parameter DROP_WHEN_FULL = 0, - // Mark incoming frames as bad frames when full - // When set, s_axis_tready is always asserted - // Requires FRAME_FIFO to be clear - parameter MARK_WHEN_FULL = 0, - // Enable pause request input - parameter PAUSE_ENABLE = 0, - // Pause between frames - parameter FRAME_PAUSE = FRAME_FIFO -) -( - /* - * AXI input - */ - input wire s_clk, - input wire s_rst, - input wire [S_DATA_WIDTH-1:0] s_axis_tdata, - input wire [S_KEEP_WIDTH-1:0] s_axis_tkeep, - input wire s_axis_tvalid, - output wire s_axis_tready, - input wire s_axis_tlast, - input wire [ID_WIDTH-1:0] s_axis_tid, - input wire [DEST_WIDTH-1:0] s_axis_tdest, - input wire [USER_WIDTH-1:0] s_axis_tuser, - - /* - * AXI output - */ - input wire m_clk, - input wire m_rst, - output wire [M_DATA_WIDTH-1:0] m_axis_tdata, - output wire [M_KEEP_WIDTH-1:0] m_axis_tkeep, - output wire m_axis_tvalid, - input wire m_axis_tready, - output wire m_axis_tlast, - output wire [ID_WIDTH-1:0] m_axis_tid, - output wire [DEST_WIDTH-1:0] m_axis_tdest, - output wire [USER_WIDTH-1:0] m_axis_tuser, - - /* - * Pause - */ - input wire s_pause_req, - output wire s_pause_ack, - input wire m_pause_req, - output wire m_pause_ack, - - /* - * Status - */ - output wire [$clog2(DEPTH):0] s_status_depth, - output wire [$clog2(DEPTH):0] s_status_depth_commit, - output wire s_status_overflow, - output wire s_status_bad_frame, - output wire s_status_good_frame, - output wire [$clog2(DEPTH):0] m_status_depth, - output wire [$clog2(DEPTH):0] m_status_depth_commit, - output wire m_status_overflow, - output wire m_status_bad_frame, - output wire m_status_good_frame -); - -// force keep width to 1 when disabled -localparam S_BYTE_LANES = S_KEEP_ENABLE ? S_KEEP_WIDTH : 1; -localparam M_BYTE_LANES = M_KEEP_ENABLE ? M_KEEP_WIDTH : 1; - -// bus byte sizes (must be identical) -localparam S_BYTE_SIZE = S_DATA_WIDTH / S_BYTE_LANES; -localparam M_BYTE_SIZE = M_DATA_WIDTH / M_BYTE_LANES; -// output bus is wider -localparam EXPAND_BUS = M_BYTE_LANES > S_BYTE_LANES; -// total data and keep widths -localparam DATA_WIDTH = EXPAND_BUS ? M_DATA_WIDTH : S_DATA_WIDTH; -localparam KEEP_WIDTH = EXPAND_BUS ? M_BYTE_LANES : S_BYTE_LANES; - -// bus width assertions -initial begin - if (S_BYTE_SIZE * S_BYTE_LANES != S_DATA_WIDTH) begin - $error("Error: input data width not evenly divisible (instance %m)"); - $finish; - end - - if (M_BYTE_SIZE * M_BYTE_LANES != M_DATA_WIDTH) begin - $error("Error: output data width not evenly divisible (instance %m)"); - $finish; - end - - if (S_BYTE_SIZE != M_BYTE_SIZE) begin - $error("Error: byte size mismatch (instance %m)"); - $finish; - end -end - -wire [DATA_WIDTH-1:0] pre_fifo_axis_tdata; -wire [KEEP_WIDTH-1:0] pre_fifo_axis_tkeep; -wire pre_fifo_axis_tvalid; -wire pre_fifo_axis_tready; -wire pre_fifo_axis_tlast; -wire [ID_WIDTH-1:0] pre_fifo_axis_tid; -wire [DEST_WIDTH-1:0] pre_fifo_axis_tdest; -wire [USER_WIDTH-1:0] pre_fifo_axis_tuser; - -wire [DATA_WIDTH-1:0] post_fifo_axis_tdata; -wire [KEEP_WIDTH-1:0] post_fifo_axis_tkeep; -wire post_fifo_axis_tvalid; -wire post_fifo_axis_tready; -wire post_fifo_axis_tlast; -wire [ID_WIDTH-1:0] post_fifo_axis_tid; -wire [DEST_WIDTH-1:0] post_fifo_axis_tdest; -wire [USER_WIDTH-1:0] post_fifo_axis_tuser; - -generate - -if (M_BYTE_LANES > S_BYTE_LANES) begin : upsize_pre - - // output wider, adapt width before FIFO - - axis_adapter #( - .S_DATA_WIDTH(S_DATA_WIDTH), - .S_KEEP_ENABLE(S_KEEP_ENABLE), - .S_KEEP_WIDTH(S_KEEP_WIDTH), - .M_DATA_WIDTH(M_DATA_WIDTH), - .M_KEEP_ENABLE(M_KEEP_ENABLE), - .M_KEEP_WIDTH(M_KEEP_WIDTH), - .ID_ENABLE(ID_ENABLE), - .ID_WIDTH(ID_WIDTH), - .DEST_ENABLE(DEST_ENABLE), - .DEST_WIDTH(DEST_WIDTH), - .USER_ENABLE(USER_ENABLE), - .USER_WIDTH(USER_WIDTH) - ) - adapter_inst ( - .clk(s_clk), - .rst(s_rst), - // AXI input - .s_axis_tdata(s_axis_tdata), - .s_axis_tkeep(s_axis_tkeep), - .s_axis_tvalid(s_axis_tvalid), - .s_axis_tready(s_axis_tready), - .s_axis_tlast(s_axis_tlast), - .s_axis_tid(s_axis_tid), - .s_axis_tdest(s_axis_tdest), - .s_axis_tuser(s_axis_tuser), - // AXI output - .m_axis_tdata(pre_fifo_axis_tdata), - .m_axis_tkeep(pre_fifo_axis_tkeep), - .m_axis_tvalid(pre_fifo_axis_tvalid), - .m_axis_tready(pre_fifo_axis_tready), - .m_axis_tlast(pre_fifo_axis_tlast), - .m_axis_tid(pre_fifo_axis_tid), - .m_axis_tdest(pre_fifo_axis_tdest), - .m_axis_tuser(pre_fifo_axis_tuser) - ); - -end else begin : bypass_pre - - assign pre_fifo_axis_tdata = s_axis_tdata; - assign pre_fifo_axis_tkeep = s_axis_tkeep; - assign pre_fifo_axis_tvalid = s_axis_tvalid; - assign s_axis_tready = pre_fifo_axis_tready; - assign pre_fifo_axis_tlast = s_axis_tlast; - assign pre_fifo_axis_tid = s_axis_tid; - assign pre_fifo_axis_tdest = s_axis_tdest; - assign pre_fifo_axis_tuser = s_axis_tuser; - -end - -axis_async_fifo #( - .DEPTH(DEPTH), - .DATA_WIDTH(DATA_WIDTH), - .KEEP_ENABLE(EXPAND_BUS ? M_KEEP_ENABLE : S_KEEP_ENABLE), - .KEEP_WIDTH(KEEP_WIDTH), - .LAST_ENABLE(1), - .ID_ENABLE(ID_ENABLE), - .ID_WIDTH(ID_WIDTH), - .DEST_ENABLE(DEST_ENABLE), - .DEST_WIDTH(DEST_WIDTH), - .USER_ENABLE(USER_ENABLE), - .USER_WIDTH(USER_WIDTH), - .RAM_PIPELINE(RAM_PIPELINE), - .OUTPUT_FIFO_ENABLE(OUTPUT_FIFO_ENABLE), - .FRAME_FIFO(FRAME_FIFO), - .USER_BAD_FRAME_VALUE(USER_BAD_FRAME_VALUE), - .USER_BAD_FRAME_MASK(USER_BAD_FRAME_MASK), - .DROP_OVERSIZE_FRAME(DROP_OVERSIZE_FRAME), - .DROP_BAD_FRAME(DROP_BAD_FRAME), - .DROP_WHEN_FULL(DROP_WHEN_FULL), - .MARK_WHEN_FULL(MARK_WHEN_FULL), - .PAUSE_ENABLE(PAUSE_ENABLE), - .FRAME_PAUSE(FRAME_PAUSE) -) -fifo_inst ( - // AXI input - .s_clk(s_clk), - .s_rst(s_rst), - .s_axis_tdata(pre_fifo_axis_tdata), - .s_axis_tkeep(pre_fifo_axis_tkeep), - .s_axis_tvalid(pre_fifo_axis_tvalid), - .s_axis_tready(pre_fifo_axis_tready), - .s_axis_tlast(pre_fifo_axis_tlast), - .s_axis_tid(pre_fifo_axis_tid), - .s_axis_tdest(pre_fifo_axis_tdest), - .s_axis_tuser(pre_fifo_axis_tuser), - // AXI output - .m_clk(m_clk), - .m_rst(m_rst), - .m_axis_tdata(post_fifo_axis_tdata), - .m_axis_tkeep(post_fifo_axis_tkeep), - .m_axis_tvalid(post_fifo_axis_tvalid), - .m_axis_tready(post_fifo_axis_tready), - .m_axis_tlast(post_fifo_axis_tlast), - .m_axis_tid(post_fifo_axis_tid), - .m_axis_tdest(post_fifo_axis_tdest), - .m_axis_tuser(post_fifo_axis_tuser), - // Pause - .s_pause_req(s_pause_req), - .s_pause_ack(s_pause_ack), - .m_pause_req(m_pause_req), - .m_pause_ack(m_pause_ack), - // Status - .s_status_depth(s_status_depth), - .s_status_depth_commit(s_status_depth_commit), - .s_status_overflow(s_status_overflow), - .s_status_bad_frame(s_status_bad_frame), - .s_status_good_frame(s_status_good_frame), - .m_status_depth(m_status_depth), - .m_status_depth_commit(m_status_depth_commit), - .m_status_overflow(m_status_overflow), - .m_status_bad_frame(m_status_bad_frame), - .m_status_good_frame(m_status_good_frame) -); - -if (M_BYTE_LANES < S_BYTE_LANES) begin : downsize_post - - // input wider, adapt width after FIFO - - axis_adapter #( - .S_DATA_WIDTH(S_DATA_WIDTH), - .S_KEEP_ENABLE(S_KEEP_ENABLE), - .S_KEEP_WIDTH(S_KEEP_WIDTH), - .M_DATA_WIDTH(M_DATA_WIDTH), - .M_KEEP_ENABLE(M_KEEP_ENABLE), - .M_KEEP_WIDTH(M_KEEP_WIDTH), - .ID_ENABLE(ID_ENABLE), - .ID_WIDTH(ID_WIDTH), - .DEST_ENABLE(DEST_ENABLE), - .DEST_WIDTH(DEST_WIDTH), - .USER_ENABLE(USER_ENABLE), - .USER_WIDTH(USER_WIDTH) - ) - adapter_inst ( - .clk(m_clk), - .rst(m_rst), - // AXI input - .s_axis_tdata(post_fifo_axis_tdata), - .s_axis_tkeep(post_fifo_axis_tkeep), - .s_axis_tvalid(post_fifo_axis_tvalid), - .s_axis_tready(post_fifo_axis_tready), - .s_axis_tlast(post_fifo_axis_tlast), - .s_axis_tid(post_fifo_axis_tid), - .s_axis_tdest(post_fifo_axis_tdest), - .s_axis_tuser(post_fifo_axis_tuser), - // AXI output - .m_axis_tdata(m_axis_tdata), - .m_axis_tkeep(m_axis_tkeep), - .m_axis_tvalid(m_axis_tvalid), - .m_axis_tready(m_axis_tready), - .m_axis_tlast(m_axis_tlast), - .m_axis_tid(m_axis_tid), - .m_axis_tdest(m_axis_tdest), - .m_axis_tuser(m_axis_tuser) - ); - -end else begin : bypass_post - - assign m_axis_tdata = post_fifo_axis_tdata; - assign m_axis_tkeep = post_fifo_axis_tkeep; - assign m_axis_tvalid = post_fifo_axis_tvalid; - assign post_fifo_axis_tready = m_axis_tready; - assign m_axis_tlast = post_fifo_axis_tlast; - assign m_axis_tid = post_fifo_axis_tid; - assign m_axis_tdest = post_fifo_axis_tdest; - assign m_axis_tuser = post_fifo_axis_tuser; - -end - -endgenerate - -endmodule - -`resetall diff --git a/src/rvvi/axis_gmii_rx.sv b/src/rvvi/axis_gmii_rx.sv deleted file mode 100644 index 037fce77a..000000000 --- a/src/rvvi/axis_gmii_rx.sv +++ /dev/null @@ -1,357 +0,0 @@ -/* - -Copyright (c) 2015-2018 Alex Forencich - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - -*/ - -// Language: Verilog 2001 - -`resetall -`default_nettype none - -/* - * AXI4-Stream GMII frame receiver (GMII in, AXI out) - */ -module axis_gmii_rx # -( - parameter DATA_WIDTH = 8, - parameter PTP_TS_ENABLE = 0, - parameter PTP_TS_WIDTH = 96, - parameter USER_WIDTH = (PTP_TS_ENABLE ? PTP_TS_WIDTH : 0) + 1 -) -( - input wire clk, - input wire rst, - - /* - * GMII input - */ - input wire [DATA_WIDTH-1:0] gmii_rxd, - input wire gmii_rx_dv, - input wire gmii_rx_er, - - /* - * AXI output - */ - output wire [DATA_WIDTH-1:0] m_axis_tdata, - output wire m_axis_tvalid, - output wire m_axis_tlast, - output wire [USER_WIDTH-1:0] m_axis_tuser, - - /* - * PTP - */ - input wire [PTP_TS_WIDTH-1:0] ptp_ts, - - /* - * Control - */ - input wire clk_enable, - input wire mii_select, - - /* - * Configuration - */ - input wire cfg_rx_enable, - - /* - * Status - */ - output wire start_packet, - output wire error_bad_frame, - output wire error_bad_fcs -); - -// bus width assertions -initial begin - if (DATA_WIDTH != 8) begin - $error("Error: Interface width must be 8"); - $finish; - end -end - -localparam [7:0] - ETH_PRE = 8'h55, - ETH_SFD = 8'hD5; - -localparam [2:0] - STATE_IDLE = 3'd0, - STATE_PAYLOAD = 3'd1, - STATE_WAIT_LAST = 3'd2; - -reg [2:0] state_reg = STATE_IDLE, state_next; - -// datapath control signals -reg reset_crc; -reg update_crc; - -reg mii_odd = 1'b0; -reg in_frame = 1'b0; - -reg [DATA_WIDTH-1:0] gmii_rxd_d0 = {DATA_WIDTH{1'b0}}; -reg [DATA_WIDTH-1:0] gmii_rxd_d1 = {DATA_WIDTH{1'b0}}; -reg [DATA_WIDTH-1:0] gmii_rxd_d2 = {DATA_WIDTH{1'b0}}; -reg [DATA_WIDTH-1:0] gmii_rxd_d3 = {DATA_WIDTH{1'b0}}; -reg [DATA_WIDTH-1:0] gmii_rxd_d4 = {DATA_WIDTH{1'b0}}; - -reg gmii_rx_dv_d0 = 1'b0; -reg gmii_rx_dv_d1 = 1'b0; -reg gmii_rx_dv_d2 = 1'b0; -reg gmii_rx_dv_d3 = 1'b0; -reg gmii_rx_dv_d4 = 1'b0; - -reg gmii_rx_er_d0 = 1'b0; -reg gmii_rx_er_d1 = 1'b0; -reg gmii_rx_er_d2 = 1'b0; -reg gmii_rx_er_d3 = 1'b0; -reg gmii_rx_er_d4 = 1'b0; - -reg [DATA_WIDTH-1:0] m_axis_tdata_reg = {DATA_WIDTH{1'b0}}, m_axis_tdata_next; -reg m_axis_tvalid_reg = 1'b0, m_axis_tvalid_next; -reg m_axis_tlast_reg = 1'b0, m_axis_tlast_next; -reg m_axis_tuser_reg = 1'b0, m_axis_tuser_next; - -reg start_packet_int_reg = 1'b0; -reg start_packet_reg = 1'b0; -reg error_bad_frame_reg = 1'b0, error_bad_frame_next; -reg error_bad_fcs_reg = 1'b0, error_bad_fcs_next; - -reg [PTP_TS_WIDTH-1:0] ptp_ts_reg = 0; - -reg [31:0] crc_state = 32'hFFFFFFFF; -wire [31:0] crc_next; - -assign m_axis_tdata = m_axis_tdata_reg; -assign m_axis_tvalid = m_axis_tvalid_reg; -assign m_axis_tlast = m_axis_tlast_reg; -assign m_axis_tuser = PTP_TS_ENABLE ? {ptp_ts_reg, m_axis_tuser_reg} : m_axis_tuser_reg; - -assign start_packet = start_packet_reg; -assign error_bad_frame = error_bad_frame_reg; -assign error_bad_fcs = error_bad_fcs_reg; - -lfsr #( - .LFSR_WIDTH(32), - .LFSR_POLY(32'h4c11db7), - .LFSR_CONFIG("GALOIS"), - .LFSR_FEED_FORWARD(0), - .REVERSE(1), - .DATA_WIDTH(8), - .STYLE("AUTO") -) -eth_crc_8 ( - .data_in(gmii_rxd_d4), - .state_in(crc_state), - .data_out(), - .state_out(crc_next) -); - -always @* begin - state_next = STATE_IDLE; - - reset_crc = 1'b0; - update_crc = 1'b0; - - m_axis_tdata_next = {DATA_WIDTH{1'b0}}; - m_axis_tvalid_next = 1'b0; - m_axis_tlast_next = 1'b0; - m_axis_tuser_next = 1'b0; - - error_bad_frame_next = 1'b0; - error_bad_fcs_next = 1'b0; - - if (!clk_enable) begin - // clock disabled - hold state - state_next = state_reg; - end else if (mii_select && !mii_odd) begin - // MII even cycle - hold state - state_next = state_reg; - end else begin - case (state_reg) - STATE_IDLE: begin - // idle state - wait for packet - reset_crc = 1'b1; - - if (gmii_rx_dv_d4 && !gmii_rx_er_d4 && gmii_rxd_d4 == ETH_SFD && cfg_rx_enable) begin - state_next = STATE_PAYLOAD; - end else begin - state_next = STATE_IDLE; - end - end - STATE_PAYLOAD: begin - // read payload - update_crc = 1'b1; - - m_axis_tdata_next = gmii_rxd_d4; - m_axis_tvalid_next = 1'b1; - - if (gmii_rx_dv_d4 && gmii_rx_er_d4) begin - // error - m_axis_tlast_next = 1'b1; - m_axis_tuser_next = 1'b1; - error_bad_frame_next = 1'b1; - state_next = STATE_WAIT_LAST; - end else if (!gmii_rx_dv) begin - // end of packet - m_axis_tlast_next = 1'b1; - if (gmii_rx_er_d0 || gmii_rx_er_d1 || gmii_rx_er_d2 || gmii_rx_er_d3) begin - // error received in FCS bytes - m_axis_tuser_next = 1'b1; - error_bad_frame_next = 1'b1; - end else if ({gmii_rxd_d0, gmii_rxd_d1, gmii_rxd_d2, gmii_rxd_d3} == ~crc_next) begin - // FCS good - m_axis_tuser_next = 1'b0; - end else begin - // FCS bad - m_axis_tuser_next = 1'b1; - error_bad_frame_next = 1'b1; - error_bad_fcs_next = 1'b1; - end - state_next = STATE_IDLE; - end else begin - state_next = STATE_PAYLOAD; - end - end - STATE_WAIT_LAST: begin - // wait for end of packet - - if (~gmii_rx_dv) begin - state_next = STATE_IDLE; - end else begin - state_next = STATE_WAIT_LAST; - end - end - endcase - end -end - -always @(posedge clk) begin - state_reg <= state_next; - - m_axis_tdata_reg <= m_axis_tdata_next; - m_axis_tvalid_reg <= m_axis_tvalid_next; - m_axis_tlast_reg <= m_axis_tlast_next; - m_axis_tuser_reg <= m_axis_tuser_next; - - start_packet_int_reg <= 1'b0; - start_packet_reg <= 1'b0; - - if (start_packet_int_reg) begin - ptp_ts_reg <= ptp_ts; - start_packet_reg <= 1'b1; - end - - if (clk_enable) begin - if (mii_select) begin - mii_odd <= !mii_odd; - - if (in_frame) begin - in_frame <= gmii_rx_dv; - end else if (gmii_rx_dv && {gmii_rxd[3:0], gmii_rxd_d0[7:4]} == ETH_SFD) begin - in_frame <= 1'b1; - start_packet_int_reg <= 1'b1; - mii_odd <= 1'b1; - end - - gmii_rxd_d0 <= {gmii_rxd[3:0], gmii_rxd_d0[7:4]}; - - if (mii_odd) begin - gmii_rxd_d1 <= gmii_rxd_d0; - gmii_rxd_d2 <= gmii_rxd_d1; - gmii_rxd_d3 <= gmii_rxd_d2; - gmii_rxd_d4 <= gmii_rxd_d3; - - gmii_rx_dv_d0 <= gmii_rx_dv & gmii_rx_dv_d0; - gmii_rx_dv_d1 <= gmii_rx_dv_d0 & gmii_rx_dv; - gmii_rx_dv_d2 <= gmii_rx_dv_d1 & gmii_rx_dv; - gmii_rx_dv_d3 <= gmii_rx_dv_d2 & gmii_rx_dv; - gmii_rx_dv_d4 <= gmii_rx_dv_d3 & gmii_rx_dv; - - gmii_rx_er_d0 <= gmii_rx_er | gmii_rx_er_d0; - gmii_rx_er_d1 <= gmii_rx_er_d0; - gmii_rx_er_d2 <= gmii_rx_er_d1; - gmii_rx_er_d3 <= gmii_rx_er_d2; - gmii_rx_er_d4 <= gmii_rx_er_d3; - end else begin - gmii_rx_dv_d0 <= gmii_rx_dv; - gmii_rx_er_d0 <= gmii_rx_er; - end - end else begin - if (in_frame) begin - in_frame <= gmii_rx_dv; - end else if (gmii_rx_dv && gmii_rxd == ETH_SFD) begin - in_frame <= 1'b1; - start_packet_int_reg <= 1'b1; - end - - gmii_rxd_d0 <= gmii_rxd; - gmii_rxd_d1 <= gmii_rxd_d0; - gmii_rxd_d2 <= gmii_rxd_d1; - gmii_rxd_d3 <= gmii_rxd_d2; - gmii_rxd_d4 <= gmii_rxd_d3; - - gmii_rx_dv_d0 <= gmii_rx_dv; - gmii_rx_dv_d1 <= gmii_rx_dv_d0 & gmii_rx_dv; - gmii_rx_dv_d2 <= gmii_rx_dv_d1 & gmii_rx_dv; - gmii_rx_dv_d3 <= gmii_rx_dv_d2 & gmii_rx_dv; - gmii_rx_dv_d4 <= gmii_rx_dv_d3 & gmii_rx_dv; - - gmii_rx_er_d0 <= gmii_rx_er; - gmii_rx_er_d1 <= gmii_rx_er_d0; - gmii_rx_er_d2 <= gmii_rx_er_d1; - gmii_rx_er_d3 <= gmii_rx_er_d2; - gmii_rx_er_d4 <= gmii_rx_er_d3; - end - end - - if (reset_crc) begin - crc_state <= 32'hFFFFFFFF; - end else if (update_crc) begin - crc_state <= crc_next; - end - - error_bad_frame_reg <= error_bad_frame_next; - error_bad_fcs_reg <= error_bad_fcs_next; - - if (rst) begin - state_reg <= STATE_IDLE; - - m_axis_tvalid_reg <= 1'b0; - - start_packet_int_reg <= 1'b0; - start_packet_reg <= 1'b0; - error_bad_frame_reg <= 1'b0; - error_bad_fcs_reg <= 1'b0; - - in_frame <= 1'b0; - mii_odd <= 1'b0; - - gmii_rx_dv_d0 <= 1'b0; - gmii_rx_dv_d1 <= 1'b0; - gmii_rx_dv_d2 <= 1'b0; - gmii_rx_dv_d3 <= 1'b0; - gmii_rx_dv_d4 <= 1'b0; - end -end - -endmodule - -`resetall diff --git a/src/rvvi/axis_gmii_tx.sv b/src/rvvi/axis_gmii_tx.sv deleted file mode 100644 index f2936039f..000000000 --- a/src/rvvi/axis_gmii_tx.sv +++ /dev/null @@ -1,457 +0,0 @@ -/* - -Copyright (c) 2015-2018 Alex Forencich - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - -*/ - -// Language: Verilog 2001 - -`resetall -`default_nettype none - -/* - * AXI4-Stream GMII frame transmitter (AXI in, GMII out) - */ -module axis_gmii_tx # -( - parameter DATA_WIDTH = 8, - parameter ENABLE_PADDING = 1, - parameter MIN_FRAME_LENGTH = 64, - parameter PTP_TS_ENABLE = 0, - parameter PTP_TS_WIDTH = 96, - parameter PTP_TS_CTRL_IN_TUSER = 0, - parameter PTP_TAG_ENABLE = PTP_TS_ENABLE, - parameter PTP_TAG_WIDTH = 16, - parameter USER_WIDTH = (PTP_TS_ENABLE ? (PTP_TAG_ENABLE ? PTP_TAG_WIDTH : 0) + (PTP_TS_CTRL_IN_TUSER ? 1 : 0) : 0) + 1 -) -( - input wire clk, - input wire rst, - - /* - * AXI input - */ - input wire [DATA_WIDTH-1:0] s_axis_tdata, - input wire s_axis_tvalid, - output wire s_axis_tready, - input wire s_axis_tlast, - input wire [USER_WIDTH-1:0] s_axis_tuser, - - /* - * GMII output - */ - output wire [DATA_WIDTH-1:0] gmii_txd, - output wire gmii_tx_en, - output wire gmii_tx_er, - - /* - * PTP - */ - input wire [PTP_TS_WIDTH-1:0] ptp_ts, - output wire [PTP_TS_WIDTH-1:0] m_axis_ptp_ts, - output wire [PTP_TAG_WIDTH-1:0] m_axis_ptp_ts_tag, - output wire m_axis_ptp_ts_valid, - - /* - * Control - */ - input wire clk_enable, - input wire mii_select, - - /* - * Configuration - */ - input wire [7:0] cfg_ifg, - input wire cfg_tx_enable, - - /* - * Status - */ - output wire start_packet, - output wire error_underflow -); - -parameter MIN_LEN_WIDTH = $clog2(MIN_FRAME_LENGTH-4-1+1); - -// bus width assertions -initial begin - if (DATA_WIDTH != 8) begin - $error("Error: Interface width must be 8"); - $finish; - end -end - -localparam [7:0] - ETH_PRE = 8'h55, - ETH_SFD = 8'hD5; - -localparam [2:0] - STATE_IDLE = 3'd0, - STATE_PREAMBLE = 3'd1, - STATE_PAYLOAD = 3'd2, - STATE_LAST = 3'd3, - STATE_PAD = 3'd4, - STATE_FCS = 3'd5, - STATE_IFG = 3'd6; - -reg [2:0] state_reg = STATE_IDLE, state_next; - -// datapath control signals -reg reset_crc; -reg update_crc; - -reg [7:0] s_tdata_reg = 8'd0, s_tdata_next; - -reg mii_odd_reg = 1'b0, mii_odd_next; -reg [3:0] mii_msn_reg = 4'b0, mii_msn_next; - -reg frame_reg = 1'b0, frame_next; -reg frame_error_reg = 1'b0, frame_error_next; -reg [7:0] frame_ptr_reg = 0, frame_ptr_next; -reg [MIN_LEN_WIDTH-1:0] frame_min_count_reg = 0, frame_min_count_next; - -reg [7:0] gmii_txd_reg = 8'd0, gmii_txd_next; -reg gmii_tx_en_reg = 1'b0, gmii_tx_en_next; -reg gmii_tx_er_reg = 1'b0, gmii_tx_er_next; - -reg s_axis_tready_reg = 1'b0, s_axis_tready_next; - -reg [PTP_TS_WIDTH-1:0] m_axis_ptp_ts_reg = 0, m_axis_ptp_ts_next; -reg [PTP_TAG_WIDTH-1:0] m_axis_ptp_ts_tag_reg = 0, m_axis_ptp_ts_tag_next; -reg m_axis_ptp_ts_valid_reg = 1'b0, m_axis_ptp_ts_valid_next; - -reg start_packet_int_reg = 1'b0, start_packet_int_next; -reg start_packet_reg = 1'b0, start_packet_next; -reg error_underflow_reg = 1'b0, error_underflow_next; - -reg [31:0] crc_state = 32'hFFFFFFFF; -wire [31:0] crc_next; - -assign s_axis_tready = s_axis_tready_reg; - -assign gmii_txd = gmii_txd_reg; -assign gmii_tx_en = gmii_tx_en_reg; -assign gmii_tx_er = gmii_tx_er_reg; - -assign m_axis_ptp_ts = PTP_TS_ENABLE ? m_axis_ptp_ts_reg : 0; -assign m_axis_ptp_ts_tag = PTP_TAG_ENABLE ? m_axis_ptp_ts_tag_reg : 0; -assign m_axis_ptp_ts_valid = PTP_TS_ENABLE || PTP_TAG_ENABLE ? m_axis_ptp_ts_valid_reg : 1'b0; - -assign start_packet = start_packet_reg; -assign error_underflow = error_underflow_reg; - -lfsr #( - .LFSR_WIDTH(32), - .LFSR_POLY(32'h4c11db7), - .LFSR_CONFIG("GALOIS"), - .LFSR_FEED_FORWARD(0), - .REVERSE(1), - .DATA_WIDTH(8), - .STYLE("AUTO") -) -eth_crc_8 ( - .data_in(s_tdata_reg), - .state_in(crc_state), - .data_out(), - .state_out(crc_next) -); - -always @* begin - state_next = STATE_IDLE; - - reset_crc = 1'b0; - update_crc = 1'b0; - - mii_odd_next = mii_odd_reg; - mii_msn_next = mii_msn_reg; - - frame_next = frame_reg; - frame_error_next = frame_error_reg; - frame_ptr_next = frame_ptr_reg; - frame_min_count_next = frame_min_count_reg; - - s_axis_tready_next = 1'b0; - - s_tdata_next = s_tdata_reg; - - m_axis_ptp_ts_next = m_axis_ptp_ts_reg; - m_axis_ptp_ts_tag_next = m_axis_ptp_ts_tag_reg; - m_axis_ptp_ts_valid_next = 1'b0; - - if (start_packet_reg && PTP_TS_ENABLE) begin - m_axis_ptp_ts_next = ptp_ts; - if (PTP_TS_CTRL_IN_TUSER) begin - m_axis_ptp_ts_tag_next = s_axis_tuser >> 2; - m_axis_ptp_ts_valid_next = s_axis_tuser[1]; - end else begin - m_axis_ptp_ts_tag_next = s_axis_tuser >> 1; - m_axis_ptp_ts_valid_next = 1'b1; - end - end - - gmii_txd_next = {DATA_WIDTH{1'b0}}; - gmii_tx_en_next = 1'b0; - gmii_tx_er_next = 1'b0; - - start_packet_int_next = start_packet_int_reg; - start_packet_next = 1'b0; - error_underflow_next = 1'b0; - - if (s_axis_tvalid && s_axis_tready) begin - frame_next = !s_axis_tlast; - end - - if (!clk_enable) begin - // clock disabled - hold state and outputs - gmii_txd_next = gmii_txd_reg; - gmii_tx_en_next = gmii_tx_en_reg; - gmii_tx_er_next = gmii_tx_er_reg; - state_next = state_reg; - end else if (mii_select && mii_odd_reg) begin - // MII odd cycle - hold state, output MSN - mii_odd_next = 1'b0; - gmii_txd_next = {4'd0, mii_msn_reg}; - gmii_tx_en_next = gmii_tx_en_reg; - gmii_tx_er_next = gmii_tx_er_reg; - state_next = state_reg; - if (start_packet_int_reg) begin - start_packet_int_next = 1'b0; - start_packet_next = 1'b1; - end - end else begin - case (state_reg) - STATE_IDLE: begin - // idle state - wait for packet - reset_crc = 1'b1; - - mii_odd_next = 1'b0; - frame_ptr_next = 1; - - frame_error_next = 1'b0; - frame_min_count_next = MIN_FRAME_LENGTH-4-1; - - if (s_axis_tvalid && cfg_tx_enable) begin - mii_odd_next = 1'b1; - gmii_txd_next = ETH_PRE; - gmii_tx_en_next = 1'b1; - state_next = STATE_PREAMBLE; - end else begin - state_next = STATE_IDLE; - end - end - STATE_PREAMBLE: begin - // send preamble - reset_crc = 1'b1; - - mii_odd_next = 1'b1; - frame_ptr_next = frame_ptr_reg + 1; - - gmii_txd_next = ETH_PRE; - gmii_tx_en_next = 1'b1; - - if (frame_ptr_reg == 6) begin - s_axis_tready_next = 1'b1; - s_tdata_next = s_axis_tdata; - state_next = STATE_PREAMBLE; - end else if (frame_ptr_reg == 7) begin - // end of preamble; start payload - frame_ptr_next = 0; - if (s_axis_tready_reg) begin - s_axis_tready_next = 1'b1; - s_tdata_next = s_axis_tdata; - end - gmii_txd_next = ETH_SFD; - if (mii_select) begin - start_packet_int_next = 1'b1; - end else begin - start_packet_next = 1'b1; - end - state_next = STATE_PAYLOAD; - end else begin - state_next = STATE_PREAMBLE; - end - end - STATE_PAYLOAD: begin - // send payload - - update_crc = 1'b1; - s_axis_tready_next = 1'b1; - - mii_odd_next = 1'b1; - - if (frame_min_count_reg) begin - frame_min_count_next = frame_min_count_reg - 1; - end - - gmii_txd_next = s_tdata_reg; - gmii_tx_en_next = 1'b1; - - s_tdata_next = s_axis_tdata; - - if (!s_axis_tvalid || s_axis_tlast) begin - s_axis_tready_next = frame_next; // drop frame - frame_error_next = !s_axis_tvalid || s_axis_tuser[0]; - error_underflow_next = !s_axis_tvalid; - - state_next = STATE_LAST; - end else begin - state_next = STATE_PAYLOAD; - end - end - STATE_LAST: begin - // last payload word - - update_crc = 1'b1; - s_axis_tready_next = 1'b0; - - mii_odd_next = 1'b1; - - gmii_txd_next = s_tdata_reg; - gmii_tx_en_next = 1'b1; - - if (ENABLE_PADDING && frame_min_count_reg) begin - frame_min_count_next = frame_min_count_reg - 1; - s_tdata_next = 8'd0; - state_next = STATE_PAD; - end else begin - frame_ptr_next = 0; - state_next = STATE_FCS; - end - end - STATE_PAD: begin - // send padding - s_axis_tready_next = frame_next; // drop frame - - update_crc = 1'b1; - mii_odd_next = 1'b1; - - gmii_txd_next = 8'd0; - gmii_tx_en_next = 1'b1; - - s_tdata_next = 8'd0; - - if (frame_min_count_reg) begin - frame_min_count_next = frame_min_count_reg - 1; - state_next = STATE_PAD; - end else begin - frame_ptr_next = 0; - state_next = STATE_FCS; - end - end - STATE_FCS: begin - // send FCS - s_axis_tready_next = frame_next; // drop frame - - mii_odd_next = 1'b1; - frame_ptr_next = frame_ptr_reg + 1; - - case (frame_ptr_reg) - 2'd0: gmii_txd_next = ~crc_state[7:0]; - 2'd1: gmii_txd_next = ~crc_state[15:8]; - 2'd2: gmii_txd_next = ~crc_state[23:16]; - 2'd3: gmii_txd_next = ~crc_state[31:24]; - endcase - gmii_tx_en_next = 1'b1; - gmii_tx_er_next = frame_error_reg; - - if (frame_ptr_reg < 3) begin - state_next = STATE_FCS; - end else begin - frame_ptr_next = 0; - state_next = STATE_IFG; - end - end - STATE_IFG: begin - // send IFG - s_axis_tready_next = frame_next; // drop frame - - mii_odd_next = 1'b1; - frame_ptr_next = frame_ptr_reg + 1; - - if (frame_ptr_reg < cfg_ifg-1 || frame_reg) begin - state_next = STATE_IFG; - end else begin - state_next = STATE_IDLE; - end - end - endcase - - if (mii_select) begin - mii_msn_next = gmii_txd_next[7:4]; - gmii_txd_next[7:4] = 4'd0; - end - end -end - -always @(posedge clk) begin - state_reg <= state_next; - - frame_reg <= frame_next; - frame_error_reg <= frame_error_next; - frame_ptr_reg <= frame_ptr_next; - frame_min_count_reg <= frame_min_count_next; - - m_axis_ptp_ts_reg <= m_axis_ptp_ts_next; - m_axis_ptp_ts_tag_reg <= m_axis_ptp_ts_tag_next; - m_axis_ptp_ts_valid_reg <= m_axis_ptp_ts_valid_next; - - mii_odd_reg <= mii_odd_next; - mii_msn_reg <= mii_msn_next; - - s_tdata_reg <= s_tdata_next; - - s_axis_tready_reg <= s_axis_tready_next; - - gmii_txd_reg <= gmii_txd_next; - gmii_tx_en_reg <= gmii_tx_en_next; - gmii_tx_er_reg <= gmii_tx_er_next; - - if (reset_crc) begin - crc_state <= 32'hFFFFFFFF; - end else if (update_crc) begin - crc_state <= crc_next; - end - - start_packet_int_reg <= start_packet_int_next; - start_packet_reg <= start_packet_next; - error_underflow_reg <= error_underflow_next; - - if (rst) begin - state_reg <= STATE_IDLE; - - frame_reg <= 1'b0; - - s_axis_tready_reg <= 1'b0; - - m_axis_ptp_ts_valid_reg <= 1'b0; - - gmii_tx_en_reg <= 1'b0; - gmii_tx_er_reg <= 1'b0; - - start_packet_int_reg <= 1'b0; - start_packet_reg <= 1'b0; - error_underflow_reg <= 1'b0; - end -end - -endmodule - -`resetall diff --git a/src/rvvi/eth_axis_tx.sv b/src/rvvi/eth_axis_tx.sv deleted file mode 100644 index b4287b281..000000000 --- a/src/rvvi/eth_axis_tx.sv +++ /dev/null @@ -1,408 +0,0 @@ -/* - -Copyright (c) 2014-2020 Alex Forencich - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - -*/ - -// Language: Verilog 2001 - -`resetall -`default_nettype none - -/* - * AXI4-Stream ethernet frame transmitter (Ethernet frame in, AXI out) - */ -module eth_axis_tx # -( - // Width of AXI stream interfaces in bits - parameter DATA_WIDTH = 8, - // Propagate tkeep signal - // If disabled, tkeep assumed to be 1'b1 - parameter KEEP_ENABLE = (DATA_WIDTH>8), - // tkeep signal width (words per cycle) - parameter KEEP_WIDTH = (DATA_WIDTH/8) -) -( - input wire clk, - input wire rst, - - /* - * Ethernet frame input - */ - input wire s_eth_hdr_valid, - output wire s_eth_hdr_ready, - input wire [47:0] s_eth_dest_mac, - input wire [47:0] s_eth_src_mac, - input wire [15:0] s_eth_type, - input wire [DATA_WIDTH-1:0] s_eth_payload_axis_tdata, - input wire [KEEP_WIDTH-1:0] s_eth_payload_axis_tkeep, - input wire s_eth_payload_axis_tvalid, - output wire s_eth_payload_axis_tready, - input wire s_eth_payload_axis_tlast, - input wire s_eth_payload_axis_tuser, - - /* - * AXI output - */ - output wire [DATA_WIDTH-1:0] m_axis_tdata, - output wire [KEEP_WIDTH-1:0] m_axis_tkeep, - output wire m_axis_tvalid, - input wire m_axis_tready, - output wire m_axis_tlast, - output wire m_axis_tuser, - - /* - * Status signals - */ - output wire busy -); - -parameter BYTE_LANES = KEEP_ENABLE ? KEEP_WIDTH : 1; - -parameter HDR_SIZE = 14; - -parameter CYCLE_COUNT = (HDR_SIZE+BYTE_LANES-1)/BYTE_LANES; - -parameter PTR_WIDTH = $clog2(CYCLE_COUNT); - -parameter OFFSET = HDR_SIZE % BYTE_LANES; - -// bus width assertions -initial begin - if (BYTE_LANES * 8 != DATA_WIDTH) begin - $error("Error: AXI stream interface requires byte (8-bit) granularity (instance %m)"); - $finish; - end -end - -/* - -Ethernet frame - - Field Length - Destination MAC address 6 octets - Source MAC address 6 octets - Ethertype 2 octets - -This module receives an Ethernet frame with header fields in parallel along -with the payload in an AXI stream, combines the header with the payload, and -transmits the complete Ethernet frame on the output AXI stream interface. - -*/ - -// datapath control signals -reg store_eth_hdr; - -reg send_eth_header_reg = 1'b0, send_eth_header_next; -reg send_eth_payload_reg = 1'b0, send_eth_payload_next; -reg [PTR_WIDTH-1:0] ptr_reg = 0, ptr_next; - -reg flush_save; -reg transfer_in_save; - -reg [47:0] eth_dest_mac_reg = 48'd0; -reg [47:0] eth_src_mac_reg = 48'd0; -reg [15:0] eth_type_reg = 16'd0; - -reg s_eth_hdr_ready_reg = 1'b0, s_eth_hdr_ready_next; -reg s_eth_payload_axis_tready_reg = 1'b0, s_eth_payload_axis_tready_next; - -reg busy_reg = 1'b0; - -reg [DATA_WIDTH-1:0] save_eth_payload_axis_tdata_reg = {DATA_WIDTH{1'b0}}; -reg [KEEP_WIDTH-1:0] save_eth_payload_axis_tkeep_reg = {KEEP_WIDTH{1'b0}}; -reg save_eth_payload_axis_tlast_reg = 1'b0; -reg save_eth_payload_axis_tuser_reg = 1'b0; - -reg [DATA_WIDTH-1:0] shift_eth_payload_axis_tdata; -reg [KEEP_WIDTH-1:0] shift_eth_payload_axis_tkeep; -reg shift_eth_payload_axis_tvalid; -reg shift_eth_payload_axis_tlast; -reg shift_eth_payload_axis_tuser; -reg shift_eth_payload_axis_input_tready; -reg shift_eth_payload_axis_extra_cycle_reg = 1'b0; - -// internal datapath -reg [DATA_WIDTH-1:0] m_axis_tdata_int; -reg [KEEP_WIDTH-1:0] m_axis_tkeep_int; -reg m_axis_tvalid_int; -reg m_axis_tready_int_reg = 1'b0; -reg m_axis_tlast_int; -reg m_axis_tuser_int; -wire m_axis_tready_int_early; - -assign s_eth_hdr_ready = s_eth_hdr_ready_reg; -assign s_eth_payload_axis_tready = s_eth_payload_axis_tready_reg; - -assign busy = busy_reg; - -always @* begin - if (OFFSET == 0) begin - // passthrough if no overlap - shift_eth_payload_axis_tdata = s_eth_payload_axis_tdata; - shift_eth_payload_axis_tkeep = s_eth_payload_axis_tkeep; - shift_eth_payload_axis_tvalid = s_eth_payload_axis_tvalid; - shift_eth_payload_axis_tlast = s_eth_payload_axis_tlast; - shift_eth_payload_axis_tuser = s_eth_payload_axis_tuser; - shift_eth_payload_axis_input_tready = 1'b1; - end else if (shift_eth_payload_axis_extra_cycle_reg) begin - shift_eth_payload_axis_tdata = {s_eth_payload_axis_tdata, save_eth_payload_axis_tdata_reg} >> ((KEEP_WIDTH-OFFSET)*8); - shift_eth_payload_axis_tkeep = {{KEEP_WIDTH{1'b0}}, save_eth_payload_axis_tkeep_reg} >> (KEEP_WIDTH-OFFSET); - shift_eth_payload_axis_tvalid = 1'b1; - shift_eth_payload_axis_tlast = save_eth_payload_axis_tlast_reg; - shift_eth_payload_axis_tuser = save_eth_payload_axis_tuser_reg; - shift_eth_payload_axis_input_tready = flush_save; - end else begin - shift_eth_payload_axis_tdata = {s_eth_payload_axis_tdata, save_eth_payload_axis_tdata_reg} >> ((KEEP_WIDTH-OFFSET)*8); - shift_eth_payload_axis_tkeep = {s_eth_payload_axis_tkeep, save_eth_payload_axis_tkeep_reg} >> (KEEP_WIDTH-OFFSET); - shift_eth_payload_axis_tvalid = s_eth_payload_axis_tvalid; - shift_eth_payload_axis_tlast = (s_eth_payload_axis_tlast && ((s_eth_payload_axis_tkeep & ({KEEP_WIDTH{1'b1}} << (KEEP_WIDTH-OFFSET))) == 0)); - shift_eth_payload_axis_tuser = (s_eth_payload_axis_tuser && ((s_eth_payload_axis_tkeep & ({KEEP_WIDTH{1'b1}} << (KEEP_WIDTH-OFFSET))) == 0)); - shift_eth_payload_axis_input_tready = !(s_eth_payload_axis_tlast && s_eth_payload_axis_tready && s_eth_payload_axis_tvalid); - end -end - -always @* begin - send_eth_header_next = send_eth_header_reg; - send_eth_payload_next = send_eth_payload_reg; - ptr_next = ptr_reg; - - s_eth_hdr_ready_next = 1'b0; - s_eth_payload_axis_tready_next = 1'b0; - - store_eth_hdr = 1'b0; - - flush_save = 1'b0; - transfer_in_save = 1'b0; - - m_axis_tdata_int = {DATA_WIDTH{1'b0}}; - m_axis_tkeep_int = {KEEP_WIDTH{1'b0}}; - m_axis_tvalid_int = 1'b0; - m_axis_tlast_int = 1'b0; - m_axis_tuser_int = 1'b0; - - if (s_eth_hdr_ready && s_eth_hdr_valid) begin - store_eth_hdr = 1'b1; - ptr_next = 0; - send_eth_header_next = 1'b1; - send_eth_payload_next = (OFFSET != 0) && (CYCLE_COUNT == 1); - s_eth_payload_axis_tready_next = send_eth_payload_next && m_axis_tready_int_early; - end - - if (send_eth_payload_reg) begin - s_eth_payload_axis_tready_next = m_axis_tready_int_early && shift_eth_payload_axis_input_tready; - - m_axis_tdata_int = shift_eth_payload_axis_tdata; - m_axis_tkeep_int = shift_eth_payload_axis_tkeep; - m_axis_tlast_int = shift_eth_payload_axis_tlast; - m_axis_tuser_int = shift_eth_payload_axis_tuser; - - if ((s_eth_payload_axis_tready && s_eth_payload_axis_tvalid) || (m_axis_tready_int_reg && shift_eth_payload_axis_extra_cycle_reg)) begin - transfer_in_save = 1'b1; - - m_axis_tvalid_int = 1'b1; - - if (shift_eth_payload_axis_tlast) begin - flush_save = 1'b1; - s_eth_payload_axis_tready_next = 1'b0; - ptr_next = 0; - send_eth_payload_next = 1'b0; - end - end - end - - if (m_axis_tready_int_reg && (!OFFSET || !send_eth_payload_reg || m_axis_tvalid_int)) begin - if (send_eth_header_reg) begin - ptr_next = ptr_reg + 1; - - if ((OFFSET != 0) && (CYCLE_COUNT == 1 || ptr_next == CYCLE_COUNT-1) && !send_eth_payload_reg) begin - send_eth_payload_next = 1'b1; - s_eth_payload_axis_tready_next = m_axis_tready_int_early && shift_eth_payload_axis_input_tready; - end - - m_axis_tvalid_int = 1'b1; - - `define _HEADER_FIELD_(offset, field) \ - if (ptr_reg == offset/BYTE_LANES) begin \ - m_axis_tdata_int[(offset%BYTE_LANES)*8 +: 8] = field; \ - m_axis_tkeep_int[offset%BYTE_LANES] = 1'b1; \ - end - - `_HEADER_FIELD_(0, eth_dest_mac_reg[5*8 +: 8]) - `_HEADER_FIELD_(1, eth_dest_mac_reg[4*8 +: 8]) - `_HEADER_FIELD_(2, eth_dest_mac_reg[3*8 +: 8]) - `_HEADER_FIELD_(3, eth_dest_mac_reg[2*8 +: 8]) - `_HEADER_FIELD_(4, eth_dest_mac_reg[1*8 +: 8]) - `_HEADER_FIELD_(5, eth_dest_mac_reg[0*8 +: 8]) - `_HEADER_FIELD_(6, eth_src_mac_reg[5*8 +: 8]) - `_HEADER_FIELD_(7, eth_src_mac_reg[4*8 +: 8]) - `_HEADER_FIELD_(8, eth_src_mac_reg[3*8 +: 8]) - `_HEADER_FIELD_(9, eth_src_mac_reg[2*8 +: 8]) - `_HEADER_FIELD_(10, eth_src_mac_reg[1*8 +: 8]) - `_HEADER_FIELD_(11, eth_src_mac_reg[0*8 +: 8]) - `_HEADER_FIELD_(12, eth_type_reg[1*8 +: 8]) - `_HEADER_FIELD_(13, eth_type_reg[0*8 +: 8]) - - if (ptr_reg == 13/BYTE_LANES) begin - if (!send_eth_payload_reg) begin - s_eth_payload_axis_tready_next = m_axis_tready_int_early; - send_eth_payload_next = 1'b1; - end - send_eth_header_next = 1'b0; - end - - `undef _HEADER_FIELD_ - end - end - - s_eth_hdr_ready_next = !(send_eth_header_next || send_eth_payload_next); -end - -always @(posedge clk) begin - send_eth_header_reg <= send_eth_header_next; - send_eth_payload_reg <= send_eth_payload_next; - ptr_reg <= ptr_next; - - s_eth_hdr_ready_reg <= s_eth_hdr_ready_next; - s_eth_payload_axis_tready_reg <= s_eth_payload_axis_tready_next; - - busy_reg <= send_eth_header_next || send_eth_payload_next; - - if (store_eth_hdr) begin - eth_dest_mac_reg <= s_eth_dest_mac; - eth_src_mac_reg <= s_eth_src_mac; - eth_type_reg <= s_eth_type; - end - - if (transfer_in_save) begin - save_eth_payload_axis_tdata_reg <= s_eth_payload_axis_tdata; - save_eth_payload_axis_tkeep_reg <= s_eth_payload_axis_tkeep; - save_eth_payload_axis_tuser_reg <= s_eth_payload_axis_tuser; - end - - if (flush_save) begin - save_eth_payload_axis_tlast_reg <= 1'b0; - shift_eth_payload_axis_extra_cycle_reg <= 1'b0; - end else if (transfer_in_save) begin - save_eth_payload_axis_tlast_reg <= s_eth_payload_axis_tlast; - shift_eth_payload_axis_extra_cycle_reg <= OFFSET ? s_eth_payload_axis_tlast && ((s_eth_payload_axis_tkeep & ({KEEP_WIDTH{1'b1}} << (KEEP_WIDTH-OFFSET))) != 0) : 1'b0; - end - - if (rst) begin - send_eth_header_reg <= 1'b0; - send_eth_payload_reg <= 1'b0; - ptr_reg <= 0; - s_eth_hdr_ready_reg <= 1'b0; - s_eth_payload_axis_tready_reg <= 1'b0; - busy_reg <= 1'b0; - end -end - -// output datapath logic -reg [DATA_WIDTH-1:0] m_axis_tdata_reg = {DATA_WIDTH{1'b0}}; -reg [KEEP_WIDTH-1:0] m_axis_tkeep_reg = {KEEP_WIDTH{1'b0}}; -reg m_axis_tvalid_reg = 1'b0, m_axis_tvalid_next; -reg m_axis_tlast_reg = 1'b0; -reg m_axis_tuser_reg = 1'b0; - -reg [DATA_WIDTH-1:0] temp_m_axis_tdata_reg = {DATA_WIDTH{1'b0}}; -reg [KEEP_WIDTH-1:0] temp_m_axis_tkeep_reg = {KEEP_WIDTH{1'b0}}; -reg temp_m_axis_tvalid_reg = 1'b0, temp_m_axis_tvalid_next; -reg temp_m_axis_tlast_reg = 1'b0; -reg temp_m_axis_tuser_reg = 1'b0; - -// datapath control -reg store_axis_int_to_output; -reg store_axis_int_to_temp; -reg store_axis_temp_to_output; - -assign m_axis_tdata = m_axis_tdata_reg; -assign m_axis_tkeep = KEEP_ENABLE ? m_axis_tkeep_reg : {KEEP_WIDTH{1'b1}}; -assign m_axis_tvalid = m_axis_tvalid_reg; -assign m_axis_tlast = m_axis_tlast_reg; -assign m_axis_tuser = m_axis_tuser_reg; - -// enable ready input next cycle if output is ready or if both output registers are empty -assign m_axis_tready_int_early = m_axis_tready || (!temp_m_axis_tvalid_reg && !m_axis_tvalid_reg); - -always @* begin - // transfer sink ready state to source - m_axis_tvalid_next = m_axis_tvalid_reg; - temp_m_axis_tvalid_next = temp_m_axis_tvalid_reg; - - store_axis_int_to_output = 1'b0; - store_axis_int_to_temp = 1'b0; - store_axis_temp_to_output = 1'b0; - - if (m_axis_tready_int_reg) begin - // input is ready - if (m_axis_tready || !m_axis_tvalid_reg) begin - // output is ready or currently not valid, transfer data to output - m_axis_tvalid_next = m_axis_tvalid_int; - store_axis_int_to_output = 1'b1; - end else begin - // output is not ready, store input in temp - temp_m_axis_tvalid_next = m_axis_tvalid_int; - store_axis_int_to_temp = 1'b1; - end - end else if (m_axis_tready) begin - // input is not ready, but output is ready - m_axis_tvalid_next = temp_m_axis_tvalid_reg; - temp_m_axis_tvalid_next = 1'b0; - store_axis_temp_to_output = 1'b1; - end -end - -always @(posedge clk) begin - m_axis_tvalid_reg <= m_axis_tvalid_next; - m_axis_tready_int_reg <= m_axis_tready_int_early; - temp_m_axis_tvalid_reg <= temp_m_axis_tvalid_next; - - // datapath - if (store_axis_int_to_output) begin - m_axis_tdata_reg <= m_axis_tdata_int; - m_axis_tkeep_reg <= m_axis_tkeep_int; - m_axis_tlast_reg <= m_axis_tlast_int; - m_axis_tuser_reg <= m_axis_tuser_int; - end else if (store_axis_temp_to_output) begin - m_axis_tdata_reg <= temp_m_axis_tdata_reg; - m_axis_tkeep_reg <= temp_m_axis_tkeep_reg; - m_axis_tlast_reg <= temp_m_axis_tlast_reg; - m_axis_tuser_reg <= temp_m_axis_tuser_reg; - end - - if (store_axis_int_to_temp) begin - temp_m_axis_tdata_reg <= m_axis_tdata_int; - temp_m_axis_tkeep_reg <= m_axis_tkeep_int; - temp_m_axis_tlast_reg <= m_axis_tlast_int; - temp_m_axis_tuser_reg <= m_axis_tuser_int; - end - - if (rst) begin - m_axis_tvalid_reg <= 1'b0; - m_axis_tready_int_reg <= 1'b0; - temp_m_axis_tvalid_reg <= 1'b0; - end -end - -endmodule - -`resetall diff --git a/src/rvvi/eth_mac_1g.sv b/src/rvvi/eth_mac_1g.sv deleted file mode 100644 index 6e0592fac..000000000 --- a/src/rvvi/eth_mac_1g.sv +++ /dev/null @@ -1,643 +0,0 @@ -/* - -Copyright (c) 2015-2023 Alex Forencich - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - -*/ - -// Language: Verilog 2001 - -`resetall -`default_nettype none - -/* - * 1G Ethernet MAC - */ -module eth_mac_1g # -( - parameter DATA_WIDTH = 8, - parameter ENABLE_PADDING = 1, - parameter MIN_FRAME_LENGTH = 64, - parameter PTP_TS_ENABLE = 0, - parameter PTP_TS_FMT_TOD = 1, - parameter PTP_TS_WIDTH = PTP_TS_FMT_TOD ? 96 : 64, - parameter TX_PTP_TS_CTRL_IN_TUSER = 0, - parameter TX_PTP_TAG_ENABLE = PTP_TS_ENABLE, - parameter TX_PTP_TAG_WIDTH = 16, - parameter TX_USER_WIDTH = (PTP_TS_ENABLE ? (TX_PTP_TAG_ENABLE ? TX_PTP_TAG_WIDTH : 0) + (TX_PTP_TS_CTRL_IN_TUSER ? 1 : 0) : 0) + 1, - parameter RX_USER_WIDTH = (PTP_TS_ENABLE ? PTP_TS_WIDTH : 0) + 1, - parameter PFC_ENABLE = 0, - parameter PAUSE_ENABLE = PFC_ENABLE -) -( - input wire rx_clk, - input wire rx_rst, - input wire tx_clk, - input wire tx_rst, - - /* - * AXI input - */ - input wire [DATA_WIDTH-1:0] tx_axis_tdata, - input wire tx_axis_tvalid, - output wire tx_axis_tready, - input wire tx_axis_tlast, - input wire [TX_USER_WIDTH-1:0] tx_axis_tuser, - - /* - * AXI output - */ - output wire [DATA_WIDTH-1:0] rx_axis_tdata, - output wire rx_axis_tvalid, - output wire rx_axis_tlast, - output wire [RX_USER_WIDTH-1:0] rx_axis_tuser, - - /* - * GMII interface - */ - input wire [DATA_WIDTH-1:0] gmii_rxd, - input wire gmii_rx_dv, - input wire gmii_rx_er, - output wire [DATA_WIDTH-1:0] gmii_txd, - output wire gmii_tx_en, - output wire gmii_tx_er, - - /* - * PTP - */ - input wire [PTP_TS_WIDTH-1:0] tx_ptp_ts, - input wire [PTP_TS_WIDTH-1:0] rx_ptp_ts, - output wire [PTP_TS_WIDTH-1:0] tx_axis_ptp_ts, - output wire [TX_PTP_TAG_WIDTH-1:0] tx_axis_ptp_ts_tag, - output wire tx_axis_ptp_ts_valid, - - /* - * Link-level Flow Control (LFC) (IEEE 802.3 annex 31B PAUSE) - */ - input wire tx_lfc_req, - input wire tx_lfc_resend, - input wire rx_lfc_en, - output wire rx_lfc_req, - input wire rx_lfc_ack, - - /* - * Priority Flow Control (PFC) (IEEE 802.3 annex 31D PFC) - */ - input wire [7:0] tx_pfc_req, - input wire tx_pfc_resend, - input wire [7:0] rx_pfc_en, - output wire [7:0] rx_pfc_req, - input wire [7:0] rx_pfc_ack, - - /* - * Pause interface - */ - input wire tx_lfc_pause_en, - input wire tx_pause_req, - output wire tx_pause_ack, - - /* - * Control - */ - input wire rx_clk_enable, - input wire tx_clk_enable, - input wire rx_mii_select, - input wire tx_mii_select, - - /* - * Status - */ - output wire tx_start_packet, - output wire tx_error_underflow, - output wire rx_start_packet, - output wire rx_error_bad_frame, - output wire rx_error_bad_fcs, - output wire stat_tx_mcf, - output wire stat_rx_mcf, - output wire stat_tx_lfc_pkt, - output wire stat_tx_lfc_xon, - output wire stat_tx_lfc_xoff, - output wire stat_tx_lfc_paused, - output wire stat_tx_pfc_pkt, - output wire [7:0] stat_tx_pfc_xon, - output wire [7:0] stat_tx_pfc_xoff, - output wire [7:0] stat_tx_pfc_paused, - output wire stat_rx_lfc_pkt, - output wire stat_rx_lfc_xon, - output wire stat_rx_lfc_xoff, - output wire stat_rx_lfc_paused, - output wire stat_rx_pfc_pkt, - output wire [7:0] stat_rx_pfc_xon, - output wire [7:0] stat_rx_pfc_xoff, - output wire [7:0] stat_rx_pfc_paused, - - /* - * Configuration - */ - input wire [7:0] cfg_ifg, - input wire cfg_tx_enable, - input wire cfg_rx_enable, - input wire [47:0] cfg_mcf_rx_eth_dst_mcast, - input wire cfg_mcf_rx_check_eth_dst_mcast, - input wire [47:0] cfg_mcf_rx_eth_dst_ucast, - input wire cfg_mcf_rx_check_eth_dst_ucast, - input wire [47:0] cfg_mcf_rx_eth_src, - input wire cfg_mcf_rx_check_eth_src, - input wire [15:0] cfg_mcf_rx_eth_type, - input wire [15:0] cfg_mcf_rx_opcode_lfc, - input wire cfg_mcf_rx_check_opcode_lfc, - input wire [15:0] cfg_mcf_rx_opcode_pfc, - input wire cfg_mcf_rx_check_opcode_pfc, - input wire cfg_mcf_rx_forward, - input wire cfg_mcf_rx_enable, - input wire [47:0] cfg_tx_lfc_eth_dst, - input wire [47:0] cfg_tx_lfc_eth_src, - input wire [15:0] cfg_tx_lfc_eth_type, - input wire [15:0] cfg_tx_lfc_opcode, - input wire cfg_tx_lfc_en, - input wire [15:0] cfg_tx_lfc_quanta, - input wire [15:0] cfg_tx_lfc_refresh, - input wire [47:0] cfg_tx_pfc_eth_dst, - input wire [47:0] cfg_tx_pfc_eth_src, - input wire [15:0] cfg_tx_pfc_eth_type, - input wire [15:0] cfg_tx_pfc_opcode, - input wire cfg_tx_pfc_en, - input wire [8*16-1:0] cfg_tx_pfc_quanta, - input wire [8*16-1:0] cfg_tx_pfc_refresh, - input wire [15:0] cfg_rx_lfc_opcode, - input wire cfg_rx_lfc_en, - input wire [15:0] cfg_rx_pfc_opcode, - input wire cfg_rx_pfc_en -); - -parameter MAC_CTRL_ENABLE = PAUSE_ENABLE || PFC_ENABLE; -parameter TX_USER_WIDTH_INT = MAC_CTRL_ENABLE ? (PTP_TS_ENABLE ? (TX_PTP_TAG_ENABLE ? TX_PTP_TAG_WIDTH : 0) + 1 : 0) + 1 : TX_USER_WIDTH; - -wire [DATA_WIDTH-1:0] tx_axis_tdata_int; -wire tx_axis_tvalid_int; -wire tx_axis_tready_int; -wire tx_axis_tlast_int; -wire [TX_USER_WIDTH_INT-1:0] tx_axis_tuser_int; - -wire [DATA_WIDTH-1:0] rx_axis_tdata_int; -wire rx_axis_tvalid_int; -wire rx_axis_tlast_int; -wire [RX_USER_WIDTH-1:0] rx_axis_tuser_int; - -axis_gmii_rx #( - .DATA_WIDTH(DATA_WIDTH), - .PTP_TS_ENABLE(PTP_TS_ENABLE), - .PTP_TS_WIDTH(PTP_TS_WIDTH), - .USER_WIDTH(RX_USER_WIDTH) -) -axis_gmii_rx_inst ( - .clk(rx_clk), - .rst(rx_rst), - .gmii_rxd(gmii_rxd), - .gmii_rx_dv(gmii_rx_dv), - .gmii_rx_er(gmii_rx_er), - .m_axis_tdata(rx_axis_tdata_int), - .m_axis_tvalid(rx_axis_tvalid_int), - .m_axis_tlast(rx_axis_tlast_int), - .m_axis_tuser(rx_axis_tuser_int), - .ptp_ts(rx_ptp_ts), - .clk_enable(rx_clk_enable), - .mii_select(rx_mii_select), - .cfg_rx_enable(cfg_rx_enable), - .start_packet(rx_start_packet), - .error_bad_frame(rx_error_bad_frame), - .error_bad_fcs(rx_error_bad_fcs) -); - -axis_gmii_tx #( - .DATA_WIDTH(DATA_WIDTH), - .ENABLE_PADDING(ENABLE_PADDING), - .MIN_FRAME_LENGTH(MIN_FRAME_LENGTH), - .PTP_TS_ENABLE(PTP_TS_ENABLE), - .PTP_TS_WIDTH(PTP_TS_WIDTH), - .PTP_TS_CTRL_IN_TUSER(MAC_CTRL_ENABLE ? PTP_TS_ENABLE : TX_PTP_TS_CTRL_IN_TUSER), - .PTP_TAG_ENABLE(TX_PTP_TAG_ENABLE), - .PTP_TAG_WIDTH(TX_PTP_TAG_WIDTH), - .USER_WIDTH(TX_USER_WIDTH_INT) -) -axis_gmii_tx_inst ( - .clk(tx_clk), - .rst(tx_rst), - .s_axis_tdata(tx_axis_tdata_int), - .s_axis_tvalid(tx_axis_tvalid_int), - .s_axis_tready(tx_axis_tready_int), - .s_axis_tlast(tx_axis_tlast_int), - .s_axis_tuser(tx_axis_tuser_int), - .gmii_txd(gmii_txd), - .gmii_tx_en(gmii_tx_en), - .gmii_tx_er(gmii_tx_er), - .ptp_ts(tx_ptp_ts), - .m_axis_ptp_ts(tx_axis_ptp_ts), - .m_axis_ptp_ts_tag(tx_axis_ptp_ts_tag), - .m_axis_ptp_ts_valid(tx_axis_ptp_ts_valid), - .clk_enable(tx_clk_enable), - .mii_select(tx_mii_select), - .cfg_ifg(cfg_ifg), - .cfg_tx_enable(cfg_tx_enable), - .start_packet(tx_start_packet), - .error_underflow(tx_error_underflow) -); - -generate - -if (MAC_CTRL_ENABLE) begin : mac_ctrl - - localparam MCF_PARAMS_SIZE = PFC_ENABLE ? 18 : 2; - - wire tx_mcf_valid; - wire tx_mcf_ready; - wire [47:0] tx_mcf_eth_dst; - wire [47:0] tx_mcf_eth_src; - wire [15:0] tx_mcf_eth_type; - wire [15:0] tx_mcf_opcode; - wire [MCF_PARAMS_SIZE*8-1:0] tx_mcf_params; - - wire rx_mcf_valid; - wire [47:0] rx_mcf_eth_dst; - wire [47:0] rx_mcf_eth_src; - wire [15:0] rx_mcf_eth_type; - wire [15:0] rx_mcf_opcode; - wire [MCF_PARAMS_SIZE*8-1:0] rx_mcf_params; - - // terminate LFC pause requests from RX internally on TX side - wire tx_pause_req_int; - wire rx_lfc_ack_int; - - reg tx_lfc_req_sync_reg_1 = 1'b0; - reg tx_lfc_req_sync_reg_2 = 1'b0; - reg tx_lfc_req_sync_reg_3 = 1'b0; - - always @(posedge rx_clk or posedge rx_rst) begin - if (rx_rst) begin - tx_lfc_req_sync_reg_1 <= 1'b0; - end else begin - tx_lfc_req_sync_reg_1 <= rx_lfc_req; - end - end - - always @(posedge tx_clk or posedge tx_rst) begin - if (tx_rst) begin - tx_lfc_req_sync_reg_2 <= 1'b0; - tx_lfc_req_sync_reg_3 <= 1'b0; - end else begin - tx_lfc_req_sync_reg_2 <= tx_lfc_req_sync_reg_1; - tx_lfc_req_sync_reg_3 <= tx_lfc_req_sync_reg_2; - end - end - - reg rx_lfc_ack_sync_reg_1 = 1'b0; - reg rx_lfc_ack_sync_reg_2 = 1'b0; - reg rx_lfc_ack_sync_reg_3 = 1'b0; - - always @(posedge tx_clk or posedge tx_rst) begin - if (tx_rst) begin - rx_lfc_ack_sync_reg_1 <= 1'b0; - end else begin - rx_lfc_ack_sync_reg_1 <= tx_lfc_pause_en ? tx_pause_ack : 0; - end - end - - always @(posedge rx_clk or posedge rx_rst) begin - if (rx_rst) begin - rx_lfc_ack_sync_reg_2 <= 1'b0; - rx_lfc_ack_sync_reg_3 <= 1'b0; - end else begin - rx_lfc_ack_sync_reg_2 <= rx_lfc_ack_sync_reg_1; - rx_lfc_ack_sync_reg_3 <= rx_lfc_ack_sync_reg_2; - end - end - - assign tx_pause_req_int = tx_pause_req || (tx_lfc_pause_en ? tx_lfc_req_sync_reg_3 : 0); - - assign rx_lfc_ack_int = rx_lfc_ack || rx_lfc_ack_sync_reg_3; - - // handle PTP TS enable bit in tuser - wire [TX_USER_WIDTH_INT-1:0] tx_axis_tuser_in; - - if (PTP_TS_ENABLE && !TX_PTP_TS_CTRL_IN_TUSER) begin - assign tx_axis_tuser_in = {tx_axis_tuser[TX_USER_WIDTH-1:1], 1'b1, tx_axis_tuser[0]}; - end else begin - assign tx_axis_tuser_in = tx_axis_tuser; - end - - mac_ctrl_tx #( - .DATA_WIDTH(DATA_WIDTH), - .KEEP_ENABLE(0), - .ID_ENABLE(0), - .DEST_ENABLE(0), - .USER_ENABLE(1), - .USER_WIDTH(TX_USER_WIDTH_INT), - .MCF_PARAMS_SIZE(MCF_PARAMS_SIZE) - ) - mac_ctrl_tx_inst ( - .clk(tx_clk), - .rst(tx_rst), - - /* - * AXI stream input - */ - .s_axis_tdata(tx_axis_tdata), - .s_axis_tkeep(1'b1), - .s_axis_tvalid(tx_axis_tvalid), - .s_axis_tready(tx_axis_tready), - .s_axis_tlast(tx_axis_tlast), - .s_axis_tid(0), - .s_axis_tdest(0), - .s_axis_tuser(tx_axis_tuser_in), - - /* - * AXI stream output - */ - .m_axis_tdata(tx_axis_tdata_int), - .m_axis_tkeep(), - .m_axis_tvalid(tx_axis_tvalid_int), - .m_axis_tready(tx_axis_tready_int), - .m_axis_tlast(tx_axis_tlast_int), - .m_axis_tid(), - .m_axis_tdest(), - .m_axis_tuser(tx_axis_tuser_int), - - /* - * MAC control frame interface - */ - .mcf_valid(tx_mcf_valid), - .mcf_ready(tx_mcf_ready), - .mcf_eth_dst(tx_mcf_eth_dst), - .mcf_eth_src(tx_mcf_eth_src), - .mcf_eth_type(tx_mcf_eth_type), - .mcf_opcode(tx_mcf_opcode), - .mcf_params(tx_mcf_params), - .mcf_id(0), - .mcf_dest(0), - .mcf_user(0), - - /* - * Pause interface - */ - .tx_pause_req(tx_pause_req_int), - .tx_pause_ack(tx_pause_ack), - - /* - * Status - */ - .stat_tx_mcf(stat_tx_mcf) - ); - - mac_ctrl_rx #( - .DATA_WIDTH(DATA_WIDTH), - .KEEP_ENABLE(0), - .ID_ENABLE(0), - .DEST_ENABLE(0), - .USER_ENABLE(1), - .USER_WIDTH(RX_USER_WIDTH), - .USE_READY(0), - .MCF_PARAMS_SIZE(MCF_PARAMS_SIZE) - ) - mac_ctrl_rx_inst ( - .clk(rx_clk), - .rst(rx_rst), - - /* - * AXI stream input - */ - .s_axis_tdata(rx_axis_tdata_int), - .s_axis_tkeep(1'b1), - .s_axis_tvalid(rx_axis_tvalid_int), - .s_axis_tready(), - .s_axis_tlast(rx_axis_tlast_int), - .s_axis_tid(0), - .s_axis_tdest(0), - .s_axis_tuser(rx_axis_tuser_int), - - /* - * AXI stream output - */ - .m_axis_tdata(rx_axis_tdata), - .m_axis_tkeep(), - .m_axis_tvalid(rx_axis_tvalid), - .m_axis_tready(1'b1), - .m_axis_tlast(rx_axis_tlast), - .m_axis_tid(), - .m_axis_tdest(), - .m_axis_tuser(rx_axis_tuser), - - /* - * MAC control frame interface - */ - .mcf_valid(rx_mcf_valid), - .mcf_eth_dst(rx_mcf_eth_dst), - .mcf_eth_src(rx_mcf_eth_src), - .mcf_eth_type(rx_mcf_eth_type), - .mcf_opcode(rx_mcf_opcode), - .mcf_params(rx_mcf_params), - .mcf_id(), - .mcf_dest(), - .mcf_user(), - - /* - * Configuration - */ - .cfg_mcf_rx_eth_dst_mcast(cfg_mcf_rx_eth_dst_mcast), - .cfg_mcf_rx_check_eth_dst_mcast(cfg_mcf_rx_check_eth_dst_mcast), - .cfg_mcf_rx_eth_dst_ucast(cfg_mcf_rx_eth_dst_ucast), - .cfg_mcf_rx_check_eth_dst_ucast(cfg_mcf_rx_check_eth_dst_ucast), - .cfg_mcf_rx_eth_src(cfg_mcf_rx_eth_src), - .cfg_mcf_rx_check_eth_src(cfg_mcf_rx_check_eth_src), - .cfg_mcf_rx_eth_type(cfg_mcf_rx_eth_type), - .cfg_mcf_rx_opcode_lfc(cfg_mcf_rx_opcode_lfc), - .cfg_mcf_rx_check_opcode_lfc(cfg_mcf_rx_check_opcode_lfc), - .cfg_mcf_rx_opcode_pfc(cfg_mcf_rx_opcode_pfc), - .cfg_mcf_rx_check_opcode_pfc(cfg_mcf_rx_check_opcode_pfc), - .cfg_mcf_rx_forward(cfg_mcf_rx_forward), - .cfg_mcf_rx_enable(cfg_mcf_rx_enable), - - /* - * Status - */ - .stat_rx_mcf(stat_rx_mcf) - ); - - mac_pause_ctrl_tx #( - .MCF_PARAMS_SIZE(MCF_PARAMS_SIZE), - .PFC_ENABLE(PFC_ENABLE) - ) - mac_pause_ctrl_tx_inst ( - .clk(tx_clk), - .rst(tx_rst), - - /* - * MAC control frame interface - */ - .mcf_valid(tx_mcf_valid), - .mcf_ready(tx_mcf_ready), - .mcf_eth_dst(tx_mcf_eth_dst), - .mcf_eth_src(tx_mcf_eth_src), - .mcf_eth_type(tx_mcf_eth_type), - .mcf_opcode(tx_mcf_opcode), - .mcf_params(tx_mcf_params), - - /* - * Pause (IEEE 802.3 annex 31B) - */ - .tx_lfc_req(tx_lfc_req), - .tx_lfc_resend(tx_lfc_resend), - - /* - * Priority Flow Control (PFC) (IEEE 802.3 annex 31D) - */ - .tx_pfc_req(tx_pfc_req), - .tx_pfc_resend(tx_pfc_resend), - - /* - * Configuration - */ - .cfg_tx_lfc_eth_dst(cfg_tx_lfc_eth_dst), - .cfg_tx_lfc_eth_src(cfg_tx_lfc_eth_src), - .cfg_tx_lfc_eth_type(cfg_tx_lfc_eth_type), - .cfg_tx_lfc_opcode(cfg_tx_lfc_opcode), - .cfg_tx_lfc_en(cfg_tx_lfc_en), - .cfg_tx_lfc_quanta(cfg_tx_lfc_quanta), - .cfg_tx_lfc_refresh(cfg_tx_lfc_refresh), - .cfg_tx_pfc_eth_dst(cfg_tx_pfc_eth_dst), - .cfg_tx_pfc_eth_src(cfg_tx_pfc_eth_src), - .cfg_tx_pfc_eth_type(cfg_tx_pfc_eth_type), - .cfg_tx_pfc_opcode(cfg_tx_pfc_opcode), - .cfg_tx_pfc_en(cfg_tx_pfc_en), - .cfg_tx_pfc_quanta(cfg_tx_pfc_quanta), - .cfg_tx_pfc_refresh(cfg_tx_pfc_refresh), - .cfg_quanta_step(tx_mii_select ? (4*256)/512 : (8*256)/512), - .cfg_quanta_clk_en(tx_clk_enable), - - /* - * Status - */ - .stat_tx_lfc_pkt(stat_tx_lfc_pkt), - .stat_tx_lfc_xon(stat_tx_lfc_xon), - .stat_tx_lfc_xoff(stat_tx_lfc_xoff), - .stat_tx_lfc_paused(stat_tx_lfc_paused), - .stat_tx_pfc_pkt(stat_tx_pfc_pkt), - .stat_tx_pfc_xon(stat_tx_pfc_xon), - .stat_tx_pfc_xoff(stat_tx_pfc_xoff), - .stat_tx_pfc_paused(stat_tx_pfc_paused) - ); - - mac_pause_ctrl_rx #( - .MCF_PARAMS_SIZE(18), - .PFC_ENABLE(PFC_ENABLE) - ) - mac_pause_ctrl_rx_inst ( - .clk(rx_clk), - .rst(rx_rst), - - /* - * MAC control frame interface - */ - .mcf_valid(rx_mcf_valid), - .mcf_eth_dst(rx_mcf_eth_dst), - .mcf_eth_src(rx_mcf_eth_src), - .mcf_eth_type(rx_mcf_eth_type), - .mcf_opcode(rx_mcf_opcode), - .mcf_params(rx_mcf_params), - - /* - * Pause (IEEE 802.3 annex 31B) - */ - .rx_lfc_en(rx_lfc_en), - .rx_lfc_req(rx_lfc_req), - .rx_lfc_ack(rx_lfc_ack_int), - - /* - * Priority Flow Control (PFC) (IEEE 802.3 annex 31D) - */ - .rx_pfc_en(rx_pfc_en), - .rx_pfc_req(rx_pfc_req), - .rx_pfc_ack(rx_pfc_ack), - - /* - * Configuration - */ - .cfg_rx_lfc_opcode(cfg_rx_lfc_opcode), - .cfg_rx_lfc_en(cfg_rx_lfc_en), - .cfg_rx_pfc_opcode(cfg_rx_pfc_opcode), - .cfg_rx_pfc_en(cfg_rx_pfc_en), - .cfg_quanta_step(rx_mii_select ? (4*256)/512 : (8*256)/512), - .cfg_quanta_clk_en(rx_clk_enable), - - /* - * Status - */ - .stat_rx_lfc_pkt(stat_rx_lfc_pkt), - .stat_rx_lfc_xon(stat_rx_lfc_xon), - .stat_rx_lfc_xoff(stat_rx_lfc_xoff), - .stat_rx_lfc_paused(stat_rx_lfc_paused), - .stat_rx_pfc_pkt(stat_rx_pfc_pkt), - .stat_rx_pfc_xon(stat_rx_pfc_xon), - .stat_rx_pfc_xoff(stat_rx_pfc_xoff), - .stat_rx_pfc_paused(stat_rx_pfc_paused) - ); - -end else begin - - assign tx_axis_tdata_int = tx_axis_tdata; - assign tx_axis_tvalid_int = tx_axis_tvalid; - assign tx_axis_tready = tx_axis_tready_int; - assign tx_axis_tlast_int = tx_axis_tlast; - assign tx_axis_tuser_int = tx_axis_tuser; - - assign rx_axis_tdata = rx_axis_tdata_int; - assign rx_axis_tvalid = rx_axis_tvalid_int; - assign rx_axis_tlast = rx_axis_tlast_int; - assign rx_axis_tuser = rx_axis_tuser_int; - - assign rx_lfc_req = 0; - assign rx_pfc_req = 0; - assign tx_pause_ack = 0; - - assign stat_tx_mcf = 0; - assign stat_rx_mcf = 0; - assign stat_tx_lfc_pkt = 0; - assign stat_tx_lfc_xon = 0; - assign stat_tx_lfc_xoff = 0; - assign stat_tx_lfc_paused = 0; - assign stat_tx_pfc_pkt = 0; - assign stat_tx_pfc_xon = 0; - assign stat_tx_pfc_xoff = 0; - assign stat_tx_pfc_paused = 0; - assign stat_rx_lfc_pkt = 0; - assign stat_rx_lfc_xon = 0; - assign stat_rx_lfc_xoff = 0; - assign stat_rx_lfc_paused = 0; - assign stat_rx_pfc_pkt = 0; - assign stat_rx_pfc_xon = 0; - assign stat_rx_pfc_xoff = 0; - assign stat_rx_pfc_paused = 0; - -end - -endgenerate - -endmodule - -`resetall diff --git a/src/rvvi/eth_mac_mii.sv b/src/rvvi/eth_mac_mii.sv deleted file mode 100644 index 212f4b84a..000000000 --- a/src/rvvi/eth_mac_mii.sv +++ /dev/null @@ -1,175 +0,0 @@ -/* - -Copyright (c) 2019 Alex Forencich - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - -*/ - -// Language: Verilog 2001 - -`resetall -`default_nettype none - -/* - * 10M/100M Ethernet MAC with MII interface - */ -module eth_mac_mii # -( - // target ("SIM", "GENERIC", "XILINX", "ALTERA") - parameter TARGET = "GENERIC", - // Clock input style ("BUFG", "BUFR", "BUFIO", "BUFIO2") - // Use BUFR for Virtex-5, Virtex-6, 7-series - // Use BUFG for Ultrascale - // Use BUFIO2 for Spartan-6 - parameter CLOCK_INPUT_STYLE = "BUFIO2", - parameter ENABLE_PADDING = 1, - parameter MIN_FRAME_LENGTH = 64 -) -( - input wire rst, - output wire rx_clk, - output wire rx_rst, - output wire tx_clk, - output wire tx_rst, - - /* - * AXI input - */ - input wire [7:0] tx_axis_tdata, - input wire tx_axis_tvalid, - output wire tx_axis_tready, - input wire tx_axis_tlast, - input wire tx_axis_tuser, - - /* - * AXI output - */ - output wire [7:0] rx_axis_tdata, - output wire rx_axis_tvalid, - output wire rx_axis_tlast, - output wire rx_axis_tuser, - - /* - * MII interface - */ - input wire mii_rx_clk, - input wire [3:0] mii_rxd, - input wire mii_rx_dv, - input wire mii_rx_er, - input wire mii_tx_clk, - output wire [3:0] mii_txd, - output wire mii_tx_en, - output wire mii_tx_er, - - /* - * Status - */ - output wire tx_start_packet, - output wire tx_error_underflow, - output wire rx_start_packet, - output wire rx_error_bad_frame, - output wire rx_error_bad_fcs, - - /* - * Configuration - */ - input wire [7:0] cfg_ifg, - input wire cfg_tx_enable, - input wire cfg_rx_enable -); - -wire [3:0] mac_mii_rxd; -wire mac_mii_rx_dv; -wire mac_mii_rx_er; -wire [3:0] mac_mii_txd; -wire mac_mii_tx_en; -wire mac_mii_tx_er; - -mii_phy_if #( - .TARGET(TARGET), - .CLOCK_INPUT_STYLE(CLOCK_INPUT_STYLE) -) -mii_phy_if_inst ( - .rst(rst), - - .mac_mii_rx_clk(rx_clk), - .mac_mii_rx_rst(rx_rst), - .mac_mii_rxd(mac_mii_rxd), - .mac_mii_rx_dv(mac_mii_rx_dv), - .mac_mii_rx_er(mac_mii_rx_er), - .mac_mii_tx_clk(tx_clk), - .mac_mii_tx_rst(tx_rst), - .mac_mii_txd(mac_mii_txd), - .mac_mii_tx_en(mac_mii_tx_en), - .mac_mii_tx_er(mac_mii_tx_er), - - .phy_mii_rx_clk(mii_rx_clk), - .phy_mii_rxd(mii_rxd), - .phy_mii_rx_dv(mii_rx_dv), - .phy_mii_rx_er(mii_rx_er), - .phy_mii_tx_clk(mii_tx_clk), - .phy_mii_txd(mii_txd), - .phy_mii_tx_en(mii_tx_en), - .phy_mii_tx_er(mii_tx_er) -); - // *** there a bunch of missing pins -/* verilator lint_off PINMISSING */ -eth_mac_1g #( - .ENABLE_PADDING(ENABLE_PADDING), - .MIN_FRAME_LENGTH(MIN_FRAME_LENGTH) -) -eth_mac_1g_inst ( - .tx_clk(tx_clk), - .tx_rst(tx_rst), - .rx_clk(rx_clk), - .rx_rst(rx_rst), - .tx_axis_tdata(tx_axis_tdata), - .tx_axis_tvalid(tx_axis_tvalid), - .tx_axis_tready(tx_axis_tready), - .tx_axis_tlast(tx_axis_tlast), - .tx_axis_tuser(tx_axis_tuser), - .rx_axis_tdata(rx_axis_tdata), - .rx_axis_tvalid(rx_axis_tvalid), - .rx_axis_tlast(rx_axis_tlast), - .rx_axis_tuser(rx_axis_tuser), - .gmii_rxd(mac_mii_rxd), - .gmii_rx_dv(mac_mii_rx_dv), - .gmii_rx_er(mac_mii_rx_er), - .gmii_txd(mac_mii_txd), - .gmii_tx_en(mac_mii_tx_en), - .gmii_tx_er(mac_mii_tx_er), - .rx_clk_enable(1'b1), - .tx_clk_enable(1'b1), - .rx_mii_select(1'b1), - .tx_mii_select(1'b1), - .tx_start_packet(tx_start_packet), - .tx_error_underflow(tx_error_underflow), - .rx_start_packet(rx_start_packet), - .rx_error_bad_frame(rx_error_bad_frame), - .rx_error_bad_fcs(rx_error_bad_fcs), - .cfg_ifg(cfg_ifg), - .cfg_tx_enable(cfg_tx_enable), - .cfg_rx_enable(cfg_rx_enable) -); -/* verilator lint_on PINMISSING */ - -endmodule - -`resetall diff --git a/src/rvvi/eth_mac_mii_fifo.sv b/src/rvvi/eth_mac_mii_fifo.sv deleted file mode 100644 index a285ceeed..000000000 --- a/src/rvvi/eth_mac_mii_fifo.sv +++ /dev/null @@ -1,339 +0,0 @@ -/* - -Copyright (c) 2019 Alex Forencich - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - -*/ - -// Language: Verilog 2001 - -`resetall -`default_nettype none - -/* - * 10M/100M Ethernet MAC with MII interface and TX and RX FIFOs - */ -module eth_mac_mii_fifo # -( - // target ("SIM", "GENERIC", "XILINX", "ALTERA") - parameter TARGET = "GENERIC", - // Clock input style ("BUFG", "BUFR", "BUFIO", "BUFIO2") - // Use BUFR for Virtex-5, Virtex-6, 7-series - // Use BUFG for Ultrascale - // Use BUFIO2 for Spartan-6 - parameter CLOCK_INPUT_STYLE = "BUFIO2", - parameter AXIS_DATA_WIDTH = 8, - parameter AXIS_KEEP_ENABLE = (AXIS_DATA_WIDTH>8), - parameter AXIS_KEEP_WIDTH = (AXIS_DATA_WIDTH/8), - parameter ENABLE_PADDING = 1, - parameter MIN_FRAME_LENGTH = 64, - parameter TX_FIFO_DEPTH = 4096, - parameter TX_FIFO_RAM_PIPELINE = 1, - parameter TX_FRAME_FIFO = 1, - parameter TX_DROP_OVERSIZE_FRAME = TX_FRAME_FIFO, - parameter TX_DROP_BAD_FRAME = TX_DROP_OVERSIZE_FRAME, - parameter TX_DROP_WHEN_FULL = 0, - parameter RX_FIFO_DEPTH = 4096, - parameter RX_FIFO_RAM_PIPELINE = 1, - parameter RX_FRAME_FIFO = 1, - parameter RX_DROP_OVERSIZE_FRAME = RX_FRAME_FIFO, - parameter RX_DROP_BAD_FRAME = RX_DROP_OVERSIZE_FRAME, - parameter RX_DROP_WHEN_FULL = RX_DROP_OVERSIZE_FRAME -) -( - input wire rst, - input wire logic_clk, - input wire logic_rst, - - /* - * AXI input - */ - input wire [AXIS_DATA_WIDTH-1:0] tx_axis_tdata, - input wire [AXIS_KEEP_WIDTH-1:0] tx_axis_tkeep, - input wire tx_axis_tvalid, - output wire tx_axis_tready, - input wire tx_axis_tlast, - input wire tx_axis_tuser, - - /* - * AXI output - */ - output wire [AXIS_DATA_WIDTH-1:0] rx_axis_tdata, - output wire [AXIS_KEEP_WIDTH-1:0] rx_axis_tkeep, - output wire rx_axis_tvalid, - input wire rx_axis_tready, - output wire rx_axis_tlast, - output wire rx_axis_tuser, - - /* - * MII interface - */ - input wire mii_rx_clk, - input wire [3:0] mii_rxd, - input wire mii_rx_dv, - input wire mii_rx_er, - input wire mii_tx_clk, - output wire [3:0] mii_txd, - output wire mii_tx_en, - output wire mii_tx_er, - - /* - * Status - */ - output wire tx_error_underflow, - output wire tx_fifo_overflow, - output wire tx_fifo_bad_frame, - output wire tx_fifo_good_frame, - output wire rx_error_bad_frame, - output wire rx_error_bad_fcs, - output wire rx_fifo_overflow, - output wire rx_fifo_bad_frame, - output wire rx_fifo_good_frame, - - /* - * Configuration - */ - input wire [7:0] cfg_ifg, - input wire cfg_tx_enable, - input wire cfg_rx_enable -); - -wire tx_clk; -wire rx_clk; -wire tx_rst; -wire rx_rst; - -wire [7:0] tx_fifo_axis_tdata; -wire tx_fifo_axis_tvalid; -wire tx_fifo_axis_tready; -wire tx_fifo_axis_tlast; -wire tx_fifo_axis_tuser; - -wire [7:0] rx_fifo_axis_tdata; -wire rx_fifo_axis_tvalid; -wire rx_fifo_axis_tlast; -wire rx_fifo_axis_tuser; - -// synchronize MAC status signals into logic clock domain -wire tx_error_underflow_int; - -reg [0:0] tx_sync_reg_1 = 1'b0; -reg [0:0] tx_sync_reg_2 = 1'b0; -reg [0:0] tx_sync_reg_3 = 1'b0; -reg [0:0] tx_sync_reg_4 = 1'b0; - -assign tx_error_underflow = tx_sync_reg_3[0] ^ tx_sync_reg_4[0]; - -always @(posedge tx_clk or posedge tx_rst) begin - if (tx_rst) begin - tx_sync_reg_1 <= 1'b0; - end else begin - tx_sync_reg_1 <= tx_sync_reg_1 ^ {tx_error_underflow_int}; - end -end - -always @(posedge logic_clk or posedge logic_rst) begin - if (logic_rst) begin - tx_sync_reg_2 <= 1'b0; - tx_sync_reg_3 <= 1'b0; - tx_sync_reg_4 <= 1'b0; - end else begin - tx_sync_reg_2 <= tx_sync_reg_1; - tx_sync_reg_3 <= tx_sync_reg_2; - tx_sync_reg_4 <= tx_sync_reg_3; - end -end - -wire rx_error_bad_frame_int; -wire rx_error_bad_fcs_int; - -reg [1:0] rx_sync_reg_1 = 2'd0; -reg [1:0] rx_sync_reg_2 = 2'd0; -reg [1:0] rx_sync_reg_3 = 2'd0; -reg [1:0] rx_sync_reg_4 = 2'd0; - -assign rx_error_bad_frame = rx_sync_reg_3[0] ^ rx_sync_reg_4[0]; -assign rx_error_bad_fcs = rx_sync_reg_3[1] ^ rx_sync_reg_4[1]; - -always @(posedge rx_clk or posedge rx_rst) begin - if (rx_rst) begin - rx_sync_reg_1 <= 2'd0; - end else begin - rx_sync_reg_1 <= rx_sync_reg_1 ^ {rx_error_bad_fcs_int, rx_error_bad_frame_int}; - end -end - -always @(posedge logic_clk or posedge logic_rst) begin - if (logic_rst) begin - rx_sync_reg_2 <= 2'd0; - rx_sync_reg_3 <= 2'd0; - rx_sync_reg_4 <= 2'd0; - end else begin - rx_sync_reg_2 <= rx_sync_reg_1; - rx_sync_reg_3 <= rx_sync_reg_2; - rx_sync_reg_4 <= rx_sync_reg_3; - end -end - - // *** there are a bunch of missing pins - /* verilator lint_off PINMISSING */ -eth_mac_mii #( - .TARGET(TARGET), - .CLOCK_INPUT_STYLE(CLOCK_INPUT_STYLE), - .ENABLE_PADDING(ENABLE_PADDING), - .MIN_FRAME_LENGTH(MIN_FRAME_LENGTH) -) -eth_mac_1g_mii_inst ( - .rst(rst), - .tx_clk(tx_clk), - .tx_rst(tx_rst), - .rx_clk(rx_clk), - .rx_rst(rx_rst), - .tx_axis_tdata(tx_fifo_axis_tdata), - .tx_axis_tvalid(tx_fifo_axis_tvalid), - .tx_axis_tready(tx_fifo_axis_tready), - .tx_axis_tlast(tx_fifo_axis_tlast), - .tx_axis_tuser(tx_fifo_axis_tuser), - .rx_axis_tdata(rx_fifo_axis_tdata), - .rx_axis_tvalid(rx_fifo_axis_tvalid), - .rx_axis_tlast(rx_fifo_axis_tlast), - .rx_axis_tuser(rx_fifo_axis_tuser), - .mii_rx_clk(mii_rx_clk), - .mii_rxd(mii_rxd), - .mii_rx_dv(mii_rx_dv), - .mii_rx_er(mii_rx_er), - .mii_tx_clk(mii_tx_clk), - .mii_txd(mii_txd), - .mii_tx_en(mii_tx_en), - .mii_tx_er(mii_tx_er), - .tx_error_underflow(tx_error_underflow_int), - .rx_error_bad_frame(rx_error_bad_frame_int), - .rx_error_bad_fcs(rx_error_bad_fcs_int), - .cfg_ifg(cfg_ifg), - .cfg_tx_enable(cfg_tx_enable), - .cfg_rx_enable(cfg_rx_enable) -); - -axis_async_fifo_adapter #( - .DEPTH(TX_FIFO_DEPTH), - .S_DATA_WIDTH(AXIS_DATA_WIDTH), - .S_KEEP_ENABLE(AXIS_KEEP_ENABLE), - .S_KEEP_WIDTH(AXIS_KEEP_WIDTH), - .M_DATA_WIDTH(8), - .M_KEEP_ENABLE(0), - .ID_ENABLE(0), - .DEST_ENABLE(0), - .USER_ENABLE(1), - .USER_WIDTH(1), - .RAM_PIPELINE(TX_FIFO_RAM_PIPELINE), - .FRAME_FIFO(TX_FRAME_FIFO), - .USER_BAD_FRAME_VALUE(1'b1), - .USER_BAD_FRAME_MASK(1'b1), - .DROP_OVERSIZE_FRAME(TX_DROP_OVERSIZE_FRAME), - .DROP_BAD_FRAME(TX_DROP_BAD_FRAME), - .DROP_WHEN_FULL(TX_DROP_WHEN_FULL) -) -tx_fifo ( - // AXI input - .s_clk(logic_clk), - .s_rst(logic_rst), - .s_axis_tdata(tx_axis_tdata), - .s_axis_tkeep(tx_axis_tkeep), - .s_axis_tvalid(tx_axis_tvalid), - .s_axis_tready(tx_axis_tready), - .s_axis_tlast(tx_axis_tlast), - .s_axis_tid(0), - .s_axis_tdest(0), - .s_axis_tuser(tx_axis_tuser), - // AXI output - .m_clk(tx_clk), - .m_rst(tx_rst), - .m_axis_tdata(tx_fifo_axis_tdata), - .m_axis_tkeep(), - .m_axis_tvalid(tx_fifo_axis_tvalid), - .m_axis_tready(tx_fifo_axis_tready), - .m_axis_tlast(tx_fifo_axis_tlast), - .m_axis_tid(), - .m_axis_tdest(), - .m_axis_tuser(tx_fifo_axis_tuser), - // Status - .s_status_overflow(tx_fifo_overflow), - .s_status_bad_frame(tx_fifo_bad_frame), - .s_status_good_frame(tx_fifo_good_frame), - .m_status_overflow(), - .m_status_bad_frame(), - .m_status_good_frame() -); - -axis_async_fifo_adapter #( - .DEPTH(RX_FIFO_DEPTH), - .S_DATA_WIDTH(8), - .S_KEEP_ENABLE(0), - .M_DATA_WIDTH(AXIS_DATA_WIDTH), - .M_KEEP_ENABLE(AXIS_KEEP_ENABLE), - .M_KEEP_WIDTH(AXIS_KEEP_WIDTH), - .ID_ENABLE(0), - .DEST_ENABLE(0), - .USER_ENABLE(1), - .USER_WIDTH(1), - .RAM_PIPELINE(RX_FIFO_RAM_PIPELINE), - .FRAME_FIFO(RX_FRAME_FIFO), - .USER_BAD_FRAME_VALUE(1'b1), - .USER_BAD_FRAME_MASK(1'b1), - .DROP_OVERSIZE_FRAME(RX_DROP_OVERSIZE_FRAME), - .DROP_BAD_FRAME(RX_DROP_BAD_FRAME), - .DROP_WHEN_FULL(RX_DROP_WHEN_FULL) -) -rx_fifo ( - // AXI input - .s_clk(rx_clk), - .s_rst(rx_rst), - .s_axis_tdata(rx_fifo_axis_tdata), - .s_axis_tkeep(0), - .s_axis_tvalid(rx_fifo_axis_tvalid), - .s_axis_tready(), - .s_axis_tlast(rx_fifo_axis_tlast), - .s_axis_tid(0), - .s_axis_tdest(0), - .s_axis_tuser(rx_fifo_axis_tuser), - // AXI output - .m_clk(logic_clk), - .m_rst(logic_rst), - .m_axis_tdata(rx_axis_tdata), - .m_axis_tkeep(rx_axis_tkeep), - .m_axis_tvalid(rx_axis_tvalid), - .m_axis_tready(rx_axis_tready), - .m_axis_tlast(rx_axis_tlast), - .m_axis_tid(), - .m_axis_tdest(), - .m_axis_tuser(rx_axis_tuser), - // Status - .s_status_overflow(), - .s_status_bad_frame(), - .s_status_good_frame(), - .m_status_overflow(rx_fifo_overflow), - .m_status_bad_frame(rx_fifo_bad_frame), - .m_status_good_frame(rx_fifo_good_frame) -); -/* verilator lint_on PINMISSING */ - -endmodule - -`resetall diff --git a/src/rvvi/lfsr.sv b/src/rvvi/lfsr.sv deleted file mode 100644 index 4b404fe94..000000000 --- a/src/rvvi/lfsr.sv +++ /dev/null @@ -1,446 +0,0 @@ -/* - -Copyright (c) 2016-2023 Alex Forencich - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - -*/ - -// Language: Verilog 2001 - -`resetall -`default_nettype none - -/* - * Parametrizable combinatorial parallel LFSR/CRC - */ -module lfsr # -( - // width of LFSR - parameter LFSR_WIDTH = 31, - // LFSR polynomial - parameter LFSR_POLY = 31'h10000001, - // LFSR configuration: "GALOIS", "FIBONACCI" - parameter LFSR_CONFIG = "FIBONACCI", - // LFSR feed forward enable - parameter LFSR_FEED_FORWARD = 0, - // bit-reverse input and output - parameter REVERSE = 0, - // width of data input - parameter DATA_WIDTH = 8, - // implementation style: "AUTO", "LOOP", "REDUCTION" - parameter STYLE = "AUTO" -) -( - input wire [DATA_WIDTH-1:0] data_in, - input wire [LFSR_WIDTH-1:0] state_in, - output wire [DATA_WIDTH-1:0] data_out, - output wire [LFSR_WIDTH-1:0] state_out -); - -/* - -Fully parametrizable combinatorial parallel LFSR/CRC module. Implements an unrolled LFSR -next state computation, shifting DATA_WIDTH bits per pass through the module. Input data -is XORed with LFSR feedback path, tie data_in to zero if this is not required. - -Works in two parts: statically computes a set of bit masks, then uses these bit masks to -select bits for XORing to compute the next state. - -Ports: - -data_in - -Data bits to be shifted through the LFSR (DATA_WIDTH bits) - -state_in - -LFSR/CRC current state input (LFSR_WIDTH bits) - -data_out - -Data bits shifted out of LFSR (DATA_WIDTH bits) - -state_out - -LFSR/CRC next state output (LFSR_WIDTH bits) - -Parameters: - -LFSR_WIDTH - -Specify width of LFSR/CRC register - -LFSR_POLY - -Specify the LFSR/CRC polynomial in hex format. For example, the polynomial - -x^32 + x^26 + x^23 + x^22 + x^16 + x^12 + x^11 + x^10 + x^8 + x^7 + x^5 + x^4 + x^2 + x + 1 - -would be represented as - -32'h04c11db7 - -Note that the largest term (x^32) is suppressed. This term is generated automatically based -on LFSR_WIDTH. - -LFSR_CONFIG - -Specify the LFSR configuration, either Fibonacci or Galois. Fibonacci is generally used -for linear-feedback shift registers (LFSR) for pseudorandom binary sequence (PRBS) generators, -scramblers, and descrambers, while Galois is generally used for cyclic redundancy check -generators and checkers. - -Fibonacci style (example for 64b66b scrambler, 0x8000000001) - - DIN (LSB first) - | - V - (+)<---------------------------(+)<-----------------------------. - | ^ | - | .----. .----. .----. | .----. .----. .----. | - +->| 0 |->| 1 |->...->| 38 |-+->| 39 |->...->| 56 |->| 57 |--' - | '----' '----' '----' '----' '----' '----' - V - DOUT - -Galois style (example for CRC16, 0x8005) - - ,-------------------+-------------------------+----------(+)<-- DIN (MSB first) - | | | ^ - | .----. .----. V .----. .----. V .----. | - `->| 0 |->| 1 |->(+)->| 2 |->...->| 14 |->(+)->| 15 |--+---> DOUT - '----' '----' '----' '----' '----' - -LFSR_FEED_FORWARD - -Generate feed forward instead of feed back LFSR. Enable this for PRBS checking and self- -synchronous descrambling. - -Fibonacci feed-forward style (example for 64b66b descrambler, 0x8000000001) - - DIN (LSB first) - | - | .----. .----. .----. .----. .----. .----. - +->| 0 |->| 1 |->...->| 38 |-+->| 39 |->...->| 56 |->| 57 |--. - | '----' '----' '----' | '----' '----' '----' | - | V | - (+)<---------------------------(+)------------------------------' - | - V - DOUT - -Galois feed-forward style - - ,-------------------+-------------------------+------------+--- DIN (MSB first) - | | | | - | .----. .----. V .----. .----. V .----. V - `->| 0 |->| 1 |->(+)->| 2 |->...->| 14 |->(+)->| 15 |->(+)-> DOUT - '----' '----' '----' '----' '----' - -REVERSE - -Bit-reverse LFSR input and output. Shifts MSB first by default, set REVERSE for LSB first. - -DATA_WIDTH - -Specify width of input and output data bus. The module will perform one shift per input -data bit, so if the input data bus is not required tie data_in to zero and set DATA_WIDTH -to the required number of shifts per clock cycle. - -STYLE - -Specify implementation style. Can be "AUTO", "LOOP", or "REDUCTION". When "AUTO" -is selected, implemenation will be "LOOP" or "REDUCTION" based on synthesis translate -directives. "REDUCTION" and "LOOP" are functionally identical, however they simulate -and synthesize differently. "REDUCTION" is implemented with a loop over a Verilog -reduction operator. "LOOP" is implemented as a doubly-nested loop with no reduction -operator. "REDUCTION" is very fast for simulation in iverilog and synthesizes well in -Quartus but synthesizes poorly in ISE, likely due to large inferred XOR gates causing -problems with the optimizer. "LOOP" synthesizes will in both ISE and Quartus. "AUTO" -will default to "REDUCTION" when simulating and "LOOP" for synthesizers that obey -synthesis translate directives. - -Settings for common LFSR/CRC implementations: - -Name Configuration Length Polynomial Initial value Notes -CRC16-IBM Galois, bit-reverse 16 16'h8005 16'hffff -CRC16-CCITT Galois 16 16'h1021 16'h1d0f -CRC32 Galois, bit-reverse 32 32'h04c11db7 32'hffffffff Ethernet FCS; invert final output -CRC32C Galois, bit-reverse 32 32'h1edc6f41 32'hffffffff iSCSI, Intel CRC32 instruction; invert final output -PRBS6 Fibonacci 6 6'h21 any -PRBS7 Fibonacci 7 7'h41 any -PRBS9 Fibonacci 9 9'h021 any ITU V.52 -PRBS10 Fibonacci 10 10'h081 any ITU -PRBS11 Fibonacci 11 11'h201 any ITU O.152 -PRBS15 Fibonacci, inverted 15 15'h4001 any ITU O.152 -PRBS17 Fibonacci 17 17'h04001 any -PRBS20 Fibonacci 20 20'h00009 any ITU V.57 -PRBS23 Fibonacci, inverted 23 23'h040001 any ITU O.151 -PRBS29 Fibonacci, inverted 29 29'h08000001 any -PRBS31 Fibonacci, inverted 31 31'h10000001 any -64b66b Fibonacci, bit-reverse 58 58'h8000000001 any 10G Ethernet -128b130b Galois, bit-reverse 23 23'h210125 any PCIe gen 3 - -*/ - -function [LFSR_WIDTH+DATA_WIDTH-1:0] lfsr_mask(input [31:0] index); - reg [LFSR_WIDTH-1:0] lfsr_mask_state[LFSR_WIDTH-1:0]; - reg [DATA_WIDTH-1:0] lfsr_mask_data[LFSR_WIDTH-1:0]; - reg [LFSR_WIDTH-1:0] output_mask_state[DATA_WIDTH-1:0]; - reg [DATA_WIDTH-1:0] output_mask_data[DATA_WIDTH-1:0]; - - reg [LFSR_WIDTH-1:0] state_val; - reg [DATA_WIDTH-1:0] data_val; - - reg [DATA_WIDTH-1:0] data_mask; - - integer i, j; - - begin - // init bit masks - for (i = 0; i < LFSR_WIDTH; i = i + 1) begin - lfsr_mask_state[i] = 0; - lfsr_mask_state[i][i] = 1'b1; - lfsr_mask_data[i] = 0; - end - for (i = 0; i < DATA_WIDTH; i = i + 1) begin - output_mask_state[i] = 0; - if (i < LFSR_WIDTH) begin - output_mask_state[i][i] = 1'b1; - end - output_mask_data[i] = 0; - end - - // simulate shift register - if (LFSR_CONFIG == "FIBONACCI") begin - // Fibonacci configuration - for (data_mask = {1'b1, {DATA_WIDTH-1{1'b0}}}; data_mask != 0; data_mask = data_mask >> 1) begin - // determine shift in value - // current value in last FF, XOR with input data bit (MSB first) - state_val = lfsr_mask_state[LFSR_WIDTH-1]; - data_val = lfsr_mask_data[LFSR_WIDTH-1]; - data_val = data_val ^ data_mask; - - // add XOR inputs from correct indicies - for (j = 1; j < LFSR_WIDTH; j = j + 1) begin - if ((LFSR_POLY >> j) & 1) begin - state_val = lfsr_mask_state[j-1] ^ state_val; - data_val = lfsr_mask_data[j-1] ^ data_val; - end - end - - // shift - for (j = LFSR_WIDTH-1; j > 0; j = j - 1) begin - lfsr_mask_state[j] = lfsr_mask_state[j-1]; - lfsr_mask_data[j] = lfsr_mask_data[j-1]; - end - for (j = DATA_WIDTH-1; j > 0; j = j - 1) begin - output_mask_state[j] = output_mask_state[j-1]; - output_mask_data[j] = output_mask_data[j-1]; - end - output_mask_state[0] = state_val; - output_mask_data[0] = data_val; - if (LFSR_FEED_FORWARD) begin - // only shift in new input data - state_val = {LFSR_WIDTH{1'b0}}; - data_val = data_mask; - end - lfsr_mask_state[0] = state_val; - lfsr_mask_data[0] = data_val; - end - end else if (LFSR_CONFIG == "GALOIS") begin - // Galois configuration - for (data_mask = {1'b1, {DATA_WIDTH-1{1'b0}}}; data_mask != 0; data_mask = data_mask >> 1) begin - // determine shift in value - // current value in last FF, XOR with input data bit (MSB first) - state_val = lfsr_mask_state[LFSR_WIDTH-1]; - data_val = lfsr_mask_data[LFSR_WIDTH-1]; - data_val = data_val ^ data_mask; - - // shift - for (j = LFSR_WIDTH-1; j > 0; j = j - 1) begin - lfsr_mask_state[j] = lfsr_mask_state[j-1]; - lfsr_mask_data[j] = lfsr_mask_data[j-1]; - end - for (j = DATA_WIDTH-1; j > 0; j = j - 1) begin - output_mask_state[j] = output_mask_state[j-1]; - output_mask_data[j] = output_mask_data[j-1]; - end - output_mask_state[0] = state_val; - output_mask_data[0] = data_val; - if (LFSR_FEED_FORWARD) begin - // only shift in new input data - state_val = {LFSR_WIDTH{1'b0}}; - data_val = data_mask; - end - lfsr_mask_state[0] = state_val; - lfsr_mask_data[0] = data_val; - - // add XOR inputs at correct indicies - for (j = 1; j < LFSR_WIDTH; j = j + 1) begin - if ((LFSR_POLY >> j) & 1) begin - lfsr_mask_state[j] = lfsr_mask_state[j] ^ state_val; - lfsr_mask_data[j] = lfsr_mask_data[j] ^ data_val; - end - end - end - end else begin - $error("Error: unknown configuration setting!"); - $finish; - end - - // reverse bits if selected - if (REVERSE) begin - if (index < LFSR_WIDTH) begin - state_val = 0; - for (i = 0; i < LFSR_WIDTH; i = i + 1) begin - state_val[i] = lfsr_mask_state[LFSR_WIDTH-index-1][LFSR_WIDTH-i-1]; - end - - data_val = 0; - for (i = 0; i < DATA_WIDTH; i = i + 1) begin - data_val[i] = lfsr_mask_data[LFSR_WIDTH-index-1][DATA_WIDTH-i-1]; - end - end else begin - state_val = 0; - for (i = 0; i < LFSR_WIDTH; i = i + 1) begin - state_val[i] = output_mask_state[DATA_WIDTH-(index-LFSR_WIDTH)-1][LFSR_WIDTH-i-1]; - end - - data_val = 0; - for (i = 0; i < DATA_WIDTH; i = i + 1) begin - data_val[i] = output_mask_data[DATA_WIDTH-(index-LFSR_WIDTH)-1][DATA_WIDTH-i-1]; - end - end - end else begin - if (index < LFSR_WIDTH) begin - state_val = lfsr_mask_state[index]; - data_val = lfsr_mask_data[index]; - end else begin - state_val = output_mask_state[index-LFSR_WIDTH]; - data_val = output_mask_data[index-LFSR_WIDTH]; - end - end - lfsr_mask = {data_val, state_val}; - end -endfunction - -// synthesis translate_off -`define SIMULATION -// synthesis translate_on - -`ifdef SIMULATION -// "AUTO" style is "REDUCTION" for faster simulation -parameter STYLE_INT = (STYLE == "AUTO") ? "REDUCTION" : STYLE; -`else -// "AUTO" style is "LOOP" for better synthesis result -parameter STYLE_INT = (STYLE == "AUTO") ? "LOOP" : STYLE; -`endif - -genvar n; - -generate - -if (STYLE_INT == "REDUCTION") begin - - // use Verilog reduction operator - // fast in iverilog - // significantly larger than generated code with ISE (inferred wide XORs may be tripping up optimizer) - // slightly smaller than generated code with Quartus - // --> better for simulation - - for (n = 0; n < LFSR_WIDTH; n = n + 1) begin : lfsr_state - wire [LFSR_WIDTH+DATA_WIDTH-1:0] mask = lfsr_mask(n); - assign state_out[n] = ^({data_in, state_in} & mask); - end - for (n = 0; n < DATA_WIDTH; n = n + 1) begin : lfsr_data - wire [LFSR_WIDTH+DATA_WIDTH-1:0] mask = lfsr_mask(n+LFSR_WIDTH); - assign data_out[n] = ^({data_in, state_in} & mask); - end - -end else if (STYLE_INT == "LOOP") begin - - // use nested loops - // very slow in iverilog - // slightly smaller than generated code with ISE - // same size as generated code with Quartus - // --> better for synthesis - - for (n = 0; n < LFSR_WIDTH; n = n + 1) begin : lfsr_state - wire [LFSR_WIDTH+DATA_WIDTH-1:0] mask = lfsr_mask(n); - - reg state_reg; - - assign state_out[n] = state_reg; - - integer i; - - always @* begin - state_reg = 1'b0; - for (i = 0; i < LFSR_WIDTH; i = i + 1) begin - if (mask[i]) begin - state_reg = state_reg ^ state_in[i]; - end - end - for (i = 0; i < DATA_WIDTH; i = i + 1) begin - if (mask[i+LFSR_WIDTH]) begin - state_reg = state_reg ^ data_in[i]; - end - end - end - end - for (n = 0; n < DATA_WIDTH; n = n + 1) begin : lfsr_data - wire [LFSR_WIDTH+DATA_WIDTH-1:0] mask = lfsr_mask(n+LFSR_WIDTH); - - reg data_reg; - - assign data_out[n] = data_reg; - - integer i; - - always @* begin - data_reg = 1'b0; - for (i = 0; i < LFSR_WIDTH; i = i + 1) begin - if (mask[i]) begin - data_reg = data_reg ^ state_in[i]; - end - end - for (i = 0; i < DATA_WIDTH; i = i + 1) begin - if (mask[i+LFSR_WIDTH]) begin - data_reg = data_reg ^ data_in[i]; - end - end - end - end - -end else begin - - initial begin - $error("Error: unknown style setting!"); - $finish; - end - -end - -endgenerate - -endmodule - -`resetall diff --git a/src/rvvi/mac_ctrl_rx.sv b/src/rvvi/mac_ctrl_rx.sv deleted file mode 100644 index f7171887b..000000000 --- a/src/rvvi/mac_ctrl_rx.sv +++ /dev/null @@ -1,447 +0,0 @@ -/* - -Copyright (c) 2023 Alex Forencich - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - -*/ - -// Language: Verilog 2001 - -`resetall -`default_nettype none - -/* - * MAC control receive - */ -module mac_ctrl_rx # -( - parameter DATA_WIDTH = 8, - parameter KEEP_ENABLE = DATA_WIDTH>8, - parameter KEEP_WIDTH = DATA_WIDTH/8, - parameter ID_ENABLE = 0, - parameter ID_WIDTH = 8, - parameter DEST_ENABLE = 0, - parameter DEST_WIDTH = 8, - parameter USER_ENABLE = 1, - parameter USER_WIDTH = 1, - parameter USE_READY = 0, - parameter MCF_PARAMS_SIZE = 18 -) -( - input wire clk, - input wire rst, - - /* - * AXI stream input - */ - input wire [DATA_WIDTH-1:0] s_axis_tdata, - input wire [KEEP_WIDTH-1:0] s_axis_tkeep, - input wire s_axis_tvalid, - output wire s_axis_tready, - input wire s_axis_tlast, - input wire [ID_WIDTH-1:0] s_axis_tid, - input wire [DEST_WIDTH-1:0] s_axis_tdest, - input wire [USER_WIDTH-1:0] s_axis_tuser, - - /* - * AXI stream output - */ - output wire [DATA_WIDTH-1:0] m_axis_tdata, - output wire [KEEP_WIDTH-1:0] m_axis_tkeep, - output wire m_axis_tvalid, - input wire m_axis_tready, - output wire m_axis_tlast, - output wire [ID_WIDTH-1:0] m_axis_tid, - output wire [DEST_WIDTH-1:0] m_axis_tdest, - output wire [USER_WIDTH-1:0] m_axis_tuser, - - /* - * MAC control frame interface - */ - output wire mcf_valid, - output wire [47:0] mcf_eth_dst, - output wire [47:0] mcf_eth_src, - output wire [15:0] mcf_eth_type, - output wire [15:0] mcf_opcode, - output wire [MCF_PARAMS_SIZE*8-1:0] mcf_params, - output wire [ID_WIDTH-1:0] mcf_id, - output wire [DEST_WIDTH-1:0] mcf_dest, - output wire [USER_WIDTH-1:0] mcf_user, - - /* - * Configuration - */ - input wire [47:0] cfg_mcf_rx_eth_dst_mcast, - input wire cfg_mcf_rx_check_eth_dst_mcast, - input wire [47:0] cfg_mcf_rx_eth_dst_ucast, - input wire cfg_mcf_rx_check_eth_dst_ucast, - input wire [47:0] cfg_mcf_rx_eth_src, - input wire cfg_mcf_rx_check_eth_src, - input wire [15:0] cfg_mcf_rx_eth_type, - input wire [15:0] cfg_mcf_rx_opcode_lfc, - input wire cfg_mcf_rx_check_opcode_lfc, - input wire [15:0] cfg_mcf_rx_opcode_pfc, - input wire cfg_mcf_rx_check_opcode_pfc, - input wire cfg_mcf_rx_forward, - input wire cfg_mcf_rx_enable, - - /* - * Status - */ - output wire stat_rx_mcf -); - -parameter BYTE_LANES = KEEP_ENABLE ? KEEP_WIDTH : 1; - -parameter HDR_SIZE = 60; - -parameter CYCLE_COUNT = (HDR_SIZE+BYTE_LANES-1)/BYTE_LANES; - -parameter PTR_WIDTH = $clog2(CYCLE_COUNT); - -parameter OFFSET = HDR_SIZE % BYTE_LANES; - -// check configuration -initial begin - if (BYTE_LANES * 8 != DATA_WIDTH) begin - $error("Error: AXI stream interface requires byte (8-bit) granularity (instance %m)"); - $finish; - end - - if (MCF_PARAMS_SIZE > 44) begin - $error("Error: Maximum MCF_PARAMS_SIZE is 44 bytes (instance %m)"); - $finish; - end -end - -/* - -MAC control frame - - Field Length - Destination MAC address 6 octets [01:80:C2:00:00:01] - Source MAC address 6 octets - Ethertype 2 octets [0x8808] - Opcode 2 octets - Parameters 0-44 octets - -This module manages the reception of MAC control frames. Incoming frames are -checked based on the ethertype and (optionally) MAC addresses. Matching control -frames are marked by setting tuser[0] on the data output and forwarded through -a separate interface for processing. - -*/ - -reg read_mcf_reg = 1'b1, read_mcf_next; -reg mcf_frame_reg = 1'b0, mcf_frame_next; -reg [PTR_WIDTH-1:0] ptr_reg = 0, ptr_next; - -reg s_axis_tready_reg = 1'b0, s_axis_tready_next; - -// internal datapath -reg [DATA_WIDTH-1:0] m_axis_tdata_int; -reg [KEEP_WIDTH-1:0] m_axis_tkeep_int; -reg m_axis_tvalid_int; -reg m_axis_tready_int_reg = 1'b0; -reg m_axis_tlast_int; -reg [ID_WIDTH-1:0] m_axis_tid_int; -reg [DEST_WIDTH-1:0] m_axis_tdest_int; -reg [USER_WIDTH-1:0] m_axis_tuser_int; -wire m_axis_tready_int_early; - -reg mcf_valid_reg = 0, mcf_valid_next; -reg [47:0] mcf_eth_dst_reg = 0, mcf_eth_dst_next; -reg [47:0] mcf_eth_src_reg = 0, mcf_eth_src_next; -reg [15:0] mcf_eth_type_reg = 0, mcf_eth_type_next; -reg [15:0] mcf_opcode_reg = 0, mcf_opcode_next; -reg [MCF_PARAMS_SIZE*8-1:0] mcf_params_reg = 0, mcf_params_next; -reg [ID_WIDTH-1:0] mcf_id_reg = 0, mcf_id_next; -reg [DEST_WIDTH-1:0] mcf_dest_reg = 0, mcf_dest_next; -reg [USER_WIDTH-1:0] mcf_user_reg = 0, mcf_user_next; - -reg stat_rx_mcf_reg = 1'b0, stat_rx_mcf_next; - -assign s_axis_tready = s_axis_tready_reg; - -assign mcf_valid = mcf_valid_reg; -assign mcf_eth_dst = mcf_eth_dst_reg; -assign mcf_eth_src = mcf_eth_src_reg; -assign mcf_eth_type = mcf_eth_type_reg; -assign mcf_opcode = mcf_opcode_reg; -assign mcf_params = mcf_params_reg; -assign mcf_id = mcf_id_reg; -assign mcf_dest = mcf_dest_reg; -assign mcf_user = mcf_user_reg; - -assign stat_rx_mcf = stat_rx_mcf_reg; - -wire mcf_eth_dst_mcast_match = mcf_eth_dst_next == cfg_mcf_rx_eth_dst_mcast; -wire mcf_eth_dst_ucast_match = mcf_eth_dst_next == cfg_mcf_rx_eth_dst_ucast; -wire mcf_eth_src_match = mcf_eth_src_next == cfg_mcf_rx_eth_src; -wire mcf_eth_type_match = mcf_eth_type_next == cfg_mcf_rx_eth_type; -wire mcf_opcode_lfc_match = mcf_opcode_next == cfg_mcf_rx_opcode_lfc; -wire mcf_opcode_pfc_match = mcf_opcode_next == cfg_mcf_rx_opcode_pfc; - -wire mcf_eth_dst_match = ((mcf_eth_dst_mcast_match && cfg_mcf_rx_check_eth_dst_mcast) || - (mcf_eth_dst_ucast_match && cfg_mcf_rx_check_eth_dst_ucast) || - (!cfg_mcf_rx_check_eth_dst_mcast && !cfg_mcf_rx_check_eth_dst_ucast)); - -wire mcf_opcode_match = ((mcf_opcode_lfc_match && cfg_mcf_rx_check_opcode_lfc) || - (mcf_opcode_pfc_match && cfg_mcf_rx_check_opcode_pfc) || - (!cfg_mcf_rx_check_opcode_lfc && !cfg_mcf_rx_check_opcode_pfc)); - -wire mcf_match = (mcf_eth_dst_match && - (mcf_eth_src_match || !cfg_mcf_rx_check_eth_src) && - mcf_eth_type_match && mcf_opcode_match); - -integer k; - -always @* begin - read_mcf_next = read_mcf_reg; - mcf_frame_next = mcf_frame_reg; - ptr_next = ptr_reg; - - // pass through data - m_axis_tdata_int = s_axis_tdata; - m_axis_tkeep_int = s_axis_tkeep; - m_axis_tvalid_int = s_axis_tvalid; - m_axis_tlast_int = s_axis_tlast; - m_axis_tid_int = s_axis_tid; - m_axis_tdest_int = s_axis_tdest; - m_axis_tuser_int = s_axis_tuser; - - s_axis_tready_next = m_axis_tready_int_early || !USE_READY; - - mcf_valid_next = 1'b0; - mcf_eth_dst_next = mcf_eth_dst_reg; - mcf_eth_src_next = mcf_eth_src_reg; - mcf_eth_type_next = mcf_eth_type_reg; - mcf_opcode_next = mcf_opcode_reg; - mcf_params_next = mcf_params_reg; - mcf_id_next = mcf_id_reg; - mcf_dest_next = mcf_dest_reg; - mcf_user_next = mcf_user_reg; - - stat_rx_mcf_next = 1'b0; - - if ((s_axis_tready || !USE_READY) && s_axis_tvalid) begin - if (read_mcf_reg) begin - ptr_next = ptr_reg + 1; - - mcf_id_next = s_axis_tid; - mcf_dest_next = s_axis_tdest; - mcf_user_next = s_axis_tuser; - - `define _HEADER_FIELD_(offset, field) \ - if (ptr_reg == offset/BYTE_LANES) begin \ - field = s_axis_tdata[(offset%BYTE_LANES)*8 +: 8]; \ - end - - `_HEADER_FIELD_(0, mcf_eth_dst_next[5*8 +: 8]) - `_HEADER_FIELD_(1, mcf_eth_dst_next[4*8 +: 8]) - `_HEADER_FIELD_(2, mcf_eth_dst_next[3*8 +: 8]) - `_HEADER_FIELD_(3, mcf_eth_dst_next[2*8 +: 8]) - `_HEADER_FIELD_(4, mcf_eth_dst_next[1*8 +: 8]) - `_HEADER_FIELD_(5, mcf_eth_dst_next[0*8 +: 8]) - `_HEADER_FIELD_(6, mcf_eth_src_next[5*8 +: 8]) - `_HEADER_FIELD_(7, mcf_eth_src_next[4*8 +: 8]) - `_HEADER_FIELD_(8, mcf_eth_src_next[3*8 +: 8]) - `_HEADER_FIELD_(9, mcf_eth_src_next[2*8 +: 8]) - `_HEADER_FIELD_(10, mcf_eth_src_next[1*8 +: 8]) - `_HEADER_FIELD_(11, mcf_eth_src_next[0*8 +: 8]) - `_HEADER_FIELD_(12, mcf_eth_type_next[1*8 +: 8]) - `_HEADER_FIELD_(13, mcf_eth_type_next[0*8 +: 8]) - `_HEADER_FIELD_(14, mcf_opcode_next[1*8 +: 8]) - `_HEADER_FIELD_(15, mcf_opcode_next[0*8 +: 8]) - - if (ptr_reg == 0/BYTE_LANES) begin - // ensure params field gets cleared - mcf_params_next = 0; - end - - for (k = 0; k < MCF_PARAMS_SIZE; k = k + 1) begin - if (ptr_reg == (16+k)/BYTE_LANES) begin - mcf_params_next[k*8 +: 8] = s_axis_tdata[((16+k)%BYTE_LANES)*8 +: 8]; - end - end - - if (ptr_reg == 15/BYTE_LANES && (!KEEP_ENABLE || s_axis_tkeep[13%BYTE_LANES])) begin - // record match at end of opcode field - mcf_frame_next = mcf_match && cfg_mcf_rx_enable; - end - - if (ptr_reg == (HDR_SIZE-1)/BYTE_LANES) begin - read_mcf_next = 1'b0; - end - - `undef _HEADER_FIELD_ - end - - if (s_axis_tlast) begin - if (s_axis_tuser[0]) begin - // frame marked invalid - end else if (mcf_frame_next) begin - if (!cfg_mcf_rx_forward) begin - // mark frame invalid - m_axis_tuser_int[0] = 1'b1; - end - // transfer out MAC control frame - mcf_valid_next = 1'b1; - stat_rx_mcf_next = 1'b1; - end - - read_mcf_next = 1'b1; - mcf_frame_next = 1'b0; - ptr_next = 0; - end - end -end - -always @(posedge clk) begin - read_mcf_reg <= read_mcf_next; - mcf_frame_reg <= mcf_frame_next; - ptr_reg <= ptr_next; - - s_axis_tready_reg <= s_axis_tready_next; - - mcf_valid_reg <= mcf_valid_next; - mcf_eth_dst_reg <= mcf_eth_dst_next; - mcf_eth_src_reg <= mcf_eth_src_next; - mcf_eth_type_reg <= mcf_eth_type_next; - mcf_opcode_reg <= mcf_opcode_next; - mcf_params_reg <= mcf_params_next; - mcf_id_reg <= mcf_id_next; - mcf_dest_reg <= mcf_dest_next; - mcf_user_reg <= mcf_user_next; - - stat_rx_mcf_reg <= stat_rx_mcf_next; - - if (rst) begin - read_mcf_reg <= 1'b1; - mcf_frame_reg <= 1'b0; - ptr_reg <= 0; - s_axis_tready_reg <= 1'b0; - mcf_valid_reg <= 1'b0; - stat_rx_mcf_reg <= 1'b0; - end -end - -// output datapath logic -reg [DATA_WIDTH-1:0] m_axis_tdata_reg = {DATA_WIDTH{1'b0}}; -reg [KEEP_WIDTH-1:0] m_axis_tkeep_reg = {KEEP_WIDTH{1'b0}}; -reg m_axis_tvalid_reg = 1'b0, m_axis_tvalid_next; -reg m_axis_tlast_reg = 1'b0; -reg [ID_WIDTH-1:0] m_axis_tid_reg = {ID_WIDTH{1'b0}}; -reg [DEST_WIDTH-1:0] m_axis_tdest_reg = {DEST_WIDTH{1'b0}}; -reg [USER_WIDTH-1:0] m_axis_tuser_reg = {USER_WIDTH{1'b0}}; - -reg [DATA_WIDTH-1:0] temp_m_axis_tdata_reg = {DATA_WIDTH{1'b0}}; -reg [KEEP_WIDTH-1:0] temp_m_axis_tkeep_reg = {KEEP_WIDTH{1'b0}}; -reg temp_m_axis_tvalid_reg = 1'b0, temp_m_axis_tvalid_next; -reg temp_m_axis_tlast_reg = 1'b0; -reg [ID_WIDTH-1:0] temp_m_axis_tid_reg = {ID_WIDTH{1'b0}}; -reg [DEST_WIDTH-1:0] temp_m_axis_tdest_reg = {DEST_WIDTH{1'b0}}; -reg [USER_WIDTH-1:0] temp_m_axis_tuser_reg = {USER_WIDTH{1'b0}}; - -// datapath control -reg store_axis_int_to_output; -reg store_axis_int_to_temp; -reg store_axis_temp_to_output; - -assign m_axis_tdata = m_axis_tdata_reg; -assign m_axis_tkeep = KEEP_ENABLE ? m_axis_tkeep_reg : {KEEP_WIDTH{1'b1}}; -assign m_axis_tvalid = m_axis_tvalid_reg; -assign m_axis_tlast = m_axis_tlast_reg; -assign m_axis_tid = ID_ENABLE ? m_axis_tid_reg : {ID_WIDTH{1'b0}}; -assign m_axis_tdest = DEST_ENABLE ? m_axis_tdest_reg : {DEST_WIDTH{1'b0}}; -assign m_axis_tuser = USER_ENABLE ? m_axis_tuser_reg : {USER_WIDTH{1'b0}}; - -// enable ready input next cycle if output is ready or the temp reg will not be filled on the next cycle (output reg empty or no input) -assign m_axis_tready_int_early = m_axis_tready || !USE_READY || (!temp_m_axis_tvalid_reg && (!m_axis_tvalid_reg || !m_axis_tvalid_int)); - -always @* begin - // transfer sink ready state to source - m_axis_tvalid_next = m_axis_tvalid_reg; - temp_m_axis_tvalid_next = temp_m_axis_tvalid_reg; - - store_axis_int_to_output = 1'b0; - store_axis_int_to_temp = 1'b0; - store_axis_temp_to_output = 1'b0; - - if (m_axis_tready_int_reg) begin - // input is ready - if (m_axis_tready || !USE_READY || !m_axis_tvalid_reg) begin - // output is ready or currently not valid, transfer data to output - m_axis_tvalid_next = m_axis_tvalid_int; - store_axis_int_to_output = 1'b1; - end else begin - // output is not ready, store input in temp - temp_m_axis_tvalid_next = m_axis_tvalid_int; - store_axis_int_to_temp = 1'b1; - end - end else if (m_axis_tready || !USE_READY) begin - // input is not ready, but output is ready - m_axis_tvalid_next = temp_m_axis_tvalid_reg; - temp_m_axis_tvalid_next = 1'b0; - store_axis_temp_to_output = 1'b1; - end -end - -always @(posedge clk) begin - m_axis_tvalid_reg <= m_axis_tvalid_next; - m_axis_tready_int_reg <= m_axis_tready_int_early; - temp_m_axis_tvalid_reg <= temp_m_axis_tvalid_next; - - // datapath - if (store_axis_int_to_output) begin - m_axis_tdata_reg <= m_axis_tdata_int; - m_axis_tkeep_reg <= m_axis_tkeep_int; - m_axis_tlast_reg <= m_axis_tlast_int; - m_axis_tid_reg <= m_axis_tid_int; - m_axis_tdest_reg <= m_axis_tdest_int; - m_axis_tuser_reg <= m_axis_tuser_int; - end else if (store_axis_temp_to_output) begin - m_axis_tdata_reg <= temp_m_axis_tdata_reg; - m_axis_tkeep_reg <= temp_m_axis_tkeep_reg; - m_axis_tlast_reg <= temp_m_axis_tlast_reg; - m_axis_tid_reg <= temp_m_axis_tid_reg; - m_axis_tdest_reg <= temp_m_axis_tdest_reg; - m_axis_tuser_reg <= temp_m_axis_tuser_reg; - end - - if (store_axis_int_to_temp) begin - temp_m_axis_tdata_reg <= m_axis_tdata_int; - temp_m_axis_tkeep_reg <= m_axis_tkeep_int; - temp_m_axis_tlast_reg <= m_axis_tlast_int; - temp_m_axis_tid_reg <= m_axis_tid_int; - temp_m_axis_tdest_reg <= m_axis_tdest_int; - temp_m_axis_tuser_reg <= m_axis_tuser_int; - end - - if (rst) begin - m_axis_tvalid_reg <= 1'b0; - m_axis_tready_int_reg <= 1'b0; - temp_m_axis_tvalid_reg <= 1'b0; - end -end - -endmodule - -`resetall diff --git a/src/rvvi/mac_ctrl_tx.sv b/src/rvvi/mac_ctrl_tx.sv deleted file mode 100644 index 3d321fd64..000000000 --- a/src/rvvi/mac_ctrl_tx.sv +++ /dev/null @@ -1,420 +0,0 @@ -/* - -Copyright (c) 2023 Alex Forencich - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - -*/ - -// Language: Verilog 2001 - -`resetall -`default_nettype none - -/* - * MAC control transmit - */ -module mac_ctrl_tx # -( - parameter DATA_WIDTH = 8, - parameter KEEP_ENABLE = DATA_WIDTH>8, - parameter KEEP_WIDTH = DATA_WIDTH/8, - parameter ID_ENABLE = 0, - parameter ID_WIDTH = 8, - parameter DEST_ENABLE = 0, - parameter DEST_WIDTH = 8, - parameter USER_ENABLE = 1, - parameter USER_WIDTH = 1, - parameter MCF_PARAMS_SIZE = 18 -) -( - input wire clk, - input wire rst, - - /* - * AXI stream input - */ - input wire [DATA_WIDTH-1:0] s_axis_tdata, - input wire [KEEP_WIDTH-1:0] s_axis_tkeep, - input wire s_axis_tvalid, - output wire s_axis_tready, - input wire s_axis_tlast, - input wire [ID_WIDTH-1:0] s_axis_tid, - input wire [DEST_WIDTH-1:0] s_axis_tdest, - input wire [USER_WIDTH-1:0] s_axis_tuser, - - /* - * AXI stream output - */ - output wire [DATA_WIDTH-1:0] m_axis_tdata, - output wire [KEEP_WIDTH-1:0] m_axis_tkeep, - output wire m_axis_tvalid, - input wire m_axis_tready, - output wire m_axis_tlast, - output wire [ID_WIDTH-1:0] m_axis_tid, - output wire [DEST_WIDTH-1:0] m_axis_tdest, - output wire [USER_WIDTH-1:0] m_axis_tuser, - - /* - * MAC control frame interface - */ - input wire mcf_valid, - output wire mcf_ready, - input wire [47:0] mcf_eth_dst, - input wire [47:0] mcf_eth_src, - input wire [15:0] mcf_eth_type, - input wire [15:0] mcf_opcode, - input wire [MCF_PARAMS_SIZE*8-1:0] mcf_params, - input wire [ID_WIDTH-1:0] mcf_id, - input wire [DEST_WIDTH-1:0] mcf_dest, - input wire [USER_WIDTH-1:0] mcf_user, - - /* - * Pause interface - */ - input wire tx_pause_req, - output wire tx_pause_ack, - - /* - * Status - */ - output wire stat_tx_mcf -); - -parameter BYTE_LANES = KEEP_ENABLE ? KEEP_WIDTH : 1; - -parameter HDR_SIZE = 60; - -parameter CYCLE_COUNT = (HDR_SIZE+BYTE_LANES-1)/BYTE_LANES; - -parameter PTR_WIDTH = $clog2(CYCLE_COUNT); - -parameter OFFSET = HDR_SIZE % BYTE_LANES; - -// check configuration -initial begin - if (BYTE_LANES * 8 != DATA_WIDTH) begin - $error("Error: AXI stream interface requires byte (8-bit) granularity (instance %m)"); - $finish; - end - - if (MCF_PARAMS_SIZE > 44) begin - $error("Error: Maximum MCF_PARAMS_SIZE is 44 bytes (instance %m)"); - $finish; - end -end - -/* - -MAC control frame - - Field Length - Destination MAC address 6 octets [01:80:C2:00:00:01] - Source MAC address 6 octets - Ethertype 2 octets [0x8808] - Opcode 2 octets - Parameters 0-44 octets - -This module manages the transmission of MAC control frames. Control frames -are accepted in parallel, serialized, and merged at a higher priority with -data traffic. - -*/ - -reg send_data_reg = 1'b0, send_data_next; -reg send_mcf_reg = 1'b0, send_mcf_next; -reg [PTR_WIDTH-1:0] ptr_reg = 0, ptr_next; - -reg s_axis_tready_reg = 1'b0, s_axis_tready_next; -reg mcf_ready_reg = 1'b0, mcf_ready_next; -reg tx_pause_ack_reg = 1'b0, tx_pause_ack_next; -reg stat_tx_mcf_reg = 1'b0, stat_tx_mcf_next; - -// internal datapath -reg [DATA_WIDTH-1:0] m_axis_tdata_int; -reg [KEEP_WIDTH-1:0] m_axis_tkeep_int; -reg m_axis_tvalid_int; -reg m_axis_tready_int_reg = 1'b0; -reg m_axis_tlast_int; -reg [ID_WIDTH-1:0] m_axis_tid_int; -reg [DEST_WIDTH-1:0] m_axis_tdest_int; -reg [USER_WIDTH-1:0] m_axis_tuser_int; -wire m_axis_tready_int_early; - -assign s_axis_tready = s_axis_tready_reg; -assign mcf_ready = mcf_ready_reg; -assign tx_pause_ack = tx_pause_ack_reg; -assign stat_tx_mcf = stat_tx_mcf_reg; - -integer k; - -always @* begin - send_data_next = send_data_reg; - send_mcf_next = send_mcf_reg; - ptr_next = ptr_reg; - - s_axis_tready_next = 1'b0; - mcf_ready_next = 1'b0; - tx_pause_ack_next = tx_pause_ack_reg; - stat_tx_mcf_next = 1'b0; - - m_axis_tdata_int = 0; - m_axis_tkeep_int = 0; - m_axis_tvalid_int = 1'b0; - m_axis_tlast_int = 1'b0; - m_axis_tid_int = 0; - m_axis_tdest_int = 0; - m_axis_tuser_int = 0; - - if (!send_data_reg && !send_mcf_reg) begin - m_axis_tdata_int = s_axis_tdata; - m_axis_tkeep_int = s_axis_tkeep; - m_axis_tvalid_int = 1'b0; - m_axis_tlast_int = s_axis_tlast; - m_axis_tid_int = s_axis_tid; - m_axis_tdest_int = s_axis_tdest; - m_axis_tuser_int = s_axis_tuser; - s_axis_tready_next = m_axis_tready_int_early && !tx_pause_req; - tx_pause_ack_next = tx_pause_req; - if (s_axis_tvalid && s_axis_tready) begin - s_axis_tready_next = m_axis_tready_int_early; - tx_pause_ack_next = 1'b0; - m_axis_tvalid_int = 1'b1; - if (s_axis_tlast) begin - s_axis_tready_next = m_axis_tready_int_early && !mcf_valid && !mcf_ready; - send_data_next = 1'b0; - end else begin - send_data_next = 1'b1; - end - end else if (mcf_valid) begin - s_axis_tready_next = 1'b0; - ptr_next = 0; - send_mcf_next = 1'b1; - mcf_ready_next = (CYCLE_COUNT == 1) && m_axis_tready_int_early; - end - end - - if (send_data_reg) begin - m_axis_tdata_int = s_axis_tdata; - m_axis_tkeep_int = s_axis_tkeep; - m_axis_tvalid_int = 1'b0; - m_axis_tlast_int = s_axis_tlast; - m_axis_tid_int = s_axis_tid; - m_axis_tdest_int = s_axis_tdest; - m_axis_tuser_int = s_axis_tuser; - s_axis_tready_next = m_axis_tready_int_early; - if (s_axis_tvalid && s_axis_tready) begin - m_axis_tvalid_int = 1'b1; - if (s_axis_tlast) begin - s_axis_tready_next = m_axis_tready_int_early && !tx_pause_req; - send_data_next = 1'b0; - if (mcf_valid) begin - s_axis_tready_next = 1'b0; - ptr_next = 0; - send_mcf_next = 1'b1; - mcf_ready_next = (CYCLE_COUNT == 1) && m_axis_tready_int_early; - end - end else begin - send_data_next = 1'b1; - end - end - end - - if (send_mcf_reg) begin - mcf_ready_next = (CYCLE_COUNT == 1 || ptr_reg == CYCLE_COUNT-1) && m_axis_tready_int_early; - if (m_axis_tready_int_reg) begin - ptr_next = ptr_reg + 1; - - m_axis_tvalid_int = 1'b1; - m_axis_tid_int = mcf_id; - m_axis_tdest_int = mcf_dest; - m_axis_tuser_int = mcf_user; - - `define _HEADER_FIELD_(offset, field) \ - if (ptr_reg == offset/BYTE_LANES) begin \ - m_axis_tdata_int[(offset%BYTE_LANES)*8 +: 8] = field; \ - m_axis_tkeep_int[offset%BYTE_LANES] = 1'b1; \ - end - - `_HEADER_FIELD_(0, mcf_eth_dst[5*8 +: 8]) - `_HEADER_FIELD_(1, mcf_eth_dst[4*8 +: 8]) - `_HEADER_FIELD_(2, mcf_eth_dst[3*8 +: 8]) - `_HEADER_FIELD_(3, mcf_eth_dst[2*8 +: 8]) - `_HEADER_FIELD_(4, mcf_eth_dst[1*8 +: 8]) - `_HEADER_FIELD_(5, mcf_eth_dst[0*8 +: 8]) - `_HEADER_FIELD_(6, mcf_eth_src[5*8 +: 8]) - `_HEADER_FIELD_(7, mcf_eth_src[4*8 +: 8]) - `_HEADER_FIELD_(8, mcf_eth_src[3*8 +: 8]) - `_HEADER_FIELD_(9, mcf_eth_src[2*8 +: 8]) - `_HEADER_FIELD_(10, mcf_eth_src[1*8 +: 8]) - `_HEADER_FIELD_(11, mcf_eth_src[0*8 +: 8]) - `_HEADER_FIELD_(12, mcf_eth_type[1*8 +: 8]) - `_HEADER_FIELD_(13, mcf_eth_type[0*8 +: 8]) - `_HEADER_FIELD_(14, mcf_opcode[1*8 +: 8]) - `_HEADER_FIELD_(15, mcf_opcode[0*8 +: 8]) - - for (k = 0; k < HDR_SIZE-16; k = k + 1) begin - if (ptr_reg == (16+k)/BYTE_LANES) begin - if (k < MCF_PARAMS_SIZE) begin - m_axis_tdata_int[((16+k)%BYTE_LANES)*8 +: 8] = mcf_params[k*8 +: 8]; - end else begin - m_axis_tdata_int[((16+k)%BYTE_LANES)*8 +: 8] = 0; - end - m_axis_tkeep_int[(16+k)%BYTE_LANES] = 1'b1; - end - end - - if (ptr_reg == (HDR_SIZE-1)/BYTE_LANES) begin - s_axis_tready_next = m_axis_tready_int_early && !tx_pause_req; - mcf_ready_next = 1'b0; - m_axis_tlast_int = 1'b1; - send_mcf_next = 1'b0; - stat_tx_mcf_next = 1'b1; - end else begin - mcf_ready_next = (ptr_next == CYCLE_COUNT-1) && m_axis_tready_int_early; - end - - `undef _HEADER_FIELD_ - end - end -end - -always @(posedge clk) begin - send_data_reg <= send_data_next; - send_mcf_reg <= send_mcf_next; - ptr_reg <= ptr_next; - - s_axis_tready_reg <= s_axis_tready_next; - mcf_ready_reg <= mcf_ready_next; - tx_pause_ack_reg <= tx_pause_ack_next; - stat_tx_mcf_reg <= stat_tx_mcf_next; - - if (rst) begin - send_data_reg <= 1'b0; - send_mcf_reg <= 1'b0; - ptr_reg <= 0; - s_axis_tready_reg <= 1'b0; - mcf_ready_reg <= 1'b0; - tx_pause_ack_reg <= 1'b0; - stat_tx_mcf_reg <= 1'b0; - end -end - -// output datapath logic -reg [DATA_WIDTH-1:0] m_axis_tdata_reg = {DATA_WIDTH{1'b0}}; -reg [KEEP_WIDTH-1:0] m_axis_tkeep_reg = {KEEP_WIDTH{1'b0}}; -reg m_axis_tvalid_reg = 1'b0, m_axis_tvalid_next; -reg m_axis_tlast_reg = 1'b0; -reg [ID_WIDTH-1:0] m_axis_tid_reg = {ID_WIDTH{1'b0}}; -reg [DEST_WIDTH-1:0] m_axis_tdest_reg = {DEST_WIDTH{1'b0}}; -reg [USER_WIDTH-1:0] m_axis_tuser_reg = {USER_WIDTH{1'b0}}; - -reg [DATA_WIDTH-1:0] temp_m_axis_tdata_reg = {DATA_WIDTH{1'b0}}; -reg [KEEP_WIDTH-1:0] temp_m_axis_tkeep_reg = {KEEP_WIDTH{1'b0}}; -reg temp_m_axis_tvalid_reg = 1'b0, temp_m_axis_tvalid_next; -reg temp_m_axis_tlast_reg = 1'b0; -reg [ID_WIDTH-1:0] temp_m_axis_tid_reg = {ID_WIDTH{1'b0}}; -reg [DEST_WIDTH-1:0] temp_m_axis_tdest_reg = {DEST_WIDTH{1'b0}}; -reg [USER_WIDTH-1:0] temp_m_axis_tuser_reg = {USER_WIDTH{1'b0}}; - -// datapath control -reg store_axis_int_to_output; -reg store_axis_int_to_temp; -reg store_axis_temp_to_output; - -assign m_axis_tdata = m_axis_tdata_reg; -assign m_axis_tkeep = KEEP_ENABLE ? m_axis_tkeep_reg : {KEEP_WIDTH{1'b1}}; -assign m_axis_tvalid = m_axis_tvalid_reg; -assign m_axis_tlast = m_axis_tlast_reg; -assign m_axis_tid = ID_ENABLE ? m_axis_tid_reg : {ID_WIDTH{1'b0}}; -assign m_axis_tdest = DEST_ENABLE ? m_axis_tdest_reg : {DEST_WIDTH{1'b0}}; -assign m_axis_tuser = USER_ENABLE ? m_axis_tuser_reg : {USER_WIDTH{1'b0}}; - -// enable ready input next cycle if output is ready or the temp reg will not be filled on the next cycle (output reg empty or no input) -assign m_axis_tready_int_early = m_axis_tready || (!temp_m_axis_tvalid_reg && (!m_axis_tvalid_reg || !m_axis_tvalid_int)); - -always @* begin - // transfer sink ready state to source - m_axis_tvalid_next = m_axis_tvalid_reg; - temp_m_axis_tvalid_next = temp_m_axis_tvalid_reg; - - store_axis_int_to_output = 1'b0; - store_axis_int_to_temp = 1'b0; - store_axis_temp_to_output = 1'b0; - - if (m_axis_tready_int_reg) begin - // input is ready - if (m_axis_tready || !m_axis_tvalid_reg) begin - // output is ready or currently not valid, transfer data to output - m_axis_tvalid_next = m_axis_tvalid_int; - store_axis_int_to_output = 1'b1; - end else begin - // output is not ready, store input in temp - temp_m_axis_tvalid_next = m_axis_tvalid_int; - store_axis_int_to_temp = 1'b1; - end - end else if (m_axis_tready) begin - // input is not ready, but output is ready - m_axis_tvalid_next = temp_m_axis_tvalid_reg; - temp_m_axis_tvalid_next = 1'b0; - store_axis_temp_to_output = 1'b1; - end -end - -always @(posedge clk) begin - m_axis_tvalid_reg <= m_axis_tvalid_next; - m_axis_tready_int_reg <= m_axis_tready_int_early; - temp_m_axis_tvalid_reg <= temp_m_axis_tvalid_next; - - // datapath - if (store_axis_int_to_output) begin - m_axis_tdata_reg <= m_axis_tdata_int; - m_axis_tkeep_reg <= m_axis_tkeep_int; - m_axis_tlast_reg <= m_axis_tlast_int; - m_axis_tid_reg <= m_axis_tid_int; - m_axis_tdest_reg <= m_axis_tdest_int; - m_axis_tuser_reg <= m_axis_tuser_int; - end else if (store_axis_temp_to_output) begin - m_axis_tdata_reg <= temp_m_axis_tdata_reg; - m_axis_tkeep_reg <= temp_m_axis_tkeep_reg; - m_axis_tlast_reg <= temp_m_axis_tlast_reg; - m_axis_tid_reg <= temp_m_axis_tid_reg; - m_axis_tdest_reg <= temp_m_axis_tdest_reg; - m_axis_tuser_reg <= temp_m_axis_tuser_reg; - end - - if (store_axis_int_to_temp) begin - temp_m_axis_tdata_reg <= m_axis_tdata_int; - temp_m_axis_tkeep_reg <= m_axis_tkeep_int; - temp_m_axis_tlast_reg <= m_axis_tlast_int; - temp_m_axis_tid_reg <= m_axis_tid_int; - temp_m_axis_tdest_reg <= m_axis_tdest_int; - temp_m_axis_tuser_reg <= m_axis_tuser_int; - end - - if (rst) begin - m_axis_tvalid_reg <= 1'b0; - m_axis_tready_int_reg <= 1'b0; - temp_m_axis_tvalid_reg <= 1'b0; - end -end - -endmodule - -`resetall diff --git a/src/rvvi/mac_pause_ctrl_rx.sv b/src/rvvi/mac_pause_ctrl_rx.sv deleted file mode 100644 index e95c07bf9..000000000 --- a/src/rvvi/mac_pause_ctrl_rx.sv +++ /dev/null @@ -1,220 +0,0 @@ -/* - -Copyright (c) 2023 Alex Forencich - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - -*/ - -// Language: Verilog 2001 - -`resetall -`default_nettype none - -/* - * PFC and pause frame receive handling - */ -module mac_pause_ctrl_rx # -( - parameter MCF_PARAMS_SIZE = 18, - parameter PFC_ENABLE = 1 -) -( - input wire clk, - input wire rst, - - /* - * MAC control frame interface - */ - input wire mcf_valid, - input wire [47:0] mcf_eth_dst, - input wire [47:0] mcf_eth_src, - input wire [15:0] mcf_eth_type, - input wire [15:0] mcf_opcode, - input wire [MCF_PARAMS_SIZE*8-1:0] mcf_params, - - /* - * Link-level Flow Control (LFC) (IEEE 802.3 annex 31B PAUSE) - */ - input wire rx_lfc_en, - output wire rx_lfc_req, - input wire rx_lfc_ack, - - /* - * Priority Flow Control (PFC) (IEEE 802.3 annex 31D PFC) - */ - input wire [7:0] rx_pfc_en, - output wire [7:0] rx_pfc_req, - input wire [7:0] rx_pfc_ack, - - /* - * Configuration - */ - input wire [15:0] cfg_rx_lfc_opcode, - input wire cfg_rx_lfc_en, - input wire [15:0] cfg_rx_pfc_opcode, - input wire cfg_rx_pfc_en, - input wire [9:0] cfg_quanta_step, - input wire cfg_quanta_clk_en, - - /* - * Status - */ - output wire stat_rx_lfc_pkt, - output wire stat_rx_lfc_xon, - output wire stat_rx_lfc_xoff, - output wire stat_rx_lfc_paused, - output wire stat_rx_pfc_pkt, - output wire [7:0] stat_rx_pfc_xon, - output wire [7:0] stat_rx_pfc_xoff, - output wire [7:0] stat_rx_pfc_paused -); - -localparam QFB = 8; - -// check configuration -initial begin - if (MCF_PARAMS_SIZE < (PFC_ENABLE ? 18 : 2)) begin - $error("Error: MCF_PARAMS_SIZE too small for requested configuration (instance %m)"); - $finish; - end -end - -reg lfc_req_reg = 1'b0, lfc_req_next; -reg [7:0] pfc_req_reg = 8'd0, pfc_req_next; - -reg [16+QFB-1:0] lfc_quanta_reg = 0, lfc_quanta_next; -reg [16+QFB-1:0] pfc_quanta_reg[0:7], pfc_quanta_next[0:7]; - -reg stat_rx_lfc_pkt_reg = 1'b0, stat_rx_lfc_pkt_next; -reg stat_rx_lfc_xon_reg = 1'b0, stat_rx_lfc_xon_next; -reg stat_rx_lfc_xoff_reg = 1'b0, stat_rx_lfc_xoff_next; -reg stat_rx_pfc_pkt_reg = 1'b0, stat_rx_pfc_pkt_next; -reg [7:0] stat_rx_pfc_xon_reg = 0, stat_rx_pfc_xon_next; -reg [7:0] stat_rx_pfc_xoff_reg = 0, stat_rx_pfc_xoff_next; - -assign rx_lfc_req = lfc_req_reg; -assign rx_pfc_req = pfc_req_reg; - -assign stat_rx_lfc_pkt = stat_rx_lfc_pkt_reg; -assign stat_rx_lfc_xon = stat_rx_lfc_xon_reg; -assign stat_rx_lfc_xoff = stat_rx_lfc_xoff_reg; -assign stat_rx_lfc_paused = lfc_req_reg; -assign stat_rx_pfc_pkt = stat_rx_pfc_pkt_reg; -assign stat_rx_pfc_xon = stat_rx_pfc_xon_reg; -assign stat_rx_pfc_xoff = stat_rx_pfc_xoff_reg; -assign stat_rx_pfc_paused = pfc_req_reg; - -integer k; - -initial begin - for (k = 0; k < 8; k = k + 1) begin - pfc_quanta_reg[k] = 0; - end -end - -always @* begin - stat_rx_lfc_pkt_next = 1'b0; - stat_rx_lfc_xon_next = 1'b0; - stat_rx_lfc_xoff_next = 1'b0; - stat_rx_pfc_pkt_next = 1'b0; - stat_rx_pfc_xon_next = 0; - stat_rx_pfc_xoff_next = 0; - - if (cfg_quanta_clk_en && rx_lfc_ack) begin - if (lfc_quanta_reg > cfg_quanta_step) begin - lfc_quanta_next = lfc_quanta_reg - cfg_quanta_step; - end else begin - lfc_quanta_next = 0; - end - end else begin - lfc_quanta_next = lfc_quanta_reg; - end - - lfc_req_next = (lfc_quanta_reg != 0) && rx_lfc_en && cfg_rx_lfc_en; - - for (k = 0; k < 8; k = k + 1) begin - if (cfg_quanta_clk_en && rx_pfc_ack[k]) begin - if (pfc_quanta_reg[k] > cfg_quanta_step) begin - pfc_quanta_next[k] = pfc_quanta_reg[k] - cfg_quanta_step; - end else begin - pfc_quanta_next[k] = 0; - end - end else begin - pfc_quanta_next[k] = pfc_quanta_reg[k]; - end - - pfc_req_next[k] = (pfc_quanta_reg[k] != 0) && rx_pfc_en[k] && cfg_rx_pfc_en; - end - - if (mcf_valid) begin - if (mcf_opcode == cfg_rx_lfc_opcode && cfg_rx_lfc_en) begin - stat_rx_lfc_pkt_next = 1'b1; - stat_rx_lfc_xon_next = {mcf_params[7:0], mcf_params[15:8]} == 0; - stat_rx_lfc_xoff_next = {mcf_params[7:0], mcf_params[15:8]} != 0; - lfc_quanta_next = {mcf_params[7:0], mcf_params[15:8], {QFB{1'b0}}}; - end else if (PFC_ENABLE && mcf_opcode == cfg_rx_pfc_opcode && cfg_rx_pfc_en) begin - stat_rx_pfc_pkt_next = 1'b1; - for (k = 0; k < 8; k = k + 1) begin - if (mcf_params[k+8]) begin - stat_rx_pfc_xon_next[k] = {mcf_params[16+(k*16)+0 +: 8], mcf_params[16+(k*16)+8 +: 8]} == 0; - stat_rx_pfc_xoff_next[k] = {mcf_params[16+(k*16)+0 +: 8], mcf_params[16+(k*16)+8 +: 8]} != 0; - pfc_quanta_next[k] = {mcf_params[16+(k*16)+0 +: 8], mcf_params[16+(k*16)+8 +: 8], {QFB{1'b0}}}; - end - end - end - end -end - -always @(posedge clk) begin - lfc_req_reg <= lfc_req_next; - pfc_req_reg <= pfc_req_next; - - lfc_quanta_reg <= lfc_quanta_next; - for (k = 0; k < 8; k = k + 1) begin - pfc_quanta_reg[k] <= pfc_quanta_next[k]; - end - - stat_rx_lfc_pkt_reg <= stat_rx_lfc_pkt_next; - stat_rx_lfc_xon_reg <= stat_rx_lfc_xon_next; - stat_rx_lfc_xoff_reg <= stat_rx_lfc_xoff_next; - stat_rx_pfc_pkt_reg <= stat_rx_pfc_pkt_next; - stat_rx_pfc_xon_reg <= stat_rx_pfc_xon_next; - stat_rx_pfc_xoff_reg <= stat_rx_pfc_xoff_next; - - if (rst) begin - lfc_req_reg <= 1'b0; - pfc_req_reg <= 8'd0; - lfc_quanta_reg <= 0; - for (k = 0; k < 8; k = k + 1) begin - pfc_quanta_reg[k] <= 0; - end - - stat_rx_lfc_pkt_reg <= 1'b0; - stat_rx_lfc_xon_reg <= 1'b0; - stat_rx_lfc_xoff_reg <= 1'b0; - stat_rx_pfc_pkt_reg <= 1'b0; - stat_rx_pfc_xon_reg <= 0; - stat_rx_pfc_xoff_reg <= 0; - end -end - -endmodule - -`resetall diff --git a/src/rvvi/mac_pause_ctrl_tx.sv b/src/rvvi/mac_pause_ctrl_tx.sv deleted file mode 100644 index 20566d888..000000000 --- a/src/rvvi/mac_pause_ctrl_tx.sv +++ /dev/null @@ -1,312 +0,0 @@ -/* - -Copyright (c) 2023 Alex Forencich - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - -*/ - -// Language: Verilog 2001 - -`resetall -`default_nettype none - -/* - * PFC and pause frame transmit handling - */ -module mac_pause_ctrl_tx # -( - parameter MCF_PARAMS_SIZE = 18, - parameter PFC_ENABLE = 1 -) -( - input wire clk, - input wire rst, - - /* - * MAC control frame interface - */ - output wire mcf_valid, - input wire mcf_ready, - output wire [47:0] mcf_eth_dst, - output wire [47:0] mcf_eth_src, - output wire [15:0] mcf_eth_type, - output wire [15:0] mcf_opcode, - output wire [MCF_PARAMS_SIZE*8-1:0] mcf_params, - - /* - * Link-level Flow Control (LFC) (IEEE 802.3 annex 31B PAUSE) - */ - input wire tx_lfc_req, - input wire tx_lfc_resend, - - /* - * Priority Flow Control (PFC) (IEEE 802.3 annex 31D) - */ - input wire [7:0] tx_pfc_req, - input wire tx_pfc_resend, - - /* - * Configuration - */ - input wire [47:0] cfg_tx_lfc_eth_dst, - input wire [47:0] cfg_tx_lfc_eth_src, - input wire [15:0] cfg_tx_lfc_eth_type, - input wire [15:0] cfg_tx_lfc_opcode, - input wire cfg_tx_lfc_en, - input wire [15:0] cfg_tx_lfc_quanta, - input wire [15:0] cfg_tx_lfc_refresh, - input wire [47:0] cfg_tx_pfc_eth_dst, - input wire [47:0] cfg_tx_pfc_eth_src, - input wire [15:0] cfg_tx_pfc_eth_type, - input wire [15:0] cfg_tx_pfc_opcode, - input wire cfg_tx_pfc_en, - input wire [8*16-1:0] cfg_tx_pfc_quanta, - input wire [8*16-1:0] cfg_tx_pfc_refresh, - input wire [9:0] cfg_quanta_step, - input wire cfg_quanta_clk_en, - - /* - * Status - */ - output wire stat_tx_lfc_pkt, - output wire stat_tx_lfc_xon, - output wire stat_tx_lfc_xoff, - output wire stat_tx_lfc_paused, - output wire stat_tx_pfc_pkt, - output wire [7:0] stat_tx_pfc_xon, - output wire [7:0] stat_tx_pfc_xoff, - output wire [7:0] stat_tx_pfc_paused -); - -localparam QFB = 8; - -// check configuration -initial begin - if (MCF_PARAMS_SIZE < (PFC_ENABLE ? 18 : 2)) begin - $error("Error: MCF_PARAMS_SIZE too small for requested configuration (instance %m)"); - $finish; - end -end - -reg lfc_req_reg = 1'b0, lfc_req_next; -reg lfc_act_reg = 1'b0, lfc_act_next; -reg lfc_send_reg = 1'b0, lfc_send_next; -reg [7:0] pfc_req_reg = 8'd0, pfc_req_next; -reg [7:0] pfc_act_reg = 8'd0, pfc_act_next; -reg [7:0] pfc_en_reg = 8'd0, pfc_en_next; -reg pfc_send_reg = 1'b0, pfc_send_next; - -reg [16+QFB-1:0] lfc_refresh_reg = 0, lfc_refresh_next; -reg [16+QFB-1:0] pfc_refresh_reg[0:7], pfc_refresh_next[0:7]; - -reg stat_tx_lfc_pkt_reg = 1'b0, stat_tx_lfc_pkt_next; -reg stat_tx_lfc_xon_reg = 1'b0, stat_tx_lfc_xon_next; -reg stat_tx_lfc_xoff_reg = 1'b0, stat_tx_lfc_xoff_next; -reg stat_tx_pfc_pkt_reg = 1'b0, stat_tx_pfc_pkt_next; -reg [7:0] stat_tx_pfc_xon_reg = 0, stat_tx_pfc_xon_next; -reg [7:0] stat_tx_pfc_xoff_reg = 0, stat_tx_pfc_xoff_next; - -// MAC control interface -reg mcf_pfc_sel_reg = PFC_ENABLE != 0, mcf_pfc_sel_next; -reg mcf_valid_reg = 1'b0, mcf_valid_next; - -wire [2*8-1:0] mcf_lfc_params; -assign mcf_lfc_params[16*0 +: 16] = lfc_req_reg ? {cfg_tx_lfc_quanta[0 +: 8], cfg_tx_lfc_quanta[8 +: 8]} : 0; - -wire [18*8-1:0] mcf_pfc_params; -assign mcf_pfc_params[16*0 +: 16] = {pfc_en_reg, 8'd0}; -assign mcf_pfc_params[16*1 +: 16] = pfc_req_reg[0] ? {cfg_tx_pfc_quanta[16*0+0 +: 8], cfg_tx_pfc_quanta[16*0+8 +: 8]} : 0; -assign mcf_pfc_params[16*2 +: 16] = pfc_req_reg[1] ? {cfg_tx_pfc_quanta[16*1+0 +: 8], cfg_tx_pfc_quanta[16*1+8 +: 8]} : 0; -assign mcf_pfc_params[16*3 +: 16] = pfc_req_reg[2] ? {cfg_tx_pfc_quanta[16*2+0 +: 8], cfg_tx_pfc_quanta[16*2+8 +: 8]} : 0; -assign mcf_pfc_params[16*4 +: 16] = pfc_req_reg[3] ? {cfg_tx_pfc_quanta[16*3+0 +: 8], cfg_tx_pfc_quanta[16*3+8 +: 8]} : 0; -assign mcf_pfc_params[16*5 +: 16] = pfc_req_reg[4] ? {cfg_tx_pfc_quanta[16*4+0 +: 8], cfg_tx_pfc_quanta[16*4+8 +: 8]} : 0; -assign mcf_pfc_params[16*6 +: 16] = pfc_req_reg[5] ? {cfg_tx_pfc_quanta[16*5+0 +: 8], cfg_tx_pfc_quanta[16*5+8 +: 8]} : 0; -assign mcf_pfc_params[16*7 +: 16] = pfc_req_reg[6] ? {cfg_tx_pfc_quanta[16*6+0 +: 8], cfg_tx_pfc_quanta[16*6+8 +: 8]} : 0; -assign mcf_pfc_params[16*8 +: 16] = pfc_req_reg[7] ? {cfg_tx_pfc_quanta[16*7+0 +: 8], cfg_tx_pfc_quanta[16*7+8 +: 8]} : 0; - -assign mcf_valid = mcf_valid_reg; -assign mcf_eth_dst = (PFC_ENABLE && mcf_pfc_sel_reg) ? cfg_tx_pfc_eth_dst : cfg_tx_lfc_eth_dst; -assign mcf_eth_src = (PFC_ENABLE && mcf_pfc_sel_reg) ? cfg_tx_pfc_eth_src : cfg_tx_lfc_eth_src; -assign mcf_eth_type = (PFC_ENABLE && mcf_pfc_sel_reg) ? cfg_tx_pfc_eth_type : cfg_tx_lfc_eth_type; -assign mcf_opcode = (PFC_ENABLE && mcf_pfc_sel_reg) ? cfg_tx_pfc_opcode : cfg_tx_lfc_opcode; -assign mcf_params = (PFC_ENABLE && mcf_pfc_sel_reg) ? mcf_pfc_params : mcf_lfc_params; - -assign stat_tx_lfc_pkt = stat_tx_lfc_pkt_reg; -assign stat_tx_lfc_xon = stat_tx_lfc_xon_reg; -assign stat_tx_lfc_xoff = stat_tx_lfc_xoff_reg; -assign stat_tx_lfc_paused = lfc_req_reg; -assign stat_tx_pfc_pkt = stat_tx_pfc_pkt_reg; -assign stat_tx_pfc_xon = stat_tx_pfc_xon_reg; -assign stat_tx_pfc_xoff = stat_tx_pfc_xoff_reg; -assign stat_tx_pfc_paused = pfc_req_reg; - -integer k; - -initial begin - for (k = 0; k < 8; k = k + 1) begin - pfc_refresh_reg[k] = 0; - end -end - -always @* begin - lfc_req_next = lfc_req_reg; - lfc_act_next = lfc_act_reg; - lfc_send_next = lfc_send_reg | tx_lfc_resend; - pfc_req_next = pfc_req_reg; - pfc_act_next = pfc_act_reg; - pfc_en_next = pfc_en_reg; - pfc_send_next = pfc_send_reg | tx_pfc_resend; - - mcf_pfc_sel_next = mcf_pfc_sel_reg; - mcf_valid_next = mcf_valid_reg && !mcf_ready; - - stat_tx_lfc_pkt_next = 1'b0; - stat_tx_lfc_xon_next = 1'b0; - stat_tx_lfc_xoff_next = 1'b0; - stat_tx_pfc_pkt_next = 1'b0; - stat_tx_pfc_xon_next = 0; - stat_tx_pfc_xoff_next = 0; - - if (cfg_quanta_clk_en) begin - if (lfc_refresh_reg > cfg_quanta_step) begin - lfc_refresh_next = lfc_refresh_reg - cfg_quanta_step; - end else begin - lfc_refresh_next = 0; - if (lfc_req_reg) begin - lfc_send_next = 1'b1; - end - end - end else begin - lfc_refresh_next = lfc_refresh_reg; - end - - for (k = 0; k < 8; k = k + 1) begin - if (cfg_quanta_clk_en) begin - if (pfc_refresh_reg[k] > cfg_quanta_step) begin - pfc_refresh_next[k] = pfc_refresh_reg[k] - cfg_quanta_step; - end else begin - pfc_refresh_next[k] = 0; - if (pfc_req_reg[k]) begin - pfc_send_next = 1'b1; - end - end - end else begin - pfc_refresh_next[k] = pfc_refresh_reg[k]; - end - end - - if (cfg_tx_lfc_en) begin - if (!mcf_valid_reg) begin - if (lfc_req_reg != tx_lfc_req) begin - lfc_req_next = tx_lfc_req; - lfc_act_next = lfc_act_reg | tx_lfc_req; - lfc_send_next = 1'b1; - end - - if (lfc_send_reg && !(PFC_ENABLE && cfg_tx_pfc_en && pfc_send_reg)) begin - mcf_pfc_sel_next = 1'b0; - mcf_valid_next = lfc_act_reg; - lfc_act_next = lfc_req_reg; - lfc_refresh_next = lfc_req_reg ? {cfg_tx_lfc_refresh, {QFB{1'b0}}} : 0; - lfc_send_next = 1'b0; - - stat_tx_lfc_pkt_next = lfc_act_reg; - stat_tx_lfc_xon_next = lfc_act_reg && !lfc_req_reg; - stat_tx_lfc_xoff_next = lfc_act_reg && lfc_req_reg; - end - end - end - - if (PFC_ENABLE && cfg_tx_pfc_en) begin - if (!mcf_valid_reg) begin - if (pfc_req_reg != tx_pfc_req) begin - pfc_req_next = tx_pfc_req; - pfc_act_next = pfc_act_reg | tx_pfc_req; - pfc_send_next = 1'b1; - end - - if (pfc_send_reg) begin - mcf_pfc_sel_next = 1'b1; - mcf_valid_next = pfc_act_reg != 0; - pfc_en_next = pfc_act_reg; - pfc_act_next = pfc_req_reg; - for (k = 0; k < 8; k = k + 1) begin - pfc_refresh_next[k] = pfc_req_reg[k] ? {cfg_tx_pfc_refresh[16*k +: 16], {QFB{1'b0}}} : 0; - end - pfc_send_next = 1'b0; - - stat_tx_pfc_pkt_next = pfc_act_reg != 0; - stat_tx_pfc_xon_next = pfc_act_reg & ~pfc_req_reg; - stat_tx_pfc_xoff_next = pfc_act_reg & pfc_req_reg; - end - end - end -end - -always @(posedge clk) begin - lfc_req_reg <= lfc_req_next; - lfc_act_reg <= lfc_act_next; - lfc_send_reg <= lfc_send_next; - pfc_req_reg <= pfc_req_next; - pfc_act_reg <= pfc_act_next; - pfc_en_reg <= pfc_en_next; - pfc_send_reg <= pfc_send_next; - - mcf_pfc_sel_reg <= mcf_pfc_sel_next; - mcf_valid_reg <= mcf_valid_next; - - lfc_refresh_reg <= lfc_refresh_next; - for (k = 0; k < 8; k = k + 1) begin - pfc_refresh_reg[k] <= pfc_refresh_next[k]; - end - - stat_tx_lfc_pkt_reg <= stat_tx_lfc_pkt_next; - stat_tx_lfc_xon_reg <= stat_tx_lfc_xon_next; - stat_tx_lfc_xoff_reg <= stat_tx_lfc_xoff_next; - stat_tx_pfc_pkt_reg <= stat_tx_pfc_pkt_next; - stat_tx_pfc_xon_reg <= stat_tx_pfc_xon_next; - stat_tx_pfc_xoff_reg <= stat_tx_pfc_xoff_next; - - if (rst) begin - lfc_req_reg <= 1'b0; - lfc_act_reg <= 1'b0; - lfc_send_reg <= 1'b0; - pfc_req_reg <= 0; - pfc_act_reg <= 0; - pfc_send_reg <= 0; - mcf_pfc_sel_reg <= PFC_ENABLE != 0; - mcf_valid_reg <= 1'b0; - lfc_refresh_reg <= 0; - for (k = 0; k < 8; k = k + 1) begin - pfc_refresh_reg[k] <= 0; - end - - stat_tx_lfc_pkt_reg <= 1'b0; - stat_tx_lfc_xon_reg <= 1'b0; - stat_tx_lfc_xoff_reg <= 1'b0; - stat_tx_pfc_pkt_reg <= 1'b0; - stat_tx_pfc_xon_reg <= 0; - stat_tx_pfc_xoff_reg <= 0; - end -end - -endmodule - -`resetall diff --git a/src/rvvi/mii_phy_if.sv b/src/rvvi/mii_phy_if.sv deleted file mode 100644 index f3857ed06..000000000 --- a/src/rvvi/mii_phy_if.sv +++ /dev/null @@ -1,140 +0,0 @@ -/* - -Copyright (c) 2019 Alex Forencich - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - -*/ - -// Language: Verilog 2001 - -`resetall -`default_nettype none - -/* - * MII PHY interface - */ -module mii_phy_if # -( - // target ("SIM", "GENERIC", "XILINX", "ALTERA") - parameter TARGET = "GENERIC", - // Clock input style ("BUFG", "BUFR", "BUFIO", "BUFIO2") - // Use BUFR for Virtex-5, Virtex-6, 7-series - // Use BUFG for Ultrascale - // Use BUFIO2 for Spartan-6 - parameter CLOCK_INPUT_STYLE = "BUFIO2" -) -( - input wire rst, - - /* - * MII interface to MAC - */ - output wire mac_mii_rx_clk, - output wire mac_mii_rx_rst, - output wire [3:0] mac_mii_rxd, - output wire mac_mii_rx_dv, - output wire mac_mii_rx_er, - output wire mac_mii_tx_clk, - output wire mac_mii_tx_rst, -(* mark_debug = "true" *) input wire [3:0] mac_mii_txd, -(* mark_debug = "true" *) input wire mac_mii_tx_en, - input wire mac_mii_tx_er, - - /* - * MII interface to PHY - */ - input wire phy_mii_rx_clk, - input wire [3:0] phy_mii_rxd, - input wire phy_mii_rx_dv, - input wire phy_mii_rx_er, - input wire phy_mii_tx_clk, - output wire [3:0] phy_mii_txd, - output wire phy_mii_tx_en, - output wire phy_mii_tx_er -); - -ssio_sdr_in # -( - .TARGET(TARGET), - .CLOCK_INPUT_STYLE(CLOCK_INPUT_STYLE), - .WIDTH(6) -) -rx_ssio_sdr_inst ( - .input_clk(phy_mii_rx_clk), - .input_d({phy_mii_rxd, phy_mii_rx_dv, phy_mii_rx_er}), - .output_clk(mac_mii_rx_clk), - .output_q({mac_mii_rxd, mac_mii_rx_dv, mac_mii_rx_er}) -); - -(* IOB = "TRUE" *) -reg [3:0] phy_mii_txd_reg = 4'd0; -(* IOB = "TRUE" *) -reg phy_mii_tx_en_reg = 1'b0, phy_mii_tx_er_reg = 1'b0; - -assign phy_mii_txd = phy_mii_txd_reg; -assign phy_mii_tx_en = phy_mii_tx_en_reg; -assign phy_mii_tx_er = phy_mii_tx_er_reg; - -always @(posedge mac_mii_tx_clk) begin - phy_mii_txd_reg <= mac_mii_txd; - phy_mii_tx_en_reg <= mac_mii_tx_en; - phy_mii_tx_er_reg <= mac_mii_tx_er; -end - -generate - -if (TARGET == "XILINX") begin - BUFG - mii_bufg_inst ( - .I(phy_mii_tx_clk), - .O(mac_mii_tx_clk) - ); -end else begin - assign mac_mii_tx_clk = phy_mii_tx_clk; -end - -endgenerate - -// reset sync -reg [3:0] tx_rst_reg = 4'hf; -assign mac_mii_tx_rst = tx_rst_reg[0]; - -always @(posedge mac_mii_tx_clk or posedge rst) begin - if (rst) begin - tx_rst_reg <= 4'hf; - end else begin - tx_rst_reg <= {1'b0, tx_rst_reg[3:1]}; - end -end - -reg [3:0] rx_rst_reg = 4'hf; -assign mac_mii_rx_rst = rx_rst_reg[0]; - -always @(posedge mac_mii_rx_clk or posedge rst) begin - if (rst) begin - rx_rst_reg <= 4'hf; - end else begin - rx_rst_reg <= {1'b0, rx_rst_reg[3:1]}; - end -end - -endmodule - -`resetall diff --git a/src/rvvi/ssio_ddr_in.sv b/src/rvvi/ssio_ddr_in.sv deleted file mode 100644 index 5060f4d27..000000000 --- a/src/rvvi/ssio_ddr_in.sv +++ /dev/null @@ -1,150 +0,0 @@ -/* - -Copyright (c) 2016-2018 Alex Forencich - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - -*/ - -// Language: Verilog 2001 - -`resetall -`default_nettype none - -/* - * Generic source synchronous DDR input - */ -module ssio_ddr_in # -( - // target ("SIM", "GENERIC", "XILINX", "ALTERA") - parameter TARGET = "GENERIC", - // IODDR style ("IODDR", "IODDR2") - // Use IODDR for Virtex-4, Virtex-5, Virtex-6, 7 Series, Ultrascale - // Use IODDR2 for Spartan-6 - parameter IODDR_STYLE = "IODDR2", - // Clock input style ("BUFG", "BUFR", "BUFIO", "BUFIO2") - // Use BUFR for Virtex-6, 7-series - // Use BUFG for Virtex-5, Spartan-6, Ultrascale - parameter CLOCK_INPUT_STYLE = "BUFG", - // Width of register in bits - parameter WIDTH = 1 -) -( - input wire input_clk, - - input wire [WIDTH-1:0] input_d, - - output wire output_clk, - - output wire [WIDTH-1:0] output_q1, - output wire [WIDTH-1:0] output_q2 -); - -wire clk_int; -wire clk_io; - -generate - -if (TARGET == "XILINX") begin - - // use Xilinx clocking primitives - - if (CLOCK_INPUT_STYLE == "BUFG") begin - - // buffer RX clock - BUFG - clk_bufg ( - .I(input_clk), - .O(clk_int) - ); - - // pass through RX clock to logic and input buffers - assign clk_io = clk_int; - assign output_clk = clk_int; - - end else if (CLOCK_INPUT_STYLE == "BUFR") begin - - assign clk_int = input_clk; - - // pass through RX clock to input buffers - BUFIO - clk_bufio ( - .I(clk_int), - .O(clk_io) - ); - - // pass through RX clock to logic - BUFR #( - .BUFR_DIVIDE("BYPASS") - ) - clk_bufr ( - .I(clk_int), - .O(output_clk), - .CE(1'b1), - .CLR(1'b0) - ); - - end else if (CLOCK_INPUT_STYLE == "BUFIO") begin - - assign clk_int = input_clk; - - // pass through RX clock to input buffers - BUFIO - clk_bufio ( - .I(clk_int), - .O(clk_io) - ); - - // pass through RX clock to MAC - BUFG - clk_bufg ( - .I(clk_int), - .O(output_clk) - ); - - end - -end else begin - - // pass through RX clock to input buffers - assign clk_io = input_clk; - - // pass through RX clock to logic - assign clk_int = input_clk; - assign output_clk = clk_int; - -end - -endgenerate - -iddr #( - .TARGET(TARGET), - .IODDR_STYLE(IODDR_STYLE), - .WIDTH(WIDTH) -) -data_iddr_inst ( - .clk(clk_io), - .d(input_d), - .q1(output_q1), - .q2(output_q2) -); - -endmodule - -`resetall diff --git a/src/rvvi/ssio_sdr_in.sv b/src/rvvi/ssio_sdr_in.sv deleted file mode 100644 index 351cadc1d..000000000 --- a/src/rvvi/ssio_sdr_in.sv +++ /dev/null @@ -1,166 +0,0 @@ -/* - -Copyright (c) 2016-2018 Alex Forencich - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - -*/ - -// Language: Verilog 2001 - -`resetall -`default_nettype none - -/* - * Generic source synchronous SDR input - */ -module ssio_sdr_in # -( - // target ("SIM", "GENERIC", "XILINX", "ALTERA") - parameter TARGET = "GENERIC", - // Clock input style ("BUFG", "BUFR", "BUFIO", "BUFIO2") - // Use BUFR for Virtex-5, Virtex-6, 7-series - // Use BUFG for Ultrascale - // Use BUFIO2 for Spartan-6 - parameter CLOCK_INPUT_STYLE = "BUFIO2", - // Width of register in bits - parameter WIDTH = 1 -) -( - input wire input_clk, - - input wire [WIDTH-1:0] input_d, - - output wire output_clk, - - output wire [WIDTH-1:0] output_q -); - -wire clk_int; -wire clk_io; - -generate - -if (TARGET == "XILINX") begin - - // use Xilinx clocking primitives - - if (CLOCK_INPUT_STYLE == "BUFG") begin - - // buffer RX clock - BUFG - clk_bufg ( - .I(input_clk), - .O(clk_int) - ); - - // pass through RX clock to logic and input buffers - assign clk_io = clk_int; - assign output_clk = clk_int; - - end else if (CLOCK_INPUT_STYLE == "BUFR") begin - - assign clk_int = input_clk; - - // pass through RX clock to input buffers - BUFIO - clk_bufio ( - .I(clk_int), - .O(clk_io) - ); - - // pass through RX clock to logic - BUFR #( - .BUFR_DIVIDE("BYPASS") - ) - clk_bufr ( - .I(clk_int), - .O(output_clk), - .CE(1'b1), - .CLR(1'b0) - ); - - end else if (CLOCK_INPUT_STYLE == "BUFIO") begin - - assign clk_int = input_clk; - - // pass through RX clock to input buffers - BUFIO - clk_bufio ( - .I(clk_int), - .O(clk_io) - ); - - // pass through RX clock to MAC - BUFG - clk_bufg ( - .I(clk_int), - .O(output_clk) - ); - - end else if (CLOCK_INPUT_STYLE == "BUFIO2") begin - - // pass through RX clock to input buffers - BUFIO2 #( - .DIVIDE(1), - .DIVIDE_BYPASS("TRUE"), - .I_INVERT("FALSE"), - .USE_DOUBLER("FALSE") - ) - clk_bufio ( - .I(input_clk), - .DIVCLK(clk_int), - .IOCLK(clk_io), - .SERDESSTROBE() - ); - - // pass through RX clock to MAC - BUFG - clk_bufg ( - .I(clk_int), - .O(output_clk) - ); - - end - -end else begin - - // pass through RX clock to input buffers - assign clk_io = input_clk; - - // pass through RX clock to logic - assign clk_int = input_clk; - assign output_clk = clk_int; - -end - -endgenerate - -(* IOB = "TRUE" *) -reg [WIDTH-1:0] output_q_reg = {WIDTH{1'b0}}; - -assign output_q = output_q_reg; - -always @(posedge clk_io) begin - output_q_reg <= input_d; -end - -endmodule - -`resetall