diff options
| author | Alejandro Soto <alejandro@34project.org> | 2024-05-04 14:19:48 -0600 |
|---|---|---|
| committer | Alejandro Soto <alejandro@34project.org> | 2024-05-04 14:19:48 -0600 |
| commit | a7d92072c0bdc3a3e1c99de64f353e932846bc2a (patch) | |
| tree | cc9af86b65820c3a30cf1d0b0c97e8bfe8fc9b44 /rtl/pkt_switch/pkt_switch.v | |
| parent | 90cd29d85865bb5a4dbdf791616818b151881883 (diff) | |
rtl/pkt_switch: replace axi_timer example with pkt_switch
Diffstat (limited to 'rtl/pkt_switch/pkt_switch.v')
| -rw-r--r-- | rtl/pkt_switch/pkt_switch.v | 136 |
1 files changed, 136 insertions, 0 deletions
diff --git a/rtl/pkt_switch/pkt_switch.v b/rtl/pkt_switch/pkt_switch.v new file mode 100644 index 0000000..c146b5e --- /dev/null +++ b/rtl/pkt_switch/pkt_switch.v @@ -0,0 +1,136 @@ + +//Simple pkt switch, functionality: +// - 1 data input interface, 2 data output interfaces +// - data width is 8 bits, with "valid" bit +// - packet is tranmitted continuously (valid = 1, cannot fall in the middle) +// - when valid = 0 that means a gap between packets, packet always starts when valid 0->1 +// - first byte of the packet is address, second is packet length (in bytes), following by the data +// - non-filtered packets are transmitted on interface 0, filtered on 1 +// - if filtering is not enabled, packets are simply forwarded on interface 0 +// - 1 control interface (write only) +// - registers: +// - ADDR: FUNCTIONALITY: +// - 000 settings: +// bit 0 - enable address-based filtering +// bit 1 - enable length-based filtering +// bit 2 - transmit packet on both interfaces +// - 010 address for address-based filtering +// - 011 address based filtering mask (which bits of the address are valid) +// - 100 lower size limit for length based filtering +// - 101 uppoer size limit for length based filtering + +module pkt_switch ( + clk, + rst_n, + datain_data, + datain_valid, + dataout0_data, + dataout1_data, + dataout0_valid, + dataout1_valid, + ctrl_addr, + ctrl_data, + ctrl_wr +); + + input clk, rst_n; + //data interfaces + input [7:0] datain_data; + input datain_valid; + output reg [7:0] dataout0_data, dataout1_data; + output reg dataout0_valid, dataout1_valid; + //control interface + input [2:0] ctrl_addr; + input [7:0] ctrl_data; + input ctrl_wr; + + //config registers + reg addr_filtering_ena_r; + reg len_filtering_ena_r; + reg transmit_both_ena_r; + + reg [7:0] filter_addr_r; + reg [7:0] filter_addr_mask_r; + reg [7:0] lower_size_limit_r; + reg [7:0] upper_size_limit_r; + + reg [7:0] data_0_r, data_1_r; + reg datain_valid_0_r, datain_valid_1_r; + reg [7:0] pkt_addr_r, pkt_len_r; + + wire addr_filtering_active, channel0_active, channel1_active, len_filtering_active; + + always @(posedge clk or negedge rst_n) + begin : config_proc + if(~rst_n) begin + addr_filtering_ena_r <= 1'b0; + len_filtering_ena_r <= 1'b0; + transmit_both_ena_r <= 1'b0; + filter_addr_r <= 8'd0; + filter_addr_mask_r <= 8'd0; + lower_size_limit_r <= 8'd0; + upper_size_limit_r <= 8'd0; + end else if (ctrl_wr) begin + case (ctrl_addr) + 3'b000: begin + addr_filtering_ena_r <= ctrl_data[0]; + len_filtering_ena_r <= ctrl_data[1]; + transmit_both_ena_r <= ctrl_data[2]; + end + 3'b010: filter_addr_r <= ctrl_data; + 3'b011: filter_addr_mask_r <= ctrl_data; + 3'b100: lower_size_limit_r <= ctrl_data; + 3'b101: upper_size_limit_r <= ctrl_data; + default: ; + endcase + end + end + + always @(posedge clk or negedge rst_n) + begin : data_proc + if(~rst_n) begin + data_0_r <= 8'd0; + data_1_r <= 8'd0; + dataout0_data <= 8'd0; + dataout1_data <= 8'd0; + datain_valid_0_r <= 1'b0; + datain_valid_1_r <= 1'b0; + end else begin + data_0_r <= datain_data; + data_1_r <= data_0_r; + datain_valid_0_r <= datain_valid; + datain_valid_1_r <= datain_valid_0_r; + dataout0_data <= (channel0_active) ? data_1_r : 8'd0; + dataout0_valid <= (channel0_active) ? datain_valid_1_r : 1'b0; + dataout1_data <= (channel1_active) ? data_1_r : 8'd0; + dataout1_valid <= (channel1_active) ? datain_valid_1_r : 1'b0; + end + end + + always @(posedge clk or negedge rst_n) + begin : header_proc + if(~rst_n) begin + pkt_addr_r <= 8'd0; + pkt_len_r <= 8'd0; + end else begin + if (datain_valid && !datain_valid_0_r) //first packet byte + pkt_addr_r <= datain_data; + if (datain_valid_0_r && !datain_valid_1_r) //second packet byte + pkt_len_r <= datain_data; + end + end + + assign addr_filtering_active = + addr_filtering_ena_r && + ((pkt_addr_r & filter_addr_mask_r) == (filter_addr_r & filter_addr_mask_r)); + assign len_filtering_active = + len_filtering_ena_r && + ((pkt_len_r >= lower_size_limit_r) && (pkt_len_r <= upper_size_limit_r)); + + assign channel0_active = + !addr_filtering_active && !len_filtering_active; + assign channel1_active = + transmit_both_ena_r || + addr_filtering_active || len_filtering_active; + +endmodule |
