[Verilog]Why my counter's output delays one more clock? - counter

My partial program is as followed, it's a FSM to handle the traffic light,and the register "times" (from 4 to 1) is to compute the time that the traffic light should brighten, But whenever "times" counts to "1", the time of "times=1" is longer than other "times" about one clock.
For example:when times = 4~2,every clock will count ,but when times=1,it will take two clocks
to become times=4.
Could anybody tell me how this problem happened?
always#(posedge clk or negedge rst )
if(!rst)
begin
s1<=state1;
A<=3'b0;
B<=3'b0;
count1<=3'd4;
count2<=3'd2;
count3<=3'd3;
count4<=3'd2;
temp<=1'b1;
end
else
begin
if(temp==1)
begin
temp<=1'b0;
case(s1)
state1:
begin
times<=count1;
A<=3'b001;
B<=3'b100;
s1<=state2;
end
state2:
begin
times<=count2;
A<=3'b010;
B<=3'b100;
s1<=state3;
end
state3:
begin
times<=count3;
A<=3'b100;
B<=3'b001;
s1<=state4;
end
state4:
begin
times<=count4;
A<=3'b100;
B<=3'b010;
s1<=state1;
end
default:
begin
A[0]<=3'b000;
B[0]<=3'b000;
end
endcase
end
else
begin
if(times>1)
times<=times-1;
else if(times==1)
begin
temp<=1'b1;//can't count averagely
end
end
end

Related

fork..join in SystemVerilog

I am trying to achieve req ##[3:5]ack using fork..join. I am able to run logic for req##[5]ack. But I am unable to run for req ##[3:5]ack.
I am trying-
wait(req)
fork:check_ack
begin
wait(ack)
$display("Ack passed");
end
begin
repeat(5)
#(posedge clk);
$display("Ack failed");
end
begin
repeat(3)
#(posedge clk);
$display("Ack failed");
end
join_any
disable check_ack;
I need to somehow continue to check after 3 cycles also.
You need to create a state bit that indicates when you are inside the range.
bit in_range;
#(posedge clk iff req);
fork
begin
in_range = 0;
#(posedge clk iff ack) if (in_range) $display("passes");
else $display("fails");
end
begin
repeat(3) #(posedge clk) ;
in_range <='1;
wait(0);
end
begin
repeat(5) #(posedge clk);
$display("fails");
end
join_any
disable fork;

In which programming language this code snippet is written?

The code is written in 1999 and controls a CNC machine. If the code snippet is not adequate to determine the language i can upload the entire file. This is the code segment:
BEGIN CONDITION +S_P0_PRES AND +N_P0__PNLTST ON EXCEPTION BEGIN
SET N_P0_STB OFF
SET N_P0_KEY(*) TO BITS(0)
SET N_P0_LTS(*) TO BITS(0)
SET ..KEY_PLS(*) TO BITS(0)
SET S_P0_KEY_PLS(*) TO BITS(0)
SET S_NCX0_FLEDS(*) TO BITS(0)
IF
:-S_P0_PRES: BEGIN
SET N_P0_ACT OFF
RETURN
END
END IF
WAIT +N_P0__PNLTST OR -S_P0_PRES
END
IF
:+N_P0_STB: BEGIN
LET ..KEY_INX = 0
REPEAT WHILE [INT(..KEY_PLS(*)) <> 0]
IF
:+..KEY_PLS(..KEY_INX): BEGIN
IF
:[..KEY_NUM(..KEY_INX) < 128]: BEGIN
IF
:-..KEY_ISF(..KEY_INX): SET N_P0_KEY(..KEY_NUM(..KEY_INX)) OFF
:+..KEY_ISF(..KEY_INX): SET .P0_NCX_FUN(..KEY_NUM(..KEY_INX)) OFF
END IF
START N_P0__NCXKEY
END
:[..KEY_NUM(..KEY_INX) < LAST(N_P0_KEY(*)) + 1]: BEGIN
SET N_P0_KEY(..KEY_NUM(..KEY_INX)) OFF
START N_P0__MAIKEY
END
:[..KEY_NUM(..KEY_INX) < LAST(.P0_NCX_FUN(*)) + 1]: BEGIN
SET .P0_NCX_FUN(..KEY_NUM(..KEY_INX) - (LAST(N_P0_KEY(*)) - 127)) OFF
START N_P0__FKEY
END
END IF
I think you're looking at APT.

The counter counts strangly

My code describes a FSM to control a traffic light. There are four states, each with a different
duration.
Whenever the counter equals 1, the counter needs one more clock to change to the next value. For example, at state1, counter is programmed to count from 4 to 1. Every value should only take one clock to
change to the next, when it does, the state is changed to the next state. But when counter equals 1, it takes two clocks to change.
My program is as follows. The counter is implemented at the bottom of the always block:
module HW3(times,A,B,clk,rst,iHand,iChang,s1);
input clk,rst;
output reg [2:0]A,B;
wire oclk;//new freq
reg [2:0] count1,count2,count3,count4;//count times
reg [2:0]times;
reg temp;//control the switch
parameter [2:0]state1=3'd0,state2=3'd1,state3=3'd2,state4=3'd3;
always#(posedge clk or negedge rst )
begin
if(!rst)
begin
s1<=state1;
A<=3'b0;
B<=3'b0;
count1<=3'd4;
count2<=3'd2;
count3<=3'd3;
count4<=3'd2;
temp<=1'b1;
end
else
begin
if(temp==1)
begin
temp<=1'b0;
case(s1)
state1:
begin
times<=count1;
A<=3'b001;
B<=3'b100;
s1<=state2;
end
state2:
begin
times<=count2;
A<=3'b010;
B<=3'b100;
s1<=state3;
end
state3:
begin
times<=count3;
A<=3'b100;
B<=3'b001;
s1<=state4;
end
state4:
begin
times<=count4;
A<=3'b100;
B<=3'b010;
s1<=state1;
end
default:
begin
A<=3'b000;
B<=3'b000;
end
endcase
end
else
begin
if(times>1)
times<=times-1;
else if(times==1)
begin
temp<=1'b1;//can't count averagely
end
end
end
end
endmodule
Modify the code at the bottom of the always clock as:
if(times>2)
times<=times-1;
else if(times==2)
begin
times=times-1;
temp<=1'b1;//can't count averagely
end
Just let the times counts to 2 ,because if let it count to 1, the program will again enter the if
block in the next clock but doesnt change the value of times ,and make the value of times=1 unchanged
for one more clock

system verilog assertion trigger==1 4 cycles before signal asserted

How would I write SVA that checks that if sig goes high trigger was high 4 cycles before trigger [*4] |-> signal
is not good enough because it does not check that signal didn't go high for 3 cycles. Should I use $past how ??
This would check that on a rising edge of sig, trigger was high 4 clk cycles ago:
assert_name: assert property (
#(posedge clk) (
($rose(sig) -> $past(trigger,4))
)
);
There's nothing stopping you writing a small piece of synthesisable RTL which counts how many cycles trigger has been high.
always #(posedge clk) begin
if (trigger) begin
triggerCount := triggerCount + 1;
end else begin
triggerCount := 0;
end
end
assert_name: assert property (
#(posedge clk) (
($rose(sig) -> triggerCount == 4)
)
);

Parallel To Serial HDL

I am making a parallel to serial converter using ring counter in verilog. The ring counter is working fine but the Parallel to serial converter is not working properly and I am getting x undefined result. I am providing the code kindly help me finding the problem.
TOP
module PtoSTOP;
reg clk,rst;
wire [3:0] myout;
wire out;
Ring a(clk,rst,myout);
parToser x(myout,clk,rst,out);
initial begin
clk=1;
rst=1;
#1 rst=0;
end
always
#2 clk=~clk;
endmodule
Parallel TO Serial Converter
module parToser(myout,clk,rst,out);
input clk,rst;
input [3:0] myout;
output reg out;
reg [2:0]i;
always #(posedge clk or posedge rst) begin
if(rst) begin
out <= 0;
i <= 0;
end
else begin
out <= myout[i];
i <= i+1;
end
end
endmodule
RingCounter
module Ring(clk,rst,myout);
input clk,rst;
output reg [3:0]myout;
always #(posedge clk or posedge rst) begin
if(rst)
myout<=1;
else
myout<=myout<<1;
end
endmodule
I think the main issue you are seeing is part of parToser.
You have reg [2:0]i; which you increment and use to address input [3:0] myout; but i can hold values 0 to 7, half of which is outside the address range of [3:0] myout. You should be seeing a simulation error about out of range addressing.
Also you have included a few flip-flops with a reset condition but not added the reset to the sensitivity list in 'parToser' & 'Ring':
always #(posedge clk)
Should be:
always #(posedge clk or posedge rst)
With out this trigger your out, i and myout variables will be x, as they have not been set to a known condition.
NB: parToser i = i+1; should be i <= i+1;