1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
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
|