Question:-
Consider a finite state machine that is used to control some type of motor. The FSM has inputs x and y, which come from the motor, and produces outputs f and g, which control the motor. There is also a clock input called clk and a reset input called resetn.
The FSM has to work as follows. As long as the reset input is asserted, the FSM stays in a beginning state, called state A. When the reset signal is de-asserted, then after the next clock edge the FSM has to set the output f to 1 for one clock cycle. Then, the FSM has to monitor the x input. When x has produced the values 1, 0, 1 in three successive clock cycles, then g should be set to 1 on the following clock cycle. While maintaining g = 1 the FSM has to monitor the y input. If y has the value 1 within at most two clock cycles, then the FSM should maintain g = 1 permanently (that is, until reset). But if y does not become 1 within two clock cycles, then the FSM should set g = 0 permanently (until reset).
(The original exam question asked for a state diagram only. But here, implement the FSM.)
My Code:
module top_module (
input clk,
input resetn, // active-low synchronous reset
input x,
input y,
output f,
output g
);
parameter a=0,b=1,c=2,d=3,e=4,f1=5,g1=6,h=7,i=8,per=9;
reg [3:0] state,ns;
always#(posedge clk) begin
if(~resetn)
ns<=a;
case(state)
a:ns<=resetn ? b : a;
b:ns<=c;
c:ns<=x ? d : c;
d:ns<=x ? d : e;
e:ns<=x ? f1 : d;
f1:ns<=y ? per : g1;
g1:ns<=y ? per : i;
per:ns<=resetn ? per : a;
i:ns<=resetn ? i : a;
endcase
end
assign state=ns;
assign f=(state==b);
assign g=(state==f1|state==g1|state==per);
endmodule
There is a problem with your reset logic. You should separate the reset clause from the rest of your logic; it should only be included in the if clause, and it should not be in the case statement.
Also, the case statement should be in an else clause:
module top_module (
input clk,
input resetn, // active-low synchronous reset
input x,
input y,
output f,
output g
);
parameter a=0,b=1,c=2,d=3,e=4,f1=5,g1=6,h=7,i=8,per=9;
reg [3:0] state;
always#(posedge clk) begin
if (~resetn) begin
state<=a;
end else begin
case(state)
a:state<=b;
b:state<=c;
c:state<=x ? d : c;
d:state<=x ? d : e;
e:state<=x ? f1 : d;
f1:state<=y ? per : g1;
g1:state<=y ? per : i;
endcase
end
end
assign f=(state==b);
assign g=(state==f1|state==g1|state==per);
endmodule
There is no need to have 2 state variables. I changed the FSM so that it only keeps state.
Related
module main(input A, B, C,button,clk100mhz,output [7:0]seg,[7:0]an);
reg [3:0] D0;
reg [3:0] D1;
reg [3:0] D2;
reg [7:0] Y;
DISP7SEG m1 (clk100mhz, D0, D1, D2, 4'b0000,4'b0000,4'b0000,4'b0000,4'b0000, 1'b0, 1'b0, 1'b0,1'b0,1'b0, 1'b0, seg, an);
always#(button)
begin
if (button)
if (A+B+C == 1'b1)//only one switch
if (Y < 7'd75)
begin
Y = Y + {A,B,C} * 5'd25;
D0 = Y % 10;
D1 = (Y/10) %10;
D2 = (Y/100) %10;
end
end
endmodule
this is supposed be a basic adder up to 75 with a multiplication by 25 at every step
for example if ABC is 001
I should get 25 -> 50 -> 75 in reg Y after every button press, the problem is that xilinx ISE gives this error
WARNING:HDLCompiler:91 - "main.v" Line 33: Signal Y missing in the sensitivity list is added for synthesis purposes. HDL and post-synthesis simulations may differ as a result.
so it becomes an infinite loop every time Y is changed it triggers the always block and changes it again and so on
How am I supposed to do this without triggering this error or to somehow stop the tool from adding it to the sensitivity list
As #toolic and #Serge said, you need to use a clocked always block. Take a look at this article: https://www.chipverify.com/verilog/verilog-always-sequential-logic
The always block should be sensitive to (posedge clk100mhz). Every rising edge of the clock, it will run and increment Y if all your "if" conditions are met.
Then Y will increment for every clock that button is held down. This probably isn't the desired behavior so consider adding some logic that only triggers once for each button press.
I am working with a verilog module (shown below) has two always blocks. Won't there be some sort of race condition since one block sets a register and the other uses the register. What kind of issues would this cause?
Thanks,
Stephen
module XYZ
(
input wire CLK,
input wire Reset,
input wire nReset,
input wire [15:0] X,
input wire [15:0] A,
input wire T,
input wire B,
output reg M
);
assign C = X > A;
reg P;
reg N;
always #(posedge CLK, negedge nReset)
begin
if (~nReset)
begin
P <= 1;
N <= 1;
end else begin
if (Reset)
begin
P <= 1;
N <= 1;
end else begin
P <= T? 1: ((C & ~M)? 0: P);
N <= B? 1: ((M & ~C)? 0: N);
end
end
end
always #(posedge CLK, negedge nReset)
begin
if (~nReset)
begin
M <= 0;
end else begin
if (Reset)
begin
M <= 0;
end else begin
M <= M? ~(N & ~C): (P & C);
end
end
end
endmodule
No, there is no race condition. Verilog is an event-driven simulator. Posedge (unless there is a glitch in the clock or reset) is usually executed once per the simulation tick. If you use non-blocking assignments correctly (and it looks like you did), every always block triggered by an edge will use old versions of the input variable values, the values which existed before the clock edge.
Here is a simplified example:
always #(posedge clk)
r <= in;
always #(posedge clk)
out <= r;
What happens in this situation is the following:
r will be assigned the value of in later at the simulation tick, after the always blocks have been evaluated (see the nba scheduling region).
since r has not been yet really changed, the out will be scheduled to be assigned the value of r with the value before the edge.
If r was 0 before the edge and in was 1, at the end of the simulation r will become 1 and out will become 0.
This mimics behavior for real flops in hardware.
In your case it might look as a loop dependency. In reality it it none. For the same reason as above the M value will be the one from before the the posedge and will not cause any race. Flops cannot be involved in the combinational loops due to their properties logical properties.
I completely Agree with the above answer and i would suggest some more to the above answer, when i started learning Verilog i too got the same doubt and these lines from a ref. book clarified my doubts. I am coping the statement here and
for further doubts u can comment here or u can see the
Ref. book page number 135
Book name :Verilog HDL: A Guide to Digital Design and Synthesis,
Second Edition By Samir Palnitkar
nonblocking statements used in Example 2 eliminate the race condition.
At the positive edge of clock, the values of all right-hand-side
variables are "read," and the right-hand-side expressions are
evaluated and stored in temporary variables. During the write
operation, the values stored in the temporary variables are assigned
to the left-handside variables. Separating the read and write
operations ensures that the values of registers a and b are swapped
correctly, regardless of the order in which the write operations are
performed.
On the downside, nonblocking assignments can potentially cause a
degradation in the simulator performance and increase in memory usage.
//Example 2: Two concurrent always blocks with nonblocking
//statements
always #(posedge clock)
a <= b;
always #(posedge clock)
b <= a;
And u can use this type of coding style not compulsory but for the ease of debugging and to fasten simulation u can reduce the usage of begin-end blocks where ever possible
module XYZ
(
input wire CLK,
input wire Reset,
input wire nReset,
input wire [15:0] X,
input wire [15:0] A,
input wire T,
input wire B,
output reg M
);
reg P,N;
always #(posedge CLK, negedge nReset)
if (~nReset)begin
P <= #10 1;
N <= #10 1;
end else if (Reset) begin
P <= #10 1;
N <= #10 1;
end else begin
P <= #10 T ? 1 : ((C & ~M) ? 0: P);
N <= #10 B ? 1 : ((M & ~C) ? 0: N);
end
always #(posedge CLK, negedge nReset)
if (~nReset) M <= #10 0 ;
else if ( Reset) M <= #10 0 ;
else M <= #10 M ? ~(N & ~C): (P & C);
assign C = X > A;
endmodule
What I'm trying to do: I wish to count numbers from 0 to hexadecimal F and display these on my FPGA board at different frequencies - my board's clock (CLOCK_50) is at 50 MHz and I wish to alter the frequency/speed of the counting based on two input switches on my board (SW[1:0]).
Verilog Code for top-module & clock divider module:
//top level module
module rate_divider (input CLOCK_50, input [1:0] SW, input [1:0] KEY,output [6:0] HEX0);
//Declare parameters that define the # of clock cycles needed to generate an enable pulse
according to the desired frequency.
parameter FREQ_5MHz = 4'd9; //To divide to 5 MHz we need (10-1) cycles,
//since the pulse needs to start at the 9th cycle.
parameter FULL50_MHz = (4'd1); //The CLOCK_50's Frequency.
//Select the desired parameter based on the input switches
reg [3:0] cycles_countdown;
wire enable_display_count;
wire [3:0] selected_freq;
always #(*)
case (SW)
2'b00: cycles_countdown = FULL50_MHz;
2'b01: cycles_countdown = FREQ_5MHz;
default : cycles_countdown = FULL50_MHz;
endcase
assign selected_freq = cycles_countdown;
//wire that is the output of the display_counter and input to the 7 segment
wire [3:0] hex_value;
// instantiate my other modules
clock_divider_enable freq_divider (.d(selected_freq), .clk(CLOCK_50), .reset(KEY[0]),
.enable(enable_display_count));
display_counter count_hex (.enable(enable_display_count), .clk(CLOCK_50), .hex_out(hex_value), .reset(KEY[1]));
hex_decoder HX0 (.hex_digit(hex_value), .segments(HEX0[6:0]));
endmodule
//the clock_divider sub-circuit.
module clock_divider_enable (input [3:0] d, input clk, reset,
output enable);
reg [3:0] q;
always #(posedge clk)
begin
if (!reset || !q)
q <= d;
else
q <= q - 4'd1;
end
assign enable = (q == 4'h0) ? 1'b1 : 1'b0;
endmodule
ModelSim Code:
vlib work
vlog rate_divider.v
vsim rate_divider
log {/*}
add wave {/*}
#initial reset - using KEY[1:0]. Note: active low synchronous reset.
force {CLOCK_50} 1
force {KEY[0]} 0
force {KEY[1]} 0
run 10ns
#choose 5 MHz as the desired frequency - turn SW[0] high.
force {CLOCK_50} 0 0ns, 1 {10ns} -r 20ns
force {KEY[0]} 1
force {KEY[1]} 1
force {SW[0]} 1
force {SW[1]} 0
run 600ns
Problems I am facing:
Here's the thing - when I don't use the always block to select a parameter, and pass a desired parameter to the wire selected_freq, my simulation works fine - I can see the expected enable pulse.
HOWEVER, if I use the always block, the reg cycles_countdown does get the correct value assigned, BUT for some reason the enable signal is just a red line. When I select my clock_divider_enable module and add it's 'q' signal onto my waveform, it is red too and shows no data, and the object q is "not logged". As such, I'm unable to debug and figure out what exactly the problem with my code is.
It'd be great if someone could help with how to fix the simulation issue rather than just point out the issue with my Verilog code since I want to learn how to use ModelSim efficiently so that in the future debugging will be easier for me.
Equipment Used:
FPGA: Altera De-1-SoC, Cyclone V chip
CAD/Simulation Tools: Altera Quartus II Lite 17.0 + ModelSim Starter Edition
SW wasn't given an initial value, therefore it is high-Z (X if connected to a reg).
I'm guessing when you used the parameter approach you were parameterizing cycles_countdown. Some simulators do not trigger #* at time-0. So if there isn't a change on the senctivity list, then the block may not execute; leaving cycles_countdown as its initial value (4'hX).
Instead of driving your test with TCL commands, you can use create a testbench in with verilog. This testbench should only be used in simulation, not synthesis.
module rate_devider_tb;
reg CLOCK_50;
reg [1:0] SW;
reg [1:0] KEY;
wire [6:0] HEX0;
rate_divider dut( .CLOCK_50(CLOCK_50), .SW(SW), .KEY(KEY), .HEX0(HEX0));
always begin
CLOCK_50 = 1'b1;
#10;
CLOCK_50 = 1'b0;
#10;
end
initial begin
// init input signals
SW <= 2'b01;
KEY <= 2'b00;
// Log file reporting
$monitor("SW:%b KEY:%b HEX0:%h # %t", SW, KEY, HEX0, $time);
// waveform dumping
$dumpfile("test.vcd");
$dumpvars(0, rate_devider_tb);
wait(CLOCK_50 === 1'b0); // initialization x->1 will trigger an posedge
#(posedge CLOCK_50);
KEY <= 2'b01; // remove reset after SW was sampled
#600; // 600ns assuming timescale is in 1ns steps
$finish();
end
I'm trying to make a pipeline processor using Verilog HDL. I realized that there are maybe some race conditions somewhere in my code. So I'm going to write a sudo code and would like to ask you about if there is a race condition within and how to avoid it :
module A(input wire reset, input wire clock, output reg a_reg_o);
always #(posedge clock)
begin
if(reset == 1'h1)
begin
a_reg_o = 1'h0;
end
else
begin
a_reg_o = 1'h1;
end
end
endmodule
module B(input wire reset, input wire clock, input a_i);
reg b;
always #(posedge clock)
begin
if(reset == 1'h1)
begin
b = 1'h0;
end
else
begin
if(a_i == 1'h1)
begin
b = 1'h1;
end
else
begin
b = 1'h0;
end
end
end
endmodule
module Main(input wire reset, input wire clock);
wire a_o;
A a(reset, clock, a_o);
B b(reset, clock, a_o)
endmodule
So imagine I trigger reset signal. After the first positive edge of clock the register a_reg_o is going to be 0 and register b from module B also is going to be 0 (No race conditions yet). Now I release the reset button and let it to be negative. On the next positive edge of the clock the register a_reg_o is going to be 1, but what about register b from module B ? Is it going to be :
1. Zero, Because it didn't see the a_i changes yet.
2. It depends on the modules (A and B) total delay ( i.e. a race condition).
Thank you.
Yes there can be a race condition, because you won't know whether the net a_o is first driven by module A and then captured by module B or vice versa.
So you should use the Non Blocking Assignment for this, as that will ensure that no matter which module gets executed, the module B will always have the previous value of net a_o.
You can find more about this Non Blocking Assignments with following link. http://www.sunburst-design.com/papers/CummingsSNUG2000SJ_NBA.pdf
This is why there a non-blocking (NBA) assignments in Verilog. The coding rule is whenever there are multiple processes (in this case, multiple always blocks) accessing the same signal (a_o) synchronized to the same event (#posdege clock) where one process writes and another process reads, you need to use and NBA <= assignment to write to the signal.
I'm trying to write a multiplier based on a design. It consists of two 16-bit inputs and the a single adder is used to calculate the partial product. The LSB of one input is AND'ed with the 16 bits of the other input and the output of the AND gate is repetitively added to the previous output. The Verilog code for it is below, but I seem to be having trouble with getting the outputs to work.
module datapath(output reg [31:15]p_high,
output reg [14:0]p_low,
input [15:0]x, y,
input clk); // reset, start, x_ce, y_ce, y_load_en, p_reset,
//output done);
reg [15:0]q0;
reg [15:0]q1;
reg [15:0]and_output;
reg [16:0]sum, prev_sum;
reg d_in;
reg [3:0] count_er;
initial
begin
count_er <= 0;
sum <= 17'b0;
prev_sum <= 17'b0;
end
always#(posedge clk)
begin
q0 <= y;
q1 <= x;
and_output <= q0[count_er] & q1;
sum <= and_output + prev_sum;
prev_sum <= sum;
p_high <= sum;
d_in <= p_high[15];
p_low[14] <= d_in;
p_low <= p_low >> 1;
count_er <= count_er + 1;
end
endmodule
I created a test bench to test the circuit and the first problem I see is that, the AND operation doesn't work as I want it to. The 16-bits of the x-operand are and'ed with the LSB of the y-operand. The y-operand is shifted by one bit after every clock cycle and the final product is calculated by successively adding the partial products.
However, I am having trouble starting from the sum and prev_sum lines and their outputs are being displayed as xxxxxxxxxxxx.
You don't seem to be properly resetting all the signals you need to, or you seem to be confusing the way that nonblocking assignments work.
After initial begin:
sum is 0
prev_sum is 0
and_output is X
After first positive edge:
sum is X, because and_output is X, and X+0 returns X. At this point sum stays X forever, because X + something is always X.
You're creating a register for almost every signal in your design, which means that none of your signals update immediately. You need to make a distinction between the signals that you want to register, and the signals that are just combinational terms. Let the registers update with nonblocking statements on the posedge clock, and let the combinational terms update immediately by placing them in an always #* block.
I don't know the algorithm that you're trying to use, so I can't say which lines should be which, but I really doubt that you intend for it to take one clock cycle for x/y to propagate to q0/q1, another cycle for q to propagate to and_output, and yet another clock cycle to propogate from and_output to sum.
Comments on updated code:
Combinational blocks should use blocking assignments, not nonblocking assignments. Use = instead of <= inside the always #* block.
sum <= and_output + sum; looks wrong, It should be sum = and_output + p_high[31:16] according to your picture.
You're assigning p_low[14] twice here. Make the second statement explicitly set bits [13:0] only:
p_low[14] <= d_in;
p_low[13:0] <= p_low >> 1;
You are mixing blocking and nonblocking assignments in the same sequential always block, which can cause unexpected results:
d_in <= p_high[15];
p_low[14] = d_in;