Verilog + FPGA: If statement for switch - verilog

This is my code to control a RC Servo Motor. The code basically turns the 50MHz frequency to 1KHz.
I am using one of the switches on the FPGA to control the motor. Until the switch is on, none of the program should run.
But that doesn't seem to be happening. I don't know what I'm doing wrong. It's probably a very silly mistake.
module servo(clk,rst,clk_out,switch);
input clk,rst,switch;
output reg clk_out;
reg [15:0] counter;
always #(posedge clk or posedge rst or posedge switch)
if (switch) begin
if(rst) begin
counter <=16'd0;
clk_out <= 1'b0;
end
else if(counter==16'd25000) begin
counter <=16'd0;
clk_out <= ~clk_out;
end
else begin
counter<=counter+1;
end
end
endmodule
Also I tried changing the duty cycle so the motor rotates faster, but this doesn't seem to be working.
module servo (clk,rst,clk_out,switch);
input clk,rst,switch;
output reg clk_out;
reg [15:0] counter;
always #(posedge clk or posedge rst)
if(rst)
begin
counter<=16'd0;
clk_out <= 1'b0;
end
else if (switch)
begin
if(counter==16'd12500)
begin
clk_out <= 1'b1;
counter<=counter+1;
end
else
if(counter==16'd50000)
begin
counter <= 16'd0;
clk_out <= 1'b0;
end
else
begin
counter<=counter+1;
end
end
endmodule

Here's my cut at it - I haven't simulated it, so beware!
module servo(clk,rst,clk_out,switch);
input clk,rst,switch;
output reg clk_out;
reg [15:0] counter;
// clocked blocks should only have the clock and maybe a reset
// in the sensitivity list
always #(posedge clk or posedge rst) begin
if(rst) begin
counter <=16'd0;
clk_out <= 1'b0;
end
else if (switch) begin // 'switch' used as an enable
if(counter==16'd25000) begin
counter <=16'd0;
clk_out <= ~clk_out;
end
else begin
counter<=counter+1;
end
end
else begin
counter <= 16'd0;
end
end
endmodule
First thing I did was to remove the entry for switch in the sensitivity list - for synchronous logic, there should only be a clock and maybe a reset here.
The reset clause for the logic should be first, so I moved the test for switch using it as an enable signal in the main body of the always block. The counter will only run now if switch is high.

Related

Monostable multivibrator simulation

The monostable module implements a monostable multivibrator. It takes in three inputs (clk, reset, trigger) and outputs a single (pulse).
The trigger input triggers the module. When triggered, the output signal (pulse) will switch to a high position for a period of clock ticks, and then return to a low position. The pulse width of the output signal can be set via the PULSE_WIDTH parameter, which represents the period in clock ticks that the signal should stay high.
Now, what is happening is when it gets triggered, immediately output signal (pulse) is getting high.
When triggered, the output signal (pulse) should be high on the next active edge of clk. What changes can be done ?
module monostable(
input clk,
input reset,
input trigger,
output reg pulse = 0
);
parameter PULSE_WIDTH = 20;
reg [4:0] count = 0;
wire countReset = reset | (count == PULSE_WIDTH);
always #(posedge trigger, posedge countReset) begin
if (countReset) begin
pulse <= 1'b0;
end else begin
pulse <= 1'b1;
end
end
always #(posedge clk, posedge countReset) begin
if(countReset) begin
count <= 0;
end else begin
if(pulse) begin
count <= count + 1'b1;
end
end
end
endmodule
module monostable_tb();
reg clk;
reg reset;
reg trigger;
wire pulse;
parameter PULSE_WIDTH = 20;
monostable imonostable(.*);
initial begin
clk=0;
forever #50 clk=~clk;
end
initial begin
$monitor("trigger=%b pulse=%b, count = %0d",trigger,pulse,imonostable.count);
$dumpfile("monostable_tb.vcd");
$dumpvars(0,monostable_tb);
trigger=1'b0;
reset = 1'b0;
#(posedge clk) reset = 1'b1;
#(posedge clk) reset = 1'b0;
#(posedge clk) trigger=1'b1;
#(posedge clk) trigger=1'b0;
repeat(25) #(posedge clk);
$finish;
end
endmodule
Here is a simplified design which sets the output one cycle after the input trigger pulse, and keeps the output high for 20 cycles:
module monostable(
input clk,
input reset,
input trigger,
output reg pulse = 0
);
parameter PULSE_WIDTH = 20;
reg [4:0] count;
always #(posedge clk, posedge reset) begin
if (reset) begin
pulse <= 1'b0;
end else if (trigger) begin
pulse <= 1'b1;
end else if (count == PULSE_WIDTH-1) begin
pulse <= 1'b0;
end
end
always #(posedge clk, posedge reset) begin
if(reset) begin
count <= 0;
end else if (pulse) begin
count <= count + 1'b1;
end
end
endmodule
It now uses a single clock signal, instead of 2. It also uses a simple reset signal, which can avoid potential glitches causing unwanted asynchronous resets.
You should also use nonblocking assignments in the testbench:
#(posedge clk) reset <= 1'b1;
#(posedge clk) reset <= 1'b0;
#(posedge clk) trigger<= 1'b1;
#(posedge clk) trigger<= 1'b0;
If a 1-clock synchronous delay is needed, then run the output thru a flip flop.
module monostable(
input clk,
input reset,
input trigger,
output reg pulse = 0
);
parameter PULSE_WIDTH = 20;
reg [4:0] count = 0;
reg reg_pulse_temp;
wire countReset = reset | (count == PULSE_WIDTH);
always #(posedge trigger, posedge countReset) begin
if (countReset) begin
reg_pulse_temp <= 1'b0;
end else begin
reg_pulse_temp <= 1'b1;
end
end
always #(posedge clk, posedge countReset) begin
if(countReset) begin
count <= 0;
// reset the flop
pulse <= 0;
end else begin
if(pulse) begin
count <= count + 1'b1;
end
end
// flip flop
pulse <= reg_pulse_temp;
end
endmodule

Verilog deterministic behavior

Is following code deterministic? i.e Can it trigger error1 or error2? Is there a recommended way for generating clk2 (same as clk3)
module Test();
reg clk1;
reg clk2;
reg clk3;
reg reset;
initial
begin
clk1 <= 0;
forever
begin
#100;
clk1 <= ~clk1; // 2x freq of clk2/clk3
end
end
always #(posedge clk1)
begin
if(reset) clk2 <= 0;
else clk2 <= ~clk2;
end
initial
begin
clk3 <= 0;
#300;
forever
begin
#200;
clk3 <= ~clk3;
end
end
initial
begin
reset <= 1;
#500;
reset <= 0;
#100;
repeat (20) #(posedge clk1);
$display("Test end");
$finish;
end
always #(posedge clk2)
begin
if(clk1 == 0) $display("Error1");
end
always #(posedge clk3)
begin
if(clk1 == 0) $display("Error2");
end
endmodule;
Your code has problems, but nothing to do with determinism—it is fully deterministic. This is one case where using NBAs <= creates a problem. clk2 gets updated in a delta cycle after clk1 and clk3. That means if you have clock domain crossings from the latter to clk2 like
always_ff #(posedge clk3)
A <= B;
always_ff #(posedge clk2)
C <= A; // A has already been updated with the value of B
So never use NBAs to make assignments to clocks.

clock gating verilog code not working correctly

I'm to trying to code a clock gating logic that allows data to pass only at the posedge write_clk_en. the code is compiled correctly in EDA playground but the output is not as intended.So according to code,
# (posedge write_clk_en)begin
data_in[3] <= 1'b1;
end
at this instance the write_clk_en is disabled, so data_in[3] NBA should be halted and it waits for next valid posedge (which is the next posedge of write_clk_en here), data_in[3] should be written. But that is not happening, rather the gated clock period is also getting considered and the NBA assignment is occurring even when write_clk_en is gated for 4th pulse.What could be the issue ?.the wave form is shown here.
the sv code :
module tb;
logic [4:0] data_in;
logic write_clk;
logic write_clk_en;
logic write_clk_mod;
logic [5:0] write_clk_init;
always//write_clk 500M
begin
write_clk =0;
#10 write_clk = 1;
#10 write_clk = 0;
end
initial begin
$dumpfile("dump.vcd");
$dumpvars;
#10000 $finish;
end
initial begin
data_in=5'b00000;
write_clk_init = 6'b000000;
write_clk_mod=0;
end
initial begin
write_clk_init =6'b110111;
end
initial begin
repeat (3) begin
#(posedge write_clk)begin
if(write_clk_init[0]==1 || write_clk_init[0]==0)
write_clk_mod<=write_clk_init[0];
end
#(posedge write_clk)begin
if(write_clk_init[1]==1 || write_clk_init[1]==0)
write_clk_mod<=write_clk_init[1];
end
#(posedge write_clk)begin
if(write_clk_init[2]==1 || write_clk_init[2]==0)
write_clk_mod<=write_clk_init[2];
end
#(posedge write_clk)begin
if(write_clk_init[3]==1 || write_clk_init[3]==0)
write_clk_mod<=write_clk_init[3];
end
#(posedge write_clk)begin
if(write_clk_init[4]==1 || write_clk_init[4]==0)
write_clk_mod<=write_clk_init[4];
end
#(posedge write_clk)begin
if(write_clk_init[5]==1 || write_clk_init[5]==0)
write_clk_mod<=write_clk_init[5];
end
end
end
always # (*) begin
write_clk_en = write_clk & write_clk_mod;
end
initial begin
# (posedge write_clk_en)begin
data_in[0] <= 1'b1;
end
# (posedge write_clk_en)begin
data_in[1] <= 1'b1;
end
# (posedge write_clk_en)begin
data_in[2] <= 1'b1;
end
# (posedge write_clk_en)begin
data_in[3] <= 1'b1;
end
# (posedge write_clk_en)begin
data_in[4] <= 1'b1;
end
end
endmodule
Within initial blocks, change your NBAs to BAs. NBAs should only be used within an always #(posedge clocksignal) block
Take also into account that in simulations, #(posedge clocksignal) blocks (without the reserved word always) are treated as delays (wait until a rising edge clk event happens, then continue simulation). By the way you have written these blocks in your initial statements, I didn't know for sure if you were aware of their true behaviour. I've rewritten those #(posedge) blocks to make the simulation flow a bit clear.
I have also merged some of your initial blocks into one. Every initial block you have is started at the same time (simulation time 0). Particulary, write_clk_init is assigned in two different initial blocks.
This edited code works as expected. It is also available at https://www.edaplayground.com/x/3VYk
module tb;
reg [4:0] data_in;
reg write_clk;
reg write_clk_en;
reg write_clk_mod;
reg [5:0] write_clk_init;
initial begin
$dumpfile("dump.vcd");
$dumpvars;
#10000 $finish;
end
initial begin
data_in = 5'b00000;
write_clk_init = 6'b110111;
write_clk_mod = 0;
write_clk = 0;
repeat (3) begin
#(posedge write_clk);
if(write_clk_init[0]==1 || write_clk_init[0]==0)
write_clk_mod = write_clk_init[0];
#(posedge write_clk);
if(write_clk_init[1]==1 || write_clk_init[1]==0)
write_clk_mod = write_clk_init[1];
#(posedge write_clk);
if(write_clk_init[2]==1 || write_clk_init[2]==0)
write_clk_mod = write_clk_init[2];
#(posedge write_clk);
if(write_clk_init[3]==1 || write_clk_init[3]==0)
write_clk_mod = write_clk_init[3];
#(posedge write_clk);
if(write_clk_init[4]==1 || write_clk_init[4]==0)
write_clk_mod = write_clk_init[4];
#(posedge write_clk);
if(write_clk_init[5]==1 || write_clk_init[5]==0)
write_clk_mod = write_clk_init[5];
end
end
always #* begin
write_clk_en = write_clk & write_clk_mod;
end
initial begin
#(posedge write_clk_en);
data_in[0] = 1'b1;
#(posedge write_clk_en);
data_in[1] = 1'b1;
#(posedge write_clk_en);
data_in[2] = 1'b1;
#(posedge write_clk_en);
data_in[3] = 1'b1;
#(posedge write_clk_en);
data_in[4] = 1'b1;
end
always begin
write_clk = #10 ~write_clk;
end
endmodule

Shortests version to choose posedge/negedge sensitivity from module parameter?

I want to build a Verilog module so that the user can select the sensitivity of some input clock signal by a module parameter. As an example, I wrote the following counter which can either count up on posedge or negedge selected by parameter clockEdge.
module Counter (clk, reset, value);
parameter clockEdge = 1; // react to rising edge by default
input clk;
input reset;
output reg [7:0] value;
generate
if(clockEdge == 1) begin
always #(posedge clk or posedge reset) begin
if (reset) begin
value <= 0;
end else begin
value <= value + 1;
end
end
end else begin
always #(negedge clk or posedge reset) begin
if (reset) begin
value <= 0;
end else begin
value <= value + 1;
end
end
end
endgenerate
endmodule
This principle is working, however I don't like that the implementation is basically copy and paste for both variants. What would be a shorter version without duplication?
Simplest is to invert the clock with an exor gate. Then use that clock in an always section:
wire user_clock;
assign user_clock = clk ^ falling_edge;
always #(posedge user_clock) // or posedge/negedge reset/_n etc.
test_signal <= ~ test_signal;
If falling_edge is 0 then user_clock and clk have the same polarity and the data is clocked at nearly the same time as you have a rising edge of clk.
If falling_edge is 1 then user_clock and clk have the opposite polarity and the data is clocked nearly the same time as the falling edge of clk.
Be careful when you change the polarity of falling_edge as it can generate runt clock pulses! Safest is to use a gated clock: stop the clock, switch polarity, then start it again.
In both cases user_clock will lag the system clk by small amount. The amount depends on the delay of the exor-gate.
Here is a simulation+:
+test_signal was set to zero in an initial statement.
I think that cut-n-paste in this tiny example is ok, though verilog has some instruments to make it easier for more complicated cases, namely functions and macros. You can use them as well, i.e.
function newValue(input reset, input reg[7:0] oldValue);
if (reset) begin
newValue = 0;
end else begin
newValue = value + 1;
end
endfunction
generate
if(clockEdge == 1) begin
always #(posedge clk or posedge reset) begin
value <= newValue(reset, value);
end
end else begin
always #(negedge clk or posedge reset) begin
value <= newValue(reset, value);
end
end
endgenerate
the other possibility is to use macros with or without paramenters. Methodology-wise macros are usually worse than functions, though here is an extreme example, though in my opinion it makes the code less readable and could have issues with debugging tools.
`define NEW_VALUE(clk_edge) \
always #(clk_edge clk or posedge reset) begin\
if (reset) begin\
value <= 0;\
end else begin\
value <= value + 1;\
end\
end
generate
if(clockEdge == 1) begin
`NEW_VALUE(posedge)
end else begin
`NEW_VALUE(negedge)
end
endgenerate
Implementing custom clock reg that follows posedge or negedge of clk might be one way to do it. This seems to work well on my machine :)
reg myclk;
always#(clk) begin
if(clk) begin
myclk = clockEdge? 1 : 0; #1 myclk = 0;
end else begin
myclk = clockEdge? 0 : 1; #1 myclk = 0;
end
end
always#(posedge myclk or posedge reset) begin
if(reset)
cnt <= 0;
else
cnt <= cnt+1;
end

Verilog: Implement a Pipeline hardware using flipflops

How to create a simple one stage pipeline in Verilog?
The easiest way to create a single state pipeline is create two always block synchronized with piped input(in_pipe) as given below. This work because of how the events are queued in the simulator time cycle.
module pipeline (reset,in,clock,out)
input reset, input, clock;
output out;`
logic reset, input, clock;
reg out, in_pipe;
always #(posedge clock or negedge reset)
begin
if(reset)
begin
in_pipe <= 0;
end
else
begin
in_pipe <= in;
end
end
always #(posedge clock or negedge reset)
begin
if(reset)
begin
out<= 0;
end
else
begin
out<= in_pipe;
end
end
module pipeline#(
parameter PIPE_NUM = 2,
parameter DATA_WIDTH = 32
)(
input clock,
input [DATA_WIDTH-1:0]data_in,
output [DATA_WIDTH-1:0]data_out
);
//synthesis translate_off
initial begin
if(PIPE_NUM < 1) begin
$fatal("Error: PIPE_NUM must be greater than 0!");
end
end
//synthesis translate_on
reg [DATA_WIDTH-1:0]pipeline_reg[PIPE_NUM-1:0]/*synthesis preserve*/;
assign data_out = pipeline_reg[PIPE_NUM-1];
integer p;
always #(posedge clock)begin
pipeline_reg[0] <= data_in;
for(p = 1;p < PIPE_NUM;p = p+1)begin
pipeline_reg[p] <= pipeline_reg[p-1];
end
end
endmodule

Resources