I have this 4 bit ring counter that I'm trying to make, and I feel like I'm so close, but I can't figure out how to make one input depend on the previous state's output. Here's what I have:
`default_nettype none
// Empty top module
module top (
// I/O ports
input logic hz100, reset,
input logic [20:0] pb,
output logic [7:0] left, right
);
// Your code goes here...
q[3:0];
assign q[3:0] = right[3:0];
hc74_set setFF(.c(pb[0]), .d(pb[1]), .q(right[0]), .sn(pb[16]));
hc74_reset resetFF1(.c(pb[0]), .d(pb[1]), .q0(right[1]), .rn(pb[16]));
hc74_reset resetFF2(.c(pb[0]), .d(pb[1]), .q1(right[2]), .rn(pb[16]));
hc74_reset resetFF3(.c(pb[0]), .d(pb[1]), .q2(right[3]), .rn(pb[16]));
endmodule
// Add more modules down here...
// This is a single D flip-flop with an active-low asynchronous set (preset).
// It has no asynchronous reset because the simulator does not allow it.
// Other than the lack of a reset, it is half of a 74HC74 chip.
module hc74_set(input logic d, c, sn,
output logic q, qn);
assign qn = ~q;
always_ff #(posedge c, negedge sn)
if (sn == 1'b0)
q <= 1'b1;
else
q <= d;
endmodule
// This is a single D flip-flop with an active-low asynchronous reset (clear).
// It has no asynchronous set because the simulator does not allow it.
// Other than the lack of a set, it is half of a 74HC74 chip.
module hc74_reset(input logic d, c, rn,
output logic q, qn);
assign qn = ~q;
always_ff #(posedge c, negedge rn)
if (rn == 1'b0)
q <= 1'b0;
else
q <= d;
endmodule
This is on an FPGA simulator, which is why there are a few things like pb (these are push buttons) and left, right outputs which are sets of 8 LEDs each.
Let's first make sure we are on the same page
Based on wikipedia description of a ring counter
This could be implemented as follows:
module top (
// I/O ports
input logic reset_n,
input logic clk,
output logic [3:0] ring
);
// Your code goes here...
always #(posedge clk or negedge reset_n) begin
if(~reset_n) begin
ring = 4'b0001;
end
else begin
ring[0] <= ring[3];
ring[1] <= ring[0];
ring[2] <= ring[1];
ring[3] <= ring[2];
end
end
endmodule
The output ring is a 4-bit one hot vector, reset_n = 0 makes ring = 0001 every clock with reset_n = 1 rolls the ring to the right, [0001, 0010, 0100, 1000, 0001, ...].
But you want to use instances of the flops you defined. Notice that in an assignment a <= b, a is the output of the flop (q port), and b is the input of the flop (d port).
module top (
// I/O ports
input logic reset_n,
input logic clk,
output logic [3:0] ring
);
// Your code goes here...
hc74_set setFF(.c(clk), .d(ring[3]), .q(ring[0]), .sn(reset_n));
hc74_reset resetFF1(.c(clk), .d(ring[0]), .q0(ring[1]), .rn(reset_n));
hc74_reset resetFF2(.c(clk), .d(ring[1]), .q1(ring[2]), .rn(reset_n));
hc74_reset resetFF3(.c(clk), .d(ring[2]), .q2(ring[3]), .rn(reset_n));
endmodule
You have to connect the ports accordingly, I just used clk for the clock and reset_n for the negated reset signal.
I have to write a single SVA for the complete protocol shown in this image
I wrote the following SVA but it doesn't capture the immediate ack. How do I fix that
#(posedge clk)
$rose(val) |=>
( $stable(data) && !ack && val ) ##[1:64] ( ack && val ) ##1 ( !ack && !val )
Looking at your assertion, it won't capture the immediate ACK because you are expecting a sequence excluding an immediate ACK with !ack. I would re-write your assertion as:
sequence seq;
$stable({address, data}) ##[0:63] (val && ack && $stable({address, data})) ##1 !ack ##1 !val;
endsequence
property p;
#(posedge clk)
$rose(val) |=> seq;
endproperty
as_protocol : assert property(p);
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;
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)
)
);
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;