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.

[SOLVED] cannot match operand(s) in the condition to the corresponding edges in the enclosing

Status
Not open for further replies.

verilog_vhdl7

Newbie level 5
Joined
Nov 15, 2014
Messages
9
Helped
0
Reputation
0
Reaction score
0
Trophy points
1
Activity points
103
Hi

This is a code written for baud generator. The problem is i get the following error
//cannot match operand(s) in the condition to the corresponding edges in the enclosing event control of always construct //

First thing is what does this error means???

i have this multiple begin end blocks what does this impact in the following code.
I understand that begin end are sequential. can anyone explain the exact process flow???



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
module baud_gen(baud_clk , clk,rst);
parameter l = 77;
parameter m = 78;
parameter n = 156;
parameter o = 155;
 
input     clk;
input     rst;
 
wire      clk;
wire      rst;
 
output    baud_clk;
reg       clk_out;
reg [7:0] count;
 
wire      baud_clk;
 
always @ (posedge clk or negedge rst)
 begin
   if(!rst)
      begin
        clk_out  <= 1'bz;
        count    <= 8'b0;;
       end  
      else
         begin
           count  <= count + 1;
           end
              
           if (count > 0 && count < m)
               begin
                 clk_out <=1'b0;
                 end 
                   else if (count >l && count < n) 
                      begin
                      clk_out <=1'b1;
                     end
                      
                  
                if (count > o)
                  begin
                   count <= 8'b0;
                  end    
                     else
                       begin
                           count <= count;
                       end
        end 
assign baud_clk = clk_out;      
endmodule

Thank you
 
Last edited by a moderator:

You didn't follow the Verilog template for synthesizable sequential code

Code:
always @ (posedge clk or negedge rst)
  begin
    if(!rst)
      begin
        clk_out  <= 1'bz;
        count    <= 8'b0;;
      end  
    else
      begin
        count  <= count + 1;
        // all additional clock edge sensitive actions must go [B]here[/B]      
      end
  end
 
i did not get you.....can u explain me in an elaborated way......like i have used multiple begin end blocks...how is it affecting my design????? i will list out my questions as i m migrating from vhdl to verilog....

1. after the reset condition is executed and when it goes to else....why the it is not executing the first if.....
2. if i m putting in begin - end block what are the steps of execution
3. after incrementing the count in line 27 why is it showing the error in line 31 and what does this error means???
4. i am getting confused with begin end blocks and i m not able to understand the order of execution.

thank you
regards
 

Not a direct answer, but more an observation regarding code quality and maintainability...

4. i am getting confused with begin end blocks and i m not able to understand the order of execution.

If you have trouble with it, chances are someone else will also have trouble understanding it. That is usually a hint that some work is in order to improve readability & long term happiness (aka maintainability).

In this particular case it's sort of okay-ish, but you might want to fix the indentation. And maybe a comment or two describing what a particular if/else branch is doing. That will help you in understanding it right now, and it help you (or someone after you) at some point in the future.

And FvM's point is that if you want to infer hardware, then you have to write code according to a specific template. Why? Because the synthesizer that reads your verilog only understands a very limited number of descriptions that it can actually turn into hardware. Usually the idea is that you a hardware design (think schematic with logic elements), and AFTER you have this design all done ... only then do you start writing code. Turning that design into a hardware description of that design, which is then synthesized.

I understand that begin end are sequential.
You may want to explain what you mean here, because in the strict sense this is absolutely NOT true. And if you think what I think you are thinking, then this is a fun source of errors. They are sequential in the sense that the parser read the file line by line. But best think of the resulting hardware as "runs in parallel unless otherwise dictated by the hardware description".

Does anyone know of a good reference highlighting the usual differences between imperative programming (sequential) versus hardware description (generally parallel)?
 

Reformated to show what is wrong with the code...

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
module baud_gen #(
  parameter l = 77;
  parameter m = 78;
  parameter n = 156;
  parameter o = 155;
) (
  output    baud_clk,
  input     clk,
  input     rst
);
 
reg       clk_out;
reg [7:0] count;
 
wire      baud_clk;
 
always @ (posedge clk or negedge rst) begin
 
    if (!rst) begin
        clk_out  <= 1'bz;
        count    <= 8'b0;;
    end else begin
        count  <= count + 1;
    end
              
    if (count > 0 && count < m) begin
        clk_out <=1'b0;
    end else if (count >l && count < n) begin
        clk_out <=1'b1;
    end
                      
    if (count > o) begin
        count <= 8'b0;
    end else begin
        count <= count;
    end
 
end 
 
assign baud_clk = clk_out;      
 
endmodule


Notice that the both clk_out and count are specified in multiple if statements that will lead to multiple driver problems in the code.

Your use of the begin end is not correct, begin end makes the code between the keywords execute as a single block of code. So usage of begin end is to allow things like if statements which work on the next line (like C) to also work on multiple lines:


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
// works;
if (a) b <= c;
else   b <= d;
 
// doesn't work, syntax error
if (a) b <= c;
      e <= f;
else  b <= d;
      e <= g;
 
// fixed using begin-end
if (a) begin b <=c; e <= f; end
else  begin b <= d; e <= g; end
 
// or formatted the way I like
if (a) begin
  b <= c:
  e <= f;
end else begin
  b <= d;
  e <= g;
end

 

Thanks for reformatting. I cannot be bothered these days to do that. Want solution? Present problem better. Life's too short and all that. Well that, or pay money (aka job) to compensate for the annoyance. ;-)

At any rate, this is indeed the classic problem of thinking in terms of software programming versus hardware description. And since this problem comes up often enough, do we have any good references explaining how to think hardware instead of software? I ask because 1) it's relevant to the OP and 2) we get enough software types around here so a good reference will save us all a good bit of typing. :)

This code indeed attempts to create two logic sections in parallel and they are both attempting to drive the same clk_out signal, which is a no-no.

I'm not going to post the exact solution, but give you an outline of what you may want to do to solve it.


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
always @ (posedge clk or negedge rst) begin
 
    if (!rst) begin
        clk_out  <= 1'bz; // you sure about this?
        count    <= 8'b0;
    end else begin
        count  <= count + 1;
        // That stuff below should go here. After you do some work on it.
    end
 
    //
    // All the functionality below should be put in the above "else block"
    // Do not simply cut/paste, but actually think about it.
    // Why think? Because cut/paste result will not work, that's why! ;)
    //
    //if (count > 0 && count < m) begin
    //    clk_out <=1'b0;
    //end else if (count >l && count < n) begin
    //    clk_out <=1'b1;
    //end
                      
    //if (count > o) begin
    //    count <= 8'b0;
    //end else begin
    //    count <= count;
    //end
 
end



Incidentally, note how this suggested code template looks suspiciously much like the code template FvM suggested earlier. If I'm not mistaken this template is for synchronous logic with an asynchronous reset.
 

Thanks for reformatting. I cannot be bothered these days to do that. Want solution? Present problem better. Life's too short and all that. Well that, or pay money (aka job) to compensate for the annoyance. ;-)

I actually think that quite a few posters would benefit from adhering to a set of formatting standards that would help them spot problems. For one they shouldn't have anything but spaces in there code NO TABS.

I've used a C like indenting of my begin end blocks for decades because it makes the code more compact and I just look for matching if-end sections. Doing stuff like this has reduced the incidence of mismatched if-else if-else problems in my code to pretty much 0. The majority of problems I encounter in my code syntax wise are missing ';'s (or ;=>:).
 

Thank you everyone for your prompt reply. I got my mistake but still have some doubts. I am mentioning my doubts in commented lines.


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
always @ (posedge clk or negedge rst) begin
 
    if (!rst) begin
        clk_out  <= 1'bz;
        count    <= 8'b0;;
    end else begin
        count  <= count + 1;     // count is incremented here with begin end block and is controlled by clock //
    end
              
    if (count > 0 && count < m) begin  
 
    // is this if statement not controlled by clock???? why after incrementing count  
       above this is not getting executed???? and about multiple drivers for clock_out   
       there must be 4 comparators generating clk_out signal thats why multiple drivers
       is my understanding right???? because if
       ststements are sequential. because once count is incremented will it not checking 
       all if sequentially???? because i am thinking that way...i dont know c 
       programming so please bear with my doubts....why are begin - end blocks
       mainly used...in books it is mentioned if u have multiple statements use
       begin - end blocks//                    
                                                               
           clk_out <=1'b0;   
                
    end else if (count >l && count < n) begin
        clk_out <=1'b1;
    end
                      
    if (count > o) begin
        count <= 8'b0;
    end else begin
        count <= count;
    end
 
end 
 
assign baud_clk = clk_out;      
 
endmodule

 
Last edited by a moderator:

You did it again. You're still perfectly ignoring the suggestions that have been given by all contributors to this thread reagrding the required structure of sequential blocks.
// All the functionality below should be put in the above "else block"
// Do not simply cut/paste, but actually think about it.
// Why think? Because cut/paste result will not work, that's why! ;)

Technically, the code won't compile, with a similar error message as quoted in your first post.

The problem is in the assignment of regs count and clk_out. They are either assignment by the asynchronous reset or on the rising clock edge. The mutual exclusive character of else is required here. The following assignments in your code outside the if ... else construct would be valid both for a falling rst edge and a rising clk edge which is not possible in hardware terms.

Code:
    if (!rst) begin
        clk_out  <= 1'bz;
        count    <= 8'b0;;
    end else begin
        count  <= count + 1;     // count is incremented here with begin end block and is controlled by clock //
    end

My general suggestion: Get a Verilog text book, review the chapters about modelling of synchronous registers and required syntax of synthesizable Verilog.
 
The following code you wrote:

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
always @ (posedge clk or negedge rst) begin
 
    if (!rst) begin
        clk_out  <= 1'bz;
        count    <= 8'b0;;
    end else begin
        count  <= count + 1;     // count is incremented here with begin end block and is controlled by clock //
    end
              
    if (count > 0 && count < m) begin  
 
    // is this if statement not controlled by clock???? why after incrementing count  
       above this is not getting executed???? and about multiple drivers for clock_out   
       there must be 4 comparators generating clk_out signal thats why multiple drivers
       is my understanding right???? because if
       ststements are sequential. because once count is incremented will it not checking 
       all if sequentially???? because i am thinking that way...i dont know c 
       programming so please bear with my doubts....why are begin - end blocks
       mainly used...in books it is mentioned if u have multiple statements use
       begin - end blocks//                    
                                                               
           clk_out <=1'b0;   
                
    end else if (count >l && count < n) begin
        clk_out <=1'b1;
    end
                      
    if (count > o) begin
        count <= 8'b0;
    end else begin
        count <= count;
    end
 
end 
 
assign baud_clk = clk_out;      
 
endmodule


Is equivalent to the following:

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
// code of first if is independent of the other parallel if statements
always @ (posedge clk or negedge rst) begin
    if (!rst) begin
        clk_out  <= 1'bz;
        count    <= 8'b0;;
    end else begin
        count  <= count + 1;     // count is incremented here with begin end block and is controlled by clock //
    end
end
 
// second if statement is in parallel with first if statement, but this one conflicts
// with the previous one as it shares an output with the other if (multiple driver error).
always @ (posedge clk or negedge rst) begin              
    if (count > 0 && count < m) begin  
        clk_out <=1'b0;   
    end else if (count > l && count < n) begin
        clk_out <=1'b1;
    end
end
 
// third if that is in parallel with previous two if statements.
// this also shares a output with the first if statement and will also result in
// a multiple driver error
always @ (posedge clk or negedge rst) begin              
   if (count > o) begin
        count <= 8'b0;
    end else begin
        count <= count;
    end
end
 
endmodule



You seem to be trying to think of Verilog scheduling and execution of code as an imperative program. As Verilog represents a description of hardware: registers, logic gates, memories, and interconnect (wires), it isn't an imperative programming language. All your if statements in your edited version are executed in parallel on each positive edge of the clk or the negative edge of rst, but as you are attempting to set the value of both count and clk_out from different processes it has a multiple driver issue and doesn't simulate correctly.

To simplify your thinking only have one output for any always block and that always block should only have a single statement, which means you don't need begin-end on the always block.

e.g.

Code Verilog - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
always @ (posedge clk or negedge rst)
  // priority encoded if statement rst has highest priority, and count < 30 has the lowest,
  // resetting count back to 0 is the default
  if (!rst) begin   // poor name choice should make it obvious that it is active-low e.g. rstb, rstn, rst_n, rst_b, etc
    count <= 0;
  end else if (count == 5) begin // if count is 5 then it jumps to 7
    count <= 7;
  end else if (count < 12) begin // as long as count is less than 12 but not 5 it increments by 1
    count <= count + 1;
  end else if (count < 30) begin // as long as count is less than 30 not equal to 5 but more than 12 it increments by 2
    count <= count + 2;
  end else begin // once count reaches 30 or more it will reset back to 0 and start over again.
    count <= 0;
  end



As you can see all of the assignments for count are in a single always block not distributed across multiple if statements.

What you were thinking was that the statements would follow the imperative programming paradigm where any instance of an assignment to count following the first if statement would be immediately executed in sequential order after the first if statement was executed, that doesn't represent any kind of hardware.

You should be thinking of a hardware counter as represented (described) by a register (flip-flops) that holds the current count value, which is fed by a logic cone that computes the next count value from the current count value. Which is exactly what the count description I wrote does: count is a register with a large logic cone (the priority encoded if statement) feeding the count.

Regards
 
Nice explanation of the problem. :thumbsup: And you just answered my previous question ...

Does anyone know of a good reference highlighting the usual differences between imperative programming (sequential) versus hardware description (generally parallel)?

I think in the future I will use this thread as an example. Because it's a classic example of someone thinking in terms of imperative programming, while they should be thinking in terms of parallel hardware.

And now hopefully verilog_vhdl7 understands what he's doing wrong, so that we also have a good test of the teaching effectiveness of your explanation. Because I think it's a good explanation, but I already know what you are trying to explain. :p The real test is if it works on someone who doesn't know yet. ;)
 

Status
Not open for further replies.

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top