This site contains a lot of Free E-Books and all information about Electronics Enginering, EBooks, Algorithms, Software Books & Complete Micro Processor Guide
Showing posts with label Coding. Show all posts
Showing posts with label Coding. Show all posts
Monday, April 28, 2008
“behavioural model” & “structural model”
The phrases "behavioural model" and "structural model" are commonly used for what we'll call "high-level models" and "synthesizable models". In most cases, what people call structural code contains both structural and behavioural code. The technically correct definition of a structural model is an HDL program that contains only component instantiations and generate statements. Thus, even a program with c <= a AND b; is, strictly speaking, behavioural.
Verilog Shift Register with Test Bench
module shifter (result, value_in, direction, type, length);
output [7:0] result;
input [7:0] value_in;
input direction;
input [1:0] type;
input [2:0] length;
reg [7:0] value_out;
always @(value_in or direction or type or length)
begin
case ({direction, type})
3'b0_00: value_out = value_in >> length;
3'b0_01: case(length)
3'b000: value_out = value_in;
3'b001: value_out = {value_in[7], value_in[7:1]};
3'b010: value_out = {{2{value_in[7]}}, value_in[7:2]};
3'b011: value_out = {{3{value_in[7]}}, value_in[7:3]};
3'b100: value_out = {{4{value_in[7]}}, value_in[7:4]};
3'b101: value_out = {{5{value_in[7]}}, value_in[7:5]};
3'b110: value_out = {{6{value_in[7]}}, value_in[7:6]};
3'b111: value_out = {{7{value_in[7]}}, value_in[7]};
endcase
3'b0_10: case(length)
3'b000: value_out = value_in;
3'b001: value_out = {value_in[0], value_in[7:1]};
3'b010: value_out = {value_in[1:0], value_in[7:2]};
3'b011: value_out = {value_in[2:0], value_in[7:3]};
3'b100: value_out = {value_in[3:0], value_in[7:4]};
3'b101: value_out = {value_in[4:0], value_in[7:5]};
3'b110: value_out = {value_in[5:0], value_in[7:6]};
3'b111: value_out = {value_in[6:0], value_in[7]};
endcase
3'b1_00: value_out = value_in <<>
3'b1_01: value_out = {value_in[7], value_in[6:0] <<>
3'b1_10: case(length)
3'b000: value_out = value_in;
3'b001: value_out = {value_in[6:0], value_in[7]};
3'b010: value_out = {value_in[5:0], value_in[7:6]};
3'b011: value_out = {value_in[4:0], value_in[7:5]};
3'b100: value_out = {value_in[3:0], value_in[7:4]};
3'b101: value_out = {value_in[2:0], value_in[7:3]};
3'b110: value_out = {value_in[1:0], value_in[7:2]};
3'b111: value_out = {value_in[0], value_in[7:1]};
endcase
default: value_out = value_in;
endcase
end
assign result = value_out;
endmodule
--
module testbench;
reg clk, direction;
reg [1:0] type;
reg [2:0] length;
reg [7:0] value_in;
wire [7:0] result;
shifter shifter1(result, value_in, direction, type, length);
initial
begin
clk = 0;
direction = 1;
type = 1;
length = 3;
value_in = 'b11110110;
$display("direction = %d type = %d length = %d value_in = %b", direction, type, length, value_in);
#10 $display("done");
$finish;
end
always #5 clk = !clk;
always @(posedge clk)
$strobe("result: %b", result);
endmodule
output [7:0] result;
input [7:0] value_in;
input direction;
input [1:0] type;
input [2:0] length;
reg [7:0] value_out;
always @(value_in or direction or type or length)
begin
case ({direction, type})
3'b0_00: value_out = value_in >> length;
3'b0_01: case(length)
3'b000: value_out = value_in;
3'b001: value_out = {value_in[7], value_in[7:1]};
3'b010: value_out = {{2{value_in[7]}}, value_in[7:2]};
3'b011: value_out = {{3{value_in[7]}}, value_in[7:3]};
3'b100: value_out = {{4{value_in[7]}}, value_in[7:4]};
3'b101: value_out = {{5{value_in[7]}}, value_in[7:5]};
3'b110: value_out = {{6{value_in[7]}}, value_in[7:6]};
3'b111: value_out = {{7{value_in[7]}}, value_in[7]};
endcase
3'b0_10: case(length)
3'b000: value_out = value_in;
3'b001: value_out = {value_in[0], value_in[7:1]};
3'b010: value_out = {value_in[1:0], value_in[7:2]};
3'b011: value_out = {value_in[2:0], value_in[7:3]};
3'b100: value_out = {value_in[3:0], value_in[7:4]};
3'b101: value_out = {value_in[4:0], value_in[7:5]};
3'b110: value_out = {value_in[5:0], value_in[7:6]};
3'b111: value_out = {value_in[6:0], value_in[7]};
endcase
3'b1_00: value_out = value_in <<>
3'b1_01: value_out = {value_in[7], value_in[6:0] <<>
3'b1_10: case(length)
3'b000: value_out = value_in;
3'b001: value_out = {value_in[6:0], value_in[7]};
3'b010: value_out = {value_in[5:0], value_in[7:6]};
3'b011: value_out = {value_in[4:0], value_in[7:5]};
3'b100: value_out = {value_in[3:0], value_in[7:4]};
3'b101: value_out = {value_in[2:0], value_in[7:3]};
3'b110: value_out = {value_in[1:0], value_in[7:2]};
3'b111: value_out = {value_in[0], value_in[7:1]};
endcase
default: value_out = value_in;
endcase
end
assign result = value_out;
endmodule
--
module testbench;
reg clk, direction;
reg [1:0] type;
reg [2:0] length;
reg [7:0] value_in;
wire [7:0] result;
shifter shifter1(result, value_in, direction, type, length);
initial
begin
clk = 0;
direction = 1;
type = 1;
length = 3;
value_in = 'b11110110;
$display("direction = %d type = %d length = %d value_in = %b", direction, type, length, value_in);
#10 $display("done");
$finish;
end
always #5 clk = !clk;
always @(posedge clk)
$strobe("result: %b", result);
endmodule
Verilog Awareness
* Consider a 2:1 mux , what will be the output F if the Select (sel) is "X" ?
* What is the difference between blocking and nonblocking assignment? Explain with a simple example?
* What is the difference between wire and a reg data type?
* Write code for async reset D-Flip-Flop, Shift Register.
* Write code for 2:1 MUX using different coding styles.
* Write code for parallel encoder and priority encoder.
* Different "case" usage styles! Explain.
* What is the difference between === and == ?
* Why is defparam used for ?
* What is the difference between unary operator and logical operator ?
* What is the difference between task and function ?
* What is the difference between transport and inertial delays?
* What is the difference between casex and case statements ?
* What is the difference between $monitor and $display ?
* What is the difference between compiled, interpreted, event based and cycle based simulator ?
* What is the difference between blocking and nonblocking assignment? Explain with a simple example?
* What is the difference between wire and a reg data type?
* Write code for async reset D-Flip-Flop, Shift Register.
* Write code for 2:1 MUX using different coding styles.
* Write code for parallel encoder and priority encoder.
* Different "case" usage styles! Explain.
* What is the difference between === and == ?
* Why is defparam used for ?
* What is the difference between unary operator and logical operator ?
* What is the difference between task and function ?
* What is the difference between transport and inertial delays?
* What is the difference between casex and case statements ?
* What is the difference between $monitor and $display ?
* What is the difference between compiled, interpreted, event based and cycle based simulator ?
Verilog Awareness
Differentiate between Inter assignment Delay and Inertial Delay ?
What are the different State machine Styles ? Which is better ? Why and when do we use one ove the other? Explain Disadv. and Adv.?
What is the difference between the following lines of code ?
1. reg1<= #10 reg2 ; 2. reg3 = # 10 reg 4 ; What is value of Var1 after the following assignment ? 1. reg Var1; 2. initial begin 3. Var1<= "-" 4. end What is the output of the below code? 1. module quest_for_out(); 2. 3. integer i; 4. reg clk; 5. 6. initial begin 7. clk = 0; 8. #4 $finish; 9. end 10. 11. always #1 clk = !clk; 12. 13. always @ (posedge clk) 14. begin : FOR_OUT 15. for (i=0; i < i =" i">
16. if (i == 5) begin
17. disable FOR_OUT;
18. end
19. $display ( "Current i : %g" ,i);
20. end
21. end
22. endmodule
What is the output of the below code?
1. module quest_for_in();
2.
3. integer i;
4. reg clk;
5.
6. initial begin
7. clk = 0;
8. #4 $finish;
9. end
10.
11. always #1 clk = !clk;
12.
13. always @ (posedge clk)
14. begin
15. for (i=0; i < i =" i">
16. if (i == 5) begin
17. disable FOR_IN;
18. end
19. $display ( "Current i : %g" ,i);
20. end
21. end
22. endmodule
What are the different State machine Styles ? Which is better ? Why and when do we use one ove the other? Explain Disadv. and Adv.?
What is the difference between the following lines of code ?
1. reg1<= #10 reg2 ; 2. reg3 = # 10 reg 4 ; What is value of Var1 after the following assignment ? 1. reg Var1; 2. initial begin 3. Var1<= "-" 4. end What is the output of the below code? 1. module quest_for_out(); 2. 3. integer i; 4. reg clk; 5. 6. initial begin 7. clk = 0; 8. #4 $finish; 9. end 10. 11. always #1 clk = !clk; 12. 13. always @ (posedge clk) 14. begin : FOR_OUT 15. for (i=0; i < i =" i">
16. if (i == 5) begin
17. disable FOR_OUT;
18. end
19. $display ( "Current i : %g" ,i);
20. end
21. end
22. endmodule
What is the output of the below code?
1. module quest_for_in();
2.
3. integer i;
4. reg clk;
5.
6. initial begin
7. clk = 0;
8. #4 $finish;
9. end
10.
11. always #1 clk = !clk;
12.
13. always @ (posedge clk)
14. begin
15. for (i=0; i < i =" i">
16. if (i == 5) begin
17. disable FOR_IN;
18. end
19. $display ( "Current i : %g" ,i);
20. end
21. end
22. endmodule
Verilog Blocking Vs Non Blocking, Myths and Facts
I know people who swear by blocking and some who swear by non-blocking.
So here are some thoughts.
There is very little difference between non-blocking and blocking in speed and no errors if done correctly either way.
The main differences are:
Some people like non-blocking because you can tell that a reg on the left hand side of <= is going to be a flip flop after synthesis. /* example 1a */ reg a,b,c; always @(posedge clock) begin b <= a; /* b and c will be flip flops */ c <= b; end /* example 1b */ reg a,b,c; always @(posedge clock) begin c <= b; b <= a; /* b and c will be flip flops */ end /* example 2a */ reg a,b,c; always @(posedge clock) begin b = a; c = b; /* Only c will be a flip flop,b will go away after synthesis. */ /* We could delete the 2 above assignments and replace it with c=a;b=a; In fact, b is the same as c and can be eliminated.*/ end /* example 2b */ reg a,b,c; always @(posedge clock) begin c = b; b = a; /* Both b and c will be flip flops, because these 2 lines are reversed.*/ end Example 1a, 1b and 2b are functionally the same. Example 2a is functionally different from 2b just because the order of the statements. Some people like blocking because it takes less memory in the simulator. /* example NON-BLOCKING_MEMORY */ reg a,b,c; always @(posedge clock) begin /* b will require 2 memory locations*/ b <= a; /*<---because this b memory location will hold value of a */ c <= b; /*<---and this b memory location will hold value of b before the posedge*/ end /* example BLOCKING_MEMORY */ reg a,b,c; always @(posedge clock) begin // b will require ONLY 1 memory location c = b; b = a; end Note that I am talking about SIMULATOR memory, not flip-flop count after synthesis. In most cases, the simulator has to remember the value before and after posedge clock if a reg goes between modules in order in order to "execute modules in parallel", so there may be no savings. Some people like blocking because you can see sharing of resources more readily. // example 5 reg [15:0] a,b,c,d,e,f,j,k,g,h; reg [16:0] x,y,z; always @(posedge clock) begin x = a + b + c + d + e + f + j + k; y = x + g; z = x + h; end // example 6 reg [15:0] a,b,c,d,e,f,j,k,g,h; reg [16:0] y,z; always @(posedge clock) begin y <= (a + b + c + d + e + f + j + k) + g; z <= (a + b + c + d + e + f + j + k) + h; end Even the cheapest synthesizer should share adder logic in example 5, but a slightly smarter synthesizer is required in example 6. You will have fewer problems with race conditions in SIMULATION if you always use non-blocking assignments inside always @(posedge clock) blocks where you want to have flip-flops. file xyz.v : module xyz(a,b,clk); input b,clk; output a; reg a; always @(posedge clk) a = b; endmodule file abc.v : module abc(b,c,clk); input c, clk; output b; reg b; always @(posedge clk) b = c; endmodule Some of the simulators out there will execute module abc first and then module xyx. This effectively transfers contents of c to a in ONE clk cycle. This is what some people refer to as a simulator race conditon. Other simulators will execute module xyz and then module abc giving a different simulation result. In some simulators, order of execution cannot be controlled by users.
So here are some thoughts.
There is very little difference between non-blocking and blocking in speed and no errors if done correctly either way.
The main differences are:
Some people like non-blocking because you can tell that a reg on the left hand side of <= is going to be a flip flop after synthesis. /* example 1a */ reg a,b,c; always @(posedge clock) begin b <= a; /* b and c will be flip flops */ c <= b; end /* example 1b */ reg a,b,c; always @(posedge clock) begin c <= b; b <= a; /* b and c will be flip flops */ end /* example 2a */ reg a,b,c; always @(posedge clock) begin b = a; c = b; /* Only c will be a flip flop,b will go away after synthesis. */ /* We could delete the 2 above assignments and replace it with c=a;b=a; In fact, b is the same as c and can be eliminated.*/ end /* example 2b */ reg a,b,c; always @(posedge clock) begin c = b; b = a; /* Both b and c will be flip flops, because these 2 lines are reversed.*/ end Example 1a, 1b and 2b are functionally the same. Example 2a is functionally different from 2b just because the order of the statements. Some people like blocking because it takes less memory in the simulator. /* example NON-BLOCKING_MEMORY */ reg a,b,c; always @(posedge clock) begin /* b will require 2 memory locations*/ b <= a; /*<---because this b memory location will hold value of a */ c <= b; /*<---and this b memory location will hold value of b before the posedge*/ end /* example BLOCKING_MEMORY */ reg a,b,c; always @(posedge clock) begin // b will require ONLY 1 memory location c = b; b = a; end Note that I am talking about SIMULATOR memory, not flip-flop count after synthesis. In most cases, the simulator has to remember the value before and after posedge clock if a reg goes between modules in order in order to "execute modules in parallel", so there may be no savings. Some people like blocking because you can see sharing of resources more readily. // example 5 reg [15:0] a,b,c,d,e,f,j,k,g,h; reg [16:0] x,y,z; always @(posedge clock) begin x = a + b + c + d + e + f + j + k; y = x + g; z = x + h; end // example 6 reg [15:0] a,b,c,d,e,f,j,k,g,h; reg [16:0] y,z; always @(posedge clock) begin y <= (a + b + c + d + e + f + j + k) + g; z <= (a + b + c + d + e + f + j + k) + h; end Even the cheapest synthesizer should share adder logic in example 5, but a slightly smarter synthesizer is required in example 6. You will have fewer problems with race conditions in SIMULATION if you always use non-blocking assignments inside always @(posedge clock) blocks where you want to have flip-flops. file xyz.v : module xyz(a,b,clk); input b,clk; output a; reg a; always @(posedge clk) a = b; endmodule file abc.v : module abc(b,c,clk); input c, clk; output b; reg b; always @(posedge clk) b = c; endmodule Some of the simulators out there will execute module abc first and then module xyx. This effectively transfers contents of c to a in ONE clk cycle. This is what some people refer to as a simulator race conditon. Other simulators will execute module xyz and then module abc giving a different simulation result. In some simulators, order of execution cannot be controlled by users.
Synthesizable Verilog from behavioral constructs - 5
Delay statements, e.g. @(posedge clock), require careful attention if there are several in a row. If there are only delays on the positive edge of the clock you can implement them with a state machine:
Behavioural:
forever
begin
command1;
@(posedge clock);
command2;
@(posedge clock);
command3;
@(posedge clock);
end
Synthesizable:
always @(posedge clock or posedge reset)
if (reset) // reset the state machine when reset is high
begin
state <= 0;
end
else
begin
case (state)
0 : begin
command1;
state <= 1;
end
1 : begin
command2;
state <= 2;
end
2 : begin
command3;
state <= 0;
end
endcase
end
If both clock edges are present, then you could implement it in synthesizable Verilog with a state machine changing values on both clock edges:
Behavioural:
forever
begin
command1;
@(posedge clock);
command2;
@(negedge clock);
command3;
@(posedge clock);
@(posedge clock);
command4;
@(negedge clock);
end
Synthesizable:
always @(posedge clock or negedge clock or posedge reset)
if (reset) // reset the state machine when reset is high
begin
state <= 0;
end
else
begin
case (state)
0 : begin
command1;
state <= 1;
end
1 : if (clock == 1) // wait for the positive edge
begin
command2;
state <= 2;
end
2 : begin // this will definitely begin at the negative edge as state 1 precedes it
command3;
state <= 3;
end
3 : state <= 4; // we arrive at the positive edge of the clock, but need to wait a clock cycle
4 : if (clock == 1) // wait for the positive edge
begin
command4;
state <= 0;
end // we'll get back to state 0 at the negative clock edge, the right time for command1
endcase
end
As you can see, multiple clock edges requires care to implement in synthesizable Verilog.
Note: in general commandi refers to a block of commands. It is assumed there is an appropriate clock for the case statement state machines. Care is required in setting appropriate reset states, initialization, and completion of use of a state machine:
* Is there a signal to tell the state machine to begin?
* Does a done signal go high, signalling the state machine has finished?
* When it is not in operation, does the state machine idle correctly? Does it change signal values shared with other code? Does it set outputs from it to appropriate idling values?
* Is the state machine reset to the idle state by a reset signal?
* Ensure that you initialize all registers.
* Ensure that your state register has the correct bit width - if it is too small, assigning a larger state value will just return it to an earlier state.
Behavioural:
forever
begin
command1;
@(posedge clock);
command2;
@(posedge clock);
command3;
@(posedge clock);
end
Synthesizable:
always @(posedge clock or posedge reset)
if (reset) // reset the state machine when reset is high
begin
state <= 0;
end
else
begin
case (state)
0 : begin
command1;
state <= 1;
end
1 : begin
command2;
state <= 2;
end
2 : begin
command3;
state <= 0;
end
endcase
end
If both clock edges are present, then you could implement it in synthesizable Verilog with a state machine changing values on both clock edges:
Behavioural:
forever
begin
command1;
@(posedge clock);
command2;
@(negedge clock);
command3;
@(posedge clock);
@(posedge clock);
command4;
@(negedge clock);
end
Synthesizable:
always @(posedge clock or negedge clock or posedge reset)
if (reset) // reset the state machine when reset is high
begin
state <= 0;
end
else
begin
case (state)
0 : begin
command1;
state <= 1;
end
1 : if (clock == 1) // wait for the positive edge
begin
command2;
state <= 2;
end
2 : begin // this will definitely begin at the negative edge as state 1 precedes it
command3;
state <= 3;
end
3 : state <= 4; // we arrive at the positive edge of the clock, but need to wait a clock cycle
4 : if (clock == 1) // wait for the positive edge
begin
command4;
state <= 0;
end // we'll get back to state 0 at the negative clock edge, the right time for command1
endcase
end
As you can see, multiple clock edges requires care to implement in synthesizable Verilog.
Note: in general commandi refers to a block of commands. It is assumed there is an appropriate clock for the case statement state machines. Care is required in setting appropriate reset states, initialization, and completion of use of a state machine:
* Is there a signal to tell the state machine to begin?
* Does a done signal go high, signalling the state machine has finished?
* When it is not in operation, does the state machine idle correctly? Does it change signal values shared with other code? Does it set outputs from it to appropriate idling values?
* Is the state machine reset to the idle state by a reset signal?
* Ensure that you initialize all registers.
* Ensure that your state register has the correct bit width - if it is too small, assigning a larger state value will just return it to an earlier state.
Design Guidelines and Criteria for Digital Electronics
apparently these pages on guidelines and criteria, are from NASA. I think this is a very nice article with good amount discussion on critical aspects of Digital Design
Synthesizable Verilog from behavioral constructs - 4
When implementing Verilog tasks in modules, the best approach is to group tasks that have the same output signals into separate modules. If different modules control the same signal, then explicit arbitration logic is required to specify which module is controlling the signal at a given time. To put tasks in a separate module, you will require start and completion handshaking signals.
Behavioural:
task update_a_and_b;
begin
a = y;
wait (z != 0) b = z;
end
endtask
...
y = x + w;
update_a_and_b; // calls the task
x = a + b;
@(posedge clock);
x = b;
if (y == x) update_a_and_b;
@(posedge clock);
command1;
Care must be taken when translating this into synthesizable Verilog, to preserve correct timing:
module update_a_and_b(do_update_a_and_b, clock, reset, a, z, done_update_a_and_b, b_temp, x_temp);
input do_update_a_and_b; // this signal should go high for only one clock cycle
input clock;
input reset; // reset this module when reset goes high
input [7:0] a;
input [7:0] z;
output done_update_a_and_b;
output [7:0] b_temp;
output [7:0] x_temp;
reg done_update_a_and_b;
reg [7:0] b_temp;
reg [7:0] x_temp;
reg state;
always @(posedge refclk or posedge reset)
if (reset)
begin
state <= 0; done_update_a_and_b = 0; b_temp = 0; x_temp = 0; end else if (do_update_a_and_b && (state == 0)) begin done_update_a_and_b = 0; if (z != 0) begin b_temp = z; x_temp = a+b_temp; // x value is update inside this module, as it must occur immediately when z != 0 done_update_a_and_b = 1; // stay in state 0, we've finished end else state <= 1; end else begin case (state) 0 : done_update_a_and_b = 0; // do nothing, this is the idle state 1 : if (z != 0) begin b_temp = z; x_temp = a+b_temp; // x value is update inside this module, as it must occur immediately when z != 0 done_update_a_and_b = 1; state <= 0; // stay in state 0, we've finished end endcase end endmodule ... reg [2:0] top_state; ... case (top_state) 0 : begin y = x + w; a = y; // this must happen immediately if (z != 0) // we have to update x and b immediately if z != 0 begin b = z; x = a + b; top_state <= 2; end else begin do_update_a_and_b = 1; // call the task top_state <= 1; end end 1 : begin do_update_a_and_b = 0; // stays high for only one cycle if (done_update_a_and_b) begin // we assume the values of x and b weren't needed on the previous cycle, otherwise additional circuitry is needed // or x_temp and b_temp values need to be used on that cycle - it's very difficult to coordinate this correctly // in the general case x = x_temp; b = b_temp; top_state <= 2; end end 2 : begin x = b; if (y == x) begin a = y; // this must happen immediately if (z != 0) // we have to update x and b immediately if z != 0 begin b = z; x = a + b; top_state <= 4; end else begin do_update_a_and_b = 1; // call the task top_state <= 3; end end else top_state <= 4; end 3 : begin do_update_a_and_b = 0; // stays high for only one cycle if (done_update_a_and_b) begin // we assume the values of x and b weren't needed on the previous cycle, otherwise additional circuitry is needed // or x_temp and b_temp values need to be used on that cycle - it's very difficult to coordinate this correctly // in the general case x = x_temp; b = b_temp; top_state <= 4; end end 4: command1; endcase Now if we didn't care about having a couple of additional cycle delays between updates (i.e. assuming nothing depends on the variable values immediately, and nothing else is changing variable values), we could implement this in a far simpler fashion: module update_a_and_b(do_update_a_and_b, clock, reset, a, z, done_update_and_b, b_temp, x_temp); input do_update_a_and_b; // this signal should go high for only one clock cycle input clock; input reset; // reset this module when reset goes high input [7:0] a; input [7:0] z; output done_update_and_b; output [7:0] b_temp; output [7:0] x_temp; reg done_update_and_b; reg [7:0] b_temp; reg [7:0] x_temp; reg state; always @(posedge refclk or posedge reset) if (reset) begin state <= 0; done_update_and_b = 0; b_temp = 0; x_temp = 0; end else if (do_update_a_and_b && (state == 0)) begin state <= 1; done_update_a_and_b = 0; end else begin case (state) 0 : done_update_and_b = 0; // do nothing, this is the idle state 1 : if (z != 0) begin b_temp = z; x_temp = a+b_temp; // x value is update inside this module, as it must occur immediately when z != 0 done_update_and_b = 1; state <= 0; // stay in state 0, we've finished end endcase end endmodule ... reg [2:0] top_state; ... case (top_state) 0 : begin y = x + w; do_update_a_and_b = 1; // call the task top_state <= 1; end 1 : begin do_update_a_and_b = 0; // stays high for only one cycle if (done_update_and_b) begin x = x_temp; b = b_temp; top_state <= 2; end end 2 : begin x = b; if (y == x) begin do_update_a_and_b = 1; // call the task top_state <= 3; end else top_state <= 4; end 3 : begin do_update_a_and_b = 0; // stays high for only one cycle if (done_update_and_b) begin x = x_temp; b = b_temp; top_state <= 4; end end 4: command1; endcase Note: in general commandi refers to a block of commands. It is assumed there is an appropriate clock for the case statement state machines. Care is required in setting appropriate reset states, initialization, and completion of use of a state machine: o Is there a signal to tell the state machine to begin? o Does a done signal go high, signalling the state machine has finished? o When it is not in operation, does the state machine idle correctly? Does it change signal values shared with other code? Does it set outputs from it to appropriate idling values? o Is the state machine reset to the idle state by a reset signal? o Ensure that you initialize all registers. o Ensure that your state register has the correct bit width - if it is too small, assigning a larger state value will just return it to an earlier state.
Behavioural:
task update_a_and_b;
begin
a = y;
wait (z != 0) b = z;
end
endtask
...
y = x + w;
update_a_and_b; // calls the task
x = a + b;
@(posedge clock);
x = b;
if (y == x) update_a_and_b;
@(posedge clock);
command1;
Care must be taken when translating this into synthesizable Verilog, to preserve correct timing:
module update_a_and_b(do_update_a_and_b, clock, reset, a, z, done_update_a_and_b, b_temp, x_temp);
input do_update_a_and_b; // this signal should go high for only one clock cycle
input clock;
input reset; // reset this module when reset goes high
input [7:0] a;
input [7:0] z;
output done_update_a_and_b;
output [7:0] b_temp;
output [7:0] x_temp;
reg done_update_a_and_b;
reg [7:0] b_temp;
reg [7:0] x_temp;
reg state;
always @(posedge refclk or posedge reset)
if (reset)
begin
state <= 0; done_update_a_and_b = 0; b_temp = 0; x_temp = 0; end else if (do_update_a_and_b && (state == 0)) begin done_update_a_and_b = 0; if (z != 0) begin b_temp = z; x_temp = a+b_temp; // x value is update inside this module, as it must occur immediately when z != 0 done_update_a_and_b = 1; // stay in state 0, we've finished end else state <= 1; end else begin case (state) 0 : done_update_a_and_b = 0; // do nothing, this is the idle state 1 : if (z != 0) begin b_temp = z; x_temp = a+b_temp; // x value is update inside this module, as it must occur immediately when z != 0 done_update_a_and_b = 1; state <= 0; // stay in state 0, we've finished end endcase end endmodule ... reg [2:0] top_state; ... case (top_state) 0 : begin y = x + w; a = y; // this must happen immediately if (z != 0) // we have to update x and b immediately if z != 0 begin b = z; x = a + b; top_state <= 2; end else begin do_update_a_and_b = 1; // call the task top_state <= 1; end end 1 : begin do_update_a_and_b = 0; // stays high for only one cycle if (done_update_a_and_b) begin // we assume the values of x and b weren't needed on the previous cycle, otherwise additional circuitry is needed // or x_temp and b_temp values need to be used on that cycle - it's very difficult to coordinate this correctly // in the general case x = x_temp; b = b_temp; top_state <= 2; end end 2 : begin x = b; if (y == x) begin a = y; // this must happen immediately if (z != 0) // we have to update x and b immediately if z != 0 begin b = z; x = a + b; top_state <= 4; end else begin do_update_a_and_b = 1; // call the task top_state <= 3; end end else top_state <= 4; end 3 : begin do_update_a_and_b = 0; // stays high for only one cycle if (done_update_a_and_b) begin // we assume the values of x and b weren't needed on the previous cycle, otherwise additional circuitry is needed // or x_temp and b_temp values need to be used on that cycle - it's very difficult to coordinate this correctly // in the general case x = x_temp; b = b_temp; top_state <= 4; end end 4: command1; endcase Now if we didn't care about having a couple of additional cycle delays between updates (i.e. assuming nothing depends on the variable values immediately, and nothing else is changing variable values), we could implement this in a far simpler fashion: module update_a_and_b(do_update_a_and_b, clock, reset, a, z, done_update_and_b, b_temp, x_temp); input do_update_a_and_b; // this signal should go high for only one clock cycle input clock; input reset; // reset this module when reset goes high input [7:0] a; input [7:0] z; output done_update_and_b; output [7:0] b_temp; output [7:0] x_temp; reg done_update_and_b; reg [7:0] b_temp; reg [7:0] x_temp; reg state; always @(posedge refclk or posedge reset) if (reset) begin state <= 0; done_update_and_b = 0; b_temp = 0; x_temp = 0; end else if (do_update_a_and_b && (state == 0)) begin state <= 1; done_update_a_and_b = 0; end else begin case (state) 0 : done_update_and_b = 0; // do nothing, this is the idle state 1 : if (z != 0) begin b_temp = z; x_temp = a+b_temp; // x value is update inside this module, as it must occur immediately when z != 0 done_update_and_b = 1; state <= 0; // stay in state 0, we've finished end endcase end endmodule ... reg [2:0] top_state; ... case (top_state) 0 : begin y = x + w; do_update_a_and_b = 1; // call the task top_state <= 1; end 1 : begin do_update_a_and_b = 0; // stays high for only one cycle if (done_update_and_b) begin x = x_temp; b = b_temp; top_state <= 2; end end 2 : begin x = b; if (y == x) begin do_update_a_and_b = 1; // call the task top_state <= 3; end else top_state <= 4; end 3 : begin do_update_a_and_b = 0; // stays high for only one cycle if (done_update_and_b) begin x = x_temp; b = b_temp; top_state <= 4; end end 4: command1; endcase Note: in general commandi refers to a block of commands. It is assumed there is an appropriate clock for the case statement state machines. Care is required in setting appropriate reset states, initialization, and completion of use of a state machine: o Is there a signal to tell the state machine to begin? o Does a done signal go high, signalling the state machine has finished? o When it is not in operation, does the state machine idle correctly? Does it change signal values shared with other code? Does it set outputs from it to appropriate idling values? o Is the state machine reset to the idle state by a reset signal? o Ensure that you initialize all registers. o Ensure that your state register has the correct bit width - if it is too small, assigning a larger state value will just return it to an earlier state.
synthesizable Verilog from behavioral constructs - 3
To modify a behavioural Verilog fork and join statement to make it synthesizable.
Behavioural:
command1;
fork
// start of fork block 1
begin
wait (y != 0);
a = y;
end
// start of fork block 2
begin
wait (z != 0);
b = z;
end
join
command2;
command2 will execute only after fork blocks 1 and 2 have finished.
Synthesizable:
case (state)
0 : begin
command1;
done_fork_block_1 = 0;
done_fork_block_2 = 0;
if (y != 0)
begin
a = y;
done_fork_block_1 = 1;
end
if (z != 0)
begin
b = z;
done_fork_block_2 = 1;
end
if (done_fork_block_1 & done_fork_block_2) command2;
else state <= 1; end 1 : begin if ((y != 0) && !done_fork_block_1) begin a = y; done_fork_block_1 = 1; end if ((z != 0) && !done_fork_block_2) begin b = z; done_fork_block_2 = 1; end if (done_fork_block_1 & done_fork_block_2) command2; // else state <= 1; end endcase In some special cases, it may not be necessary to have done signals, but in general the blocks of commands being executed in parallel by fork may finish at different times. Again, if a cycle delay between command1 and the other commands executing is acceptable, then this code is simpler: case (state) 0 : begin command1; done_fork_block_1 = 0; done_fork_block_2 = 0; state <= 1; end 1 : begin if ((y != 0) && !done_fork_block_1) begin a = y; done_fork_block_1 = 1; end if ((z != 0) && !done_fork_block_2) begin b = z; done_fork_block_2 = 1; end if (done_fork_block_1 & done_fork_block_2) command2; // else state <= 1; end endcase As y or z may have different values after a clock cycle passes, care needs to be taken in choosing the simpler alternative, that doesn't exactly implement the behavioural code. Note: in general commandi refers to a block of commands. It is assumed there is an appropriate clock for the case statement state machines. Care is required in setting appropriate reset states, initialization, and completion of use of a state machine: * Is there a signal to tell the state machine to begin? * Does a done signal go high, signalling the state machine has finished? * When it is not in operation, does the state machine idle correctly? Does it change signal values shared with other code? Does it set outputs from it to appropriate idling values? * Is the state machine reset to the idle state by a reset signal? * Ensure that you initialize all registers. * Ensure that your state register has the correct bit width - if it is too small, assigning a larger state value will just return it to an earlier state.
Behavioural:
command1;
fork
// start of fork block 1
begin
wait (y != 0);
a = y;
end
// start of fork block 2
begin
wait (z != 0);
b = z;
end
join
command2;
command2 will execute only after fork blocks 1 and 2 have finished.
Synthesizable:
case (state)
0 : begin
command1;
done_fork_block_1 = 0;
done_fork_block_2 = 0;
if (y != 0)
begin
a = y;
done_fork_block_1 = 1;
end
if (z != 0)
begin
b = z;
done_fork_block_2 = 1;
end
if (done_fork_block_1 & done_fork_block_2) command2;
else state <= 1; end 1 : begin if ((y != 0) && !done_fork_block_1) begin a = y; done_fork_block_1 = 1; end if ((z != 0) && !done_fork_block_2) begin b = z; done_fork_block_2 = 1; end if (done_fork_block_1 & done_fork_block_2) command2; // else state <= 1; end endcase In some special cases, it may not be necessary to have done signals, but in general the blocks of commands being executed in parallel by fork may finish at different times. Again, if a cycle delay between command1 and the other commands executing is acceptable, then this code is simpler: case (state) 0 : begin command1; done_fork_block_1 = 0; done_fork_block_2 = 0; state <= 1; end 1 : begin if ((y != 0) && !done_fork_block_1) begin a = y; done_fork_block_1 = 1; end if ((z != 0) && !done_fork_block_2) begin b = z; done_fork_block_2 = 1; end if (done_fork_block_1 & done_fork_block_2) command2; // else state <= 1; end endcase As y or z may have different values after a clock cycle passes, care needs to be taken in choosing the simpler alternative, that doesn't exactly implement the behavioural code. Note: in general commandi refers to a block of commands. It is assumed there is an appropriate clock for the case statement state machines. Care is required in setting appropriate reset states, initialization, and completion of use of a state machine: * Is there a signal to tell the state machine to begin? * Does a done signal go high, signalling the state machine has finished? * When it is not in operation, does the state machine idle correctly? Does it change signal values shared with other code? Does it set outputs from it to appropriate idling values? * Is the state machine reset to the idle state by a reset signal? * Ensure that you initialize all registers. * Ensure that your state register has the correct bit width - if it is too small, assigning a larger state value will just return it to an earlier state.
synthesizable Verilog from behavioral constructs - 2
Modifying a behavioural Verilog while statement to make it synthesizable.
Behavioural:
command1;
while (x != 0)
begin
command2;
end
command3;
Synthesizable:
case (state)
0 : begin
command1;
if (x != 0)
begin
command2;
state <= 1; end else command3; end 1 : if (x != 0) begin command2; end else command3; endcase Again, if a cycle delay between command1 and the other commands executing is acceptable, simpler code is the following: case (state) 0 : begin command1; state <= 1; end 1 : if (x != 0) begin command2; end else command3; endcase Note: in general commandi refers to a block of commands. It is assumed there is an appropriate clock for the case statement state machines. Care is required in setting appropriate reset states, initialization, and completion of use of a state machine: o Is there a signal to tell the state machine to begin? o Does a done signal go high, signalling the state machine has finished? o When it is not in operation, does the state machine idle correctly? Does it change signal values shared with other code? Does it set outputs from it to appropriate idling values? o Is the state machine reset to the idle state by a reset signal? o Ensure that you initialize all registers. o Ensure that your state register has the correct bit width - if it is too small, assigning a larger state value will just return it to an earlier state.
Behavioural:
command1;
while (x != 0)
begin
command2;
end
command3;
Synthesizable:
case (state)
0 : begin
command1;
if (x != 0)
begin
command2;
state <= 1; end else command3; end 1 : if (x != 0) begin command2; end else command3; endcase Again, if a cycle delay between command1 and the other commands executing is acceptable, simpler code is the following: case (state) 0 : begin command1; state <= 1; end 1 : if (x != 0) begin command2; end else command3; endcase Note: in general commandi refers to a block of commands. It is assumed there is an appropriate clock for the case statement state machines. Care is required in setting appropriate reset states, initialization, and completion of use of a state machine: o Is there a signal to tell the state machine to begin? o Does a done signal go high, signalling the state machine has finished? o When it is not in operation, does the state machine idle correctly? Does it change signal values shared with other code? Does it set outputs from it to appropriate idling values? o Is the state machine reset to the idle state by a reset signal? o Ensure that you initialize all registers. o Ensure that your state register has the correct bit width - if it is too small, assigning a larger state value will just return it to an earlier state.
Verilog Awareness - Interview Questions
Q: Given the following Verilog code, what value of "a" is "displayed"?
always @(clk)
begin
a = 0;
a <= 1; $display(a); end
Q: Given the following snippet of Verilog code, draw out the waveforms for "clk" and "a".
always @(clk)
begin
a = 0;
#5 a = 1;
end
Q: What is the difference between the following two lines of Verilog code?
#5 a = b;
a = #5 b;
Q: Write Verilog to provide a divide-by-3 clock from the standard clock.
Q: What is the difference between:
c = foo ? a : b;
and
if (foo) c = a; else c = b;
Q: Using the given, draw the waveforms for the following (each version is separate, i.e. not in the same run):
reg clk;
reg a;
always #10 clk = ~clk;
(1) always @(clk) a = # 5 clk;
(2) always @(clk) a = #10 clk;
(3) always @(clk) a = #15 clk;
Now, change to a wire, and draw for:
(4) assign #5 a = clk;
(5) assign #10 a = clk;
(6) assign #15 a = clk;
always @(clk)
begin
a = 0;
a <= 1; $display(a); end
Q: Given the following snippet of Verilog code, draw out the waveforms for "clk" and "a".
always @(clk)
begin
a = 0;
#5 a = 1;
end
Q: What is the difference between the following two lines of Verilog code?
#5 a = b;
a = #5 b;
Q: Write Verilog to provide a divide-by-3 clock from the standard clock.
Q: What is the difference between:
c = foo ? a : b;
and
if (foo) c = a; else c = b;
Q: Using the given, draw the waveforms for the following (each version is separate, i.e. not in the same run):
reg clk;
reg a;
always #10 clk = ~clk;
(1) always @(clk) a = # 5 clk;
(2) always @(clk) a = #10 clk;
(3) always @(clk) a = #15 clk;
Now, change to a wire, and draw for:
(4) assign #5 a = clk;
(5) assign #10 a = clk;
(6) assign #15 a = clk;
synthesizable Verilog from behavioral constructs - 1
Modifying a behavioural Verilog wait statement to make it synthesizable.
Behavioural:
command1;
wait (x != 0);
command3;
Synthesizable:
case (state)
0 : begin
command1;
if (x != 0) command3;
else state <= 1; end 1 : if (x != 0) // wait until this is true command3; endcase You also need to add the variable state, reg state. If a cycle delay between command1 and command3 does not matter, then the following is simpler, but not identical to the original: case (state) 0 : begin command1; state <= 1; end 1 : if (x != 0) // wait until this is true command3; endcase The latter approach is preferred in many cases for coding simplicity. Note: in general commandi refers to a block of commands. It is assumed there is an appropriate clock for the case statement state machines. Care is required in setting appropriate reset states, initialization, and completion of use of a state machine: * Is there a signal to tell the state machine to begin? * Does a done signal go high, signalling the state machine has finished? * When it is not in operation, does the state machine idle correctly? Does it change signal values shared with other code? Does it set outputs from it to appropriate idling values? * Is the state machine reset to the idle state by a reset signal? * Ensure that you initialize all registers. * Ensure that your state register has the correct bit width - if it is too small, assigning a larger state value will just return it to an earlier state.
Behavioural:
command1;
wait (x != 0);
command3;
Synthesizable:
case (state)
0 : begin
command1;
if (x != 0) command3;
else state <= 1; end 1 : if (x != 0) // wait until this is true command3; endcase You also need to add the variable state, reg state. If a cycle delay between command1 and command3 does not matter, then the following is simpler, but not identical to the original: case (state) 0 : begin command1; state <= 1; end 1 : if (x != 0) // wait until this is true command3; endcase The latter approach is preferred in many cases for coding simplicity. Note: in general commandi refers to a block of commands. It is assumed there is an appropriate clock for the case statement state machines. Care is required in setting appropriate reset states, initialization, and completion of use of a state machine: * Is there a signal to tell the state machine to begin? * Does a done signal go high, signalling the state machine has finished? * When it is not in operation, does the state machine idle correctly? Does it change signal values shared with other code? Does it set outputs from it to appropriate idling values? * Is the state machine reset to the idle state by a reset signal? * Ensure that you initialize all registers. * Ensure that your state register has the correct bit width - if it is too small, assigning a larger state value will just return it to an earlier state.
Subscribe to:
Posts (Atom)