Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

check certain string from continuous input: Verilog

Status
Not open for further replies.

beginner_EDA

Full Member level 4
Joined
Aug 14, 2013
Messages
191
Helped
0
Reputation
0
Reaction score
0
Trophy points
1,296
Activity points
3,854
Hello Everybody,

I am receiving continuous input in hex format (of corresponding ASCII character) and I have to check certain strings (which is of bigger length. lets's say "Hello How are you") out of it and then trigger some action in verilog. But I don't know how to do that.

Could anybody please help?
 

ASCII character 8-bit wide by N entry shift register, a loadable string register, a big mask comparator to match the loaded string with the input string. That's probably the simplest implementation, but it may not be the most resource efficient if the string becomes very large.

Other implementations that are similar to software implementations of searches (where you compare byte by byte and reset when matches don't occur) are much more complex to implement and would require running the logic at a much higher rate than the continuous input data to keep up.
 
ASCII character 8-bit wide by N entry shift register, a loadable string register, a big mask comparator to match the loaded string with the input string.
Hi,
Actually I have 4 bit continuous data stream at 250 MHz and I want to check MAC Address of both destination(48 bit) and source(48 bit) which is together of 96 bit long before starting the payload.
This is how I tried to check:

Code Verilog - [expand]
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
input [3:0] ENET0_RX_DATA;
output [3:0] payload;
reg [3:0] input_data [0:23];
reg [4:0] index = 0;
reg [95:0] string_check = 0;
reg trigger_for_payload = 0;
 
 
    always @ (posedge test_250_mhz)
        begin 
                index <= index + 1;
                    if (index > 23)
                        begin
                            index <= 0;
                        end
                input_data[index] <= ENET0_RX_DATA;
                    
        end
        
    always @ (posedge test_250_mhz)
        begin
                if (index == 0)
                    begin
                      
                        string_check <= {input_data[0], input_data[1], input_data[2], input_data[3], input_data[4], input_data[5], input_data[6], input_data[7], 
                        input_data[8], input_data[9], input_data[10], input_data[11], input_data[12], input_data[13], input_data[14], input_data[15],
                        input_data[16], input_data[17], input_data[18], input_data[19], input_data[20], input_data[21], input_data[22], input_data[23]};
                    end
                        if (string_check == 0xe0db44d6855f0007edfe8f10) // 96 bit known source and //destination address
                            begin
                                trigger_for_payload <= 1;
                            end
                    
                end
        end
 
 
always @ (posedge test_250_mhz)
    begin
                if (trigger_for_payload == 1) 
                   begin
                           payload <= ENET0_RX_DATA
                   end
        end



but I couldn't understand how to rotate/shift at the same time while comparing the string?
 

but I couldn't understand how to rotate/shift at the same time while comparing the string?
The problem you are having looks to be with how to pipeline a design.

Currently you are implementing each function that is required, but as individual functions, which must now interact in a pipeline.

You are using an index to demultiplex, when you should just use a shift register. Then you had registers holding values for string_check, trigger_for_payload, and payload, but none of them are fed from pipeline registers to align what they are each doing. e.g. Unless ENET0_RX_DATA doesn't start outputting the payload for what looks like 2 clock cycles you'll be sending the payload missing the first two pieces of data, because you didn't delay the data to match the control pipeline of string_check and trigger_for_payload.

Do you have a testbench? You should write one if you don't have one. And post both if you have problems you don't understand or can't solve.
 

The problem you are having looks to be with how to pipeline a design.
Hi this seems to be very complicated.

Can I use state machine for this purpose?
I tried in this way but not sure whether this is correct way or not.

Code Verilog - [expand]
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
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
// string to check from 4 bit continuous input:  0xe0db44d6855f0007edfe8f10
// once this string(MAC Address of SRC and DST) identified,  start payload.
 
 
localparam [4:0] IDLE        = 5'd0;
localparam [4:0] STATE_0     = 5'd1;
localparam [4:0] STATE_1     = 5'd2;
localparam [4:0] STATE_2     = 5'd3;
localparam [4:0] STATE_3     = 5'd4;
localparam [4:0] STATE_4     = 5'd5;
localparam [4:0] STATE_5     = 5'd6;
localparam [4:0] STATE_6     = 5'd7;
localparam [4:0] STATE_7     = 5'd8;
localparam [4:0] STATE_8     = 5'd9;
localparam [4:0] STATE_9     = 5'd10;
localparam [4:0] STATE_10    = 5'd11;
localparam [4:0] STATE_11    = 5'd12;
localparam [4:0] STATE_12    = 5'd13;
localparam [4:0] STATE_13    = 5'd14;
localparam [4:0] STATE_14    = 5'd15;
localparam [4:0] STATE_15     = 5'd16;
localparam [4:0] STATE_16     = 5'd17;
localparam [4:0] STATE_17     = 5'd18;
localparam [4:0] STATE_18     = 5'd19;
localparam [4:0] STATE_19     = 5'd20;
localparam [4:0] STATE_20     = 5'd21;
localparam [4:0] STATE_21     = 5'd22;
localparam [4:0] STATE_22     = 5'd23;
 
 
input [3:0] ENET0_RX_DATA;
output [3:0] payload;
reg     [4:0]   state;
reg     trigger_for_payload;
 
always @ (posedge test_250_mhz or posedge clock_reset)
begin
    if(clock_reset)
    begin
        state           <= IDLE;
    end
    else
    begin
        case(state)
        IDLE:
        begin
            if(ENET0_RX_DATA == 0xe)
                begin
                    state <= STATE_0;
                end
            else
                begin
                    state <= IDLE;
                end
            
        end
        STATE_0:
         begin
            if(ENET0_RX_DATA == 0x0)
                begin
                    state <= STATE_1;
                end
            else
                begin
                    state <= IDLE;
                end
            
        end
        
       
        STATE_1:
         begin
            if(ENET0_RX_DATA == 0xd)
                begin
                    state <= STATE_2;
                end
            else
                begin
                    state <= IDLE;
                end
            
        end
        STATE_2:
         begin
            if(ENET0_RX_DATA == 0xb)
                begin
                    state <= STATE_3;
                end
            else
                begin
                    state <= IDLE;
                end
            
        end
        STATE_3:
        begin
            if(ENET0_RX_DATA == 0x4)
                begin
                    state <= STATE_4;
                end
            else
                begin
                    state <= IDLE;
                end
            
        end
        STATE_4:
         begin
            if(ENET0_RX_DATA == 0x4)
                begin
                    state <= STATE_5;
                end
            else
                begin
                    state <= IDLE;
                end
            
        end
        STATE_5:
         begin
            if(ENET0_RX_DATA == 0xd)
                begin
                    state <= STATE_6;
                end
            else
                begin
                    state <= IDLE;
                end
            
        end
        STATE_6:
        begin
            if(ENET0_RX_DATA == 0x6)
                begin
                    state <= STATE_7;
                end
            else
                begin
                    state <= IDLE;
                end
            
        end
        STATE_7:
         begin
            if(ENET0_RX_DATA == 0x8)
                begin
                    state <= STATE_8;
                end
            else
                begin
                    state <= IDLE;
                end
            
        end
        STATE_8:
         begin
            if(ENET0_RX_DATA == 0x5)
                begin
                    state <= STATE_9;
                end
            else
                begin
                    state <= IDLE;
                end
            
        end
        STATE_9:
         begin
            if(ENET0_RX_DATA == 0x5)
                begin
                    state <= STATE_10;
                end
            else
                begin
                    state <= IDLE;
                end
            
        end
        STATE_10:
         begin
            if(ENET0_RX_DATA == 0xf)
                begin
                    state <= STATE_11;
                end
            else
                begin
                    state <= IDLE;
                end
            
        end
        STATE_11:
         begin
            if(ENET0_RX_DATA == 0x0)
                begin
                    state <= STATE_12;
                end
            else
                begin
                    state <= IDLE;
                end
            
        end
        STATE_12:
         begin
            if(ENET0_RX_DATA == 0x0)
                begin
                    state <= STATE_13;
                end
            else
                begin
                    state <= IDLE;
                end
            
        end
        STATE_PW_13:
        begin
            if(ENET0_RX_DATA == 0x0)
                begin
                    state <= STATE_14;
                end
            else
                begin
                    state <= IDLE;
                end
            
        end
        STATE_14:
         begin
            if(ENET0_RX_DATA == 0x7)
                begin
                    state <= STATE_15;
                end
            else
                begin
                    state <= IDLE;
                end
            
        end
        STATE_15:
         begin
            if(ENET0_RX_DATA == 0xe)
                begin
                    state <= STATE_16;
                end
            else
                begin
                    state <= IDLE;
                end
            
        end  
      STATE_16:
       begin
            if(ENET0_RX_DATA == 0xd)
                begin
                    state <= STATE_17;
                end
            else
                begin
                    state <= IDLE;
                end
            
        end
      STATE_17:
       begin
            if(ENET0_RX_DATA == 0xf)
                begin
                    state <= STATE_18;
                end
            else
                begin
                    state <= IDLE;
                end
            
        end
      STATE_18:
       begin
            if(ENET0_RX_DATA == 0xe)
                begin
                    state <= STATE_19;
                end
            else
                begin
                    state <= IDLE;
                end
            
        end
      STATE_19:
       begin
            if(ENET0_RX_DATA == 0x8)
                begin
                    state <= STATE_20;
                end
            else
                begin
                    state <= IDLE;
                end
            
        end
      STATE_20:
       begin
            if(ENET0_RX_DATA == 0xf)
                begin
                    state <= STATE_21;
                end
            else
                begin
                    state <= IDLE;
                end
            
        end
      STATE_21:
       begin
            if(ENET0_RX_DATA == 0x1)
                begin
                    state <= STATE_22;
                end
            else
                begin
                    state <= IDLE;
                end
            
        end
      STATE_22:
       begin
            if(ENET0_RX_DATA == 0x0)
                begin
                    trigger_for_payload <= 1;
                end
            
            
        end
        default:
        begin
            state <= IDLE;
        end
        endcase
    end
end
 
always @ (posedge test_250_mhz)
    begin
                if (trigger_for_payload == 1) 
                   begin
                           payload <= ENET0_RX_DATA
                   end
        end

 
Last edited:

Such a simple state machine is not the solution. You can have a "false start" just before the correct sequence. The state machine can then be in some other state than "IDLE" when the first wanted data arrives. In software, it is common to have complex state machines for this task. Look at "lexical analyzers". "flex" is one example.

For hardware, the shift register+comparators suggested by ads-ee is a much simpler solution.
 

It's said that the "continuous data stream" is ethernet data. So packet respectively frame synchronization takes place before the MAC fields. Any state/index counter has to refer to it.
 

It's said that the "continuous data stream" is ethernet data. So packet respectively frame synchronization takes place before the MAC fields. Any state/index counter has to refer to it.
Hi FvM,
I have udp data stream. Can I use "udp length field" and also the "frame length size" together for synchronization of frames by setting counter depending on those 2 parameters?
 

Hi this seems to be very complicated.

Can I use state machine for this purpose?

I would avoid using a state machine altogether. As you are finding out it's much more complicated to do it the "software way" in HDL.

The last design I received UDP data, the GEMAC that we were using output a data valid signal as I recall. I edge detected the data valid and used that to start a counter for the frame. I used the count value to determine which part of the header I was at and a shift register to turn the incoming data into parallel data. In your case it would turn the 4-bit data into 48-bit source/destination addresses.

Basically all I had were a counter, a shift register, pipeline registers to align (delay) signals, and a bunch of other registers and compare logic to make decisions like is this a VLAN etc. The only "state" information in the design was the counter and the control of when it finished counting and resetting back to 0.
 

You are using an index to demultiplex, when you should just use a shift register. Then you had registers holding values for string_check, trigger_for_payload, and payload, but none of them are fed from pipeline registers to align what they are each doing.
Hi
sorry but I am not able to formulate code for shift register in this case.
could you please provide some hints.
 

Hi
sorry but I am not able to formulate code for shift register in this case.
could you please provide some hints.

Here is an example of a byte shift register that can shift 32 bytes


Code Verilog - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
reg [7:0] my_array [0:31]; // 32-element array of bytes
 
always @ (posedge clk) begin
  // shift register code
  for (i=0;i<32;i=i+1) begin
    if (i==0) begin
      my_array[i] <= input_byte;
    end else begin
      my_array[i] <= my_array[i-1];
    end
  end
end
// the above is the equivalent of...(with loop unrolled)
always @(posedge clk) begin
  my_array[0] <= input_byte;
  my_array[1] <= my_array[0];
  //...
  my_array[31] <= my_array[30];
end
// another cumbersome method...
always @ (posedge clk) begin
  // note ... means there are a lot of my_array[*] in between, that I'm too lazy to write out
  {my_array[31], my_array[30], .... , my_array[1], my_array[0]} <= {my_array[30], ... , my_array[0], input_byte};
end

 
Here is an example of a byte shift register that can shift 32 bytes
Thanks for the code.
I have one question according to this:
I am not sure if I can check my string (0xe0db44d6855f0007edfe8f10 // 96 bit known source and destination address)
like below and set trigger:

Code Verilog - [expand]
1
2
3
4
5
6
7
8
always @ (posedge clock)
begin
        if (my_array == my_string)
            begin
                trigger_for_payload <= 1;
            end
                        
end


and reset of index 0,1, ...31 is not needed?
Note: Here my_array mean {my_array[0], my_array[1], ...my_array[31]} and assuming my_string is of same size of my_array.
 
Last edited:

I am not sure if I can check my string (0xe0db44d6855f0007edfe8f10 // 96 bit known source and destination address)
like below and set trigger:

Code Verilog - [expand]
1
2
3
4
5
6
7
8
always @ (posedge clock)
begin
        if (my_array == my_string)
            begin
                trigger_for_payload <= 1;
            end
                        
end


and reset of index 0,1, ...31 is not needed?
Note: Here my_array mean {my_array[0], my_array[1], ...my_array[31]} and assuming my_string is of same size of my_array.

Drats, I forgot about you wanting to compare that string of yours to a 96-bit value.

Then you should perform the shift as follows using the same example shift register of bytes with 32 deep shift register.

Code Verilog - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
localparam data_width = 8;
localparam shift_leng = 32;
reg [data_width*shift_leng-1:0]  shift_reg;
 
// most significant byte is in the highest bits (i.e. the first value
// that was shifted in).
always @ (posedge clk) begin
  shift_reg[data_width-1:0] <= input_data[data_width-1:0];
  for (i=1;i<shift_leng;i=i+1) begin
    shift_reg[data_width*i +:data_width] <= shift_reg[data_width*(i-1) +:data_width];
  end
end
 
// then the comparison is simply
if (shift_reg == 256'h1234_1234_1234_1234_1234_1234_1234_1234) begin
  // code that does something when shift_reg content matches.
end


I didn't post this code the first time because I thought the slicing might confuse you, as it may not necessarily look like a shift register to a novice when written like this.

The previous code would have required a compare like this:

Code Verilog - [expand]
1
{my_array[31], my_array[30]....my_array[1],my_array[0]} == 256'h1234_1234_1234_1234_1234_1234_1234_1234

 
Try modular appoach, first make a FIFO register of the length of bytes u need to compare, on every byte updation compare the FIFO register with required bytes, FSM is an efficient and systematic way of doing it, u should give it a try, I did the same kind of thing with UART, FIFO register worked for me
your satates may b, if(header_match) nstate
if(msb_match) n state etc
 

Try modular appoach, first make a FIFO register of the length of bytes u need to compare, on every byte updation compare the FIFO register with required bytes, FSM is an efficient and systematic way of doing it, u should give it a try, I did the same kind of thing with UART, FIFO register worked for me
your satates may b, if(header_match) nstate
if(msb_match) n state etc

Hi,
I tried FSM as mentioned in post #5 of this thread but unfortunately I didn't get expected result.
Could you please post the major part of code.
 

Hi,
I tried FSM as mentioned in post #5 of this thread but unfortunately I didn't get expected result.
Could you please post the major part of code.

fouwad was using a UART === SLOW stuff. You are trying to work with Ethenet UDP frames. If you don't mind increasing the latency go ahead and use an FSM with a store and forward buffer to store UDP frames while you parse the header using an FSM.

I've already said you should use a pipelined approach as that results in the smallest amount of latency and is very easy to implement (once you understand the concept of pipelining). I've used UDP in multiple projects and never once used an FSM to extract the headers and route the packets.
 
Drats, I forgot about you wanting to compare that string of yours to a 96-bit value.

Then you should perform the shift as follows using the same example shift register of bytes with 32 deep shift register.
Hi, Thanks. String checking is working using this pipeline method.

For next step to extract payload and synchronize the UDP Frame. I tried this way:


Code Verilog - [expand]
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
// payload starts after 42 byte header. Frame = 14 byte, IP = 20 byte, UDP = 8 byte.
// and I am checking just first 12 byte of Frame header which is combination of source(6 byte) and destination(6 byte) //MAC Address. This means my payload must start after 30 byte once string is checked.
 
// For Frame synchronization, I am extracting UDP Length field and assigning to a counter as:
// counter <= UDP Length field - 8; 
// and decrementing counter and once counter is zero start new Frame (string check)
 
reg trigger = 0;
reg [95:0] string_check = 0;
reg [3:0] payload;
reg [3:0] extract_length [51:54];
reg trigger_reset = 0;
reg [15:0] count = 0;
reg [7:0] ct_extract_leng = 0;
 
reg [7:0] count_sec = 0;
 
localparam data_width = 4;
localparam shift_leng = 24;
reg [4:0] i = 0;
 
 
reg [data_width*shift_leng-1:0]  shift_reg;
 
// most significant byte is in the highest bits (i.e. the first value
// that was shifted in).
always @ (posedge test_250_mhz) 
begin
  shift_reg[data_width-1:0] <= ENET0_RX_DATA;
      for (i=1;i<shift_leng;i=i+1) 
          begin
             shift_reg[data_width*i +:data_width] <= shift_reg[data_width*(i-1) +:data_width];
          end
            end
            
 
 
// then the comparison is simply
if (shift_reg == 96'h0070DEFFF8010EBD556DF8F5)
  // code that does something when shift_reg content matches.
      begin
        trigger <= 1;   
                
      end
      
      if (trigger_reset == 1)
            begin
                trigger <= 0;   
            end
 end 
 
 
    // to extract payload length from UDP length field. UDP Payload length field is 26 byte after string check is done. // i.e. 52 nibble. but there is one register delay. So, I took 51, 52, 53, 54 nibble.  
    always @ (posedge test_250_mhz)
        begin
              if (trigger == 1)
                  begin
                  
                      ct_extract_leng <= ct_extract_leng + 1;
                        if ((ct_extract_leng > 50) && (ct_extract_leng < 55))
                            begin
                                
                                        extract_length [ct_extract_leng] <= ENET0_RX_DATA;
                            end
                                    
                                    if (ct_extract_leng > 54)
                                              begin
                                                    ct_extract_leng <= 0;
                                              end
                    end 
        end  
        
    //  resetting the Frame for Frame synchronization         
    always @ (posedge test_250_mhz)
        begin
        count <= {extract_length[51], extract_length[52], extract_length[53], extract_length[54]} - 8 ;
         count <=  count - 1 ;      
                
                    if (count == 0)
                        begin
                            trigger_reset <= 1;
                            
                        end
                    else
                        begin
                            trigger_reset <= 0;                                             
                        end
                                              
                        
                end
 
 
                
    // Taking the payload data          
    always @ (posedge test_250_mhz)
        begin
              if (trigger == 1)
                  begin
                        count_sec <= count_sec + 1; 
                            if (count_sec > 60)
                                begin
                                    Rx_fifo_write <= 1;
                                    payload <= ENET0_RX_DATA;
                                end
                            else
                                begin
                                    Rx_fifo_write <= 0;
                                    count_sec <= 0;
                                end
 
                  end
        end



but I didn't get anything in payload. What's wrong here?
 
Last edited:

Do you have a testbench to drive this code snippet?

How about providing the testbench and code that can be simulated, and I can try taking a look at it.

Here is another case of using the wrong structure to do something that is inherently a simple shift register.
Code:
if ((ct_extract_leng > 50) && (ct_extract_leng < 55)) begin
  extract_length [ct_extract_leng] <= ENET0_RX_DATA;
end
This is creating a set of four 4-bit registers that are being indexed using a counter. So the code has to be logic that does the following:
Code:
extract_length[51] <= (ct_extract_leng == 51) ? ENET0_RX_DATA : extract_length[51];
if it was coded like a shift register there would only be a shift enable when ct_extrat_leng is between 50 and 55 and the extract_length would have the same data as you are getting now. The way you are approaching the problem is very software like with all the indexing.
 

Status
Not open for further replies.

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top