Approach to design valid/ready handshake - verilog

I have implemented valid/ready handshake signals in verilog. I just wanted to know if my approach is right or something is wrong. I shall be happy to know of any improvement.
A simple counter is used as an input to fifo. So when fifo is almost full which is declared when used word of fifo is 8 (8 stacks of fifo are used out of 16), ready is zero.
Here is the code.
module fifohandshake(
input CLK,
input RST,
input [31:0] INPUT,
output [31:0] OUTDATA,
output [3:0] usedword,
output Writereq,
input RDReq,
output Almost_full,
output EMPty,
output FUlL,
output VALID,
output READY
);
reg valid;
reg ready;
reg WRReq;
assign VALID=valid;
assign READY=ready;
assign Writereq=WRReq;
fifoip u0(
.clock(CLK),
.data(INPUT),
.rdreq(RDReq),
.sclr(RST),
.wrreq(WRReq),
.almost_full(Almost_full),
.empty(EMPty),
.full(FUlL),
.q(OUTDATA),
.usedw(usedword)
);
always #(posedge CLK)
begin
if(INPUT)
begin
valid<=1;
end
else
begin
valid<=0;
end
end
always #(posedge CLK)
begin
if(Almost_full)
begin
ready<=0;
end
else
begin
ready<=1;
end
end
always #(posedge CLK)
begin
if(ready)
begin
WRReq<=1;
end
else
begin
WRReq<=0;
end
end
endmodule
Have I done it in a right way or is there something that I need to correct? Here are the waveform results.
enter image description here

For those who think that I didn't put enough effort in my research. A finite state machine is a good approach to implement ready/valid handshake protocol. Few points have to be kept in mind
The valid signal doesn't depends upon ready signal. In other words there shouldn't be a combinational loop if you trace your logical circuit from valid to ready signal.
Three basic states can be defined for valid/ready protocol. First idol state where there is no valid data even though the slave is ready to accept data. Then, a transfer state where both ready and valid signals are high. And the third state is wait state where we have the valid signal high but ready signal is low.
A buffer (a fifo or a simple register) has to be used in the wait state to buffer the valid data in case the slave is no ready. Hence, data is not lost and is still on the data line whenever slave is again ready.
That's it....
This was the help that I was trying to ask from the community but from the last couple of days whenever I post something someone intentionally mark my question to be -1. I hope not to experience it next time...

Related

$fclose placement in testbench

I want to use $fmonitor so that an output value is written to a file every time the value changes.
When I place $fclose inside the initial begin block, there are no errors. However, unsurprisingly, the output file is empty.
When I place $fclose right before the endmodule statement, I get a syntax error. Where should I place it?
`timescale 1ns / 1ps
module fir168_input_ones_tb();
integer fp;
reg clk, rst;
wire tvalid, fir_valid, fir_rdy;
wire [15:0] inputdata;
wire signed [39:0] fir_out;
generateOnes indata(
.clk (clk),
.outData (inputdata),
.tlast (tvalid));
fir168 fir168_i
//(.M_AXIS_DATA_0_tdata(fir_out_trunc),
(.M_AXIS_DATA_0_tdata(fir_out),
.M_AXIS_DATA_0_tvalid(fir_valid),
.S_AXIS_DATA_0_tdata(inputdata),
.S_AXIS_DATA_0_tready(fir_rdy),
.S_AXIS_DATA_0_tvalid(tvalid),
.aclk_0(clk));
always begin
clk = ~clk; #5;
end
initial begin
fp = $fopen("simOutput.txt", "w+");
$fmonitorh(fp, fir_out);
clk = 0;
//$display("%d", fir_out);
//$fclose(fp);
end//initial
$fclose(fp);
endmodule
$fopen/$fmonitor/$fclose are all procedural statements that must be placed inside procedural code.
When you had $fclose in the initial block, you closed it at time 0 before $fmonitor had a chance to produce any output. $fmonitor writes the state of its arguments at then end of current time slot when any of them change value.
You need to let your simulation run for some period of time and then have it execute a $finish. There is no need to explicitly use $fclose unless you have too many files open at one time, or some other process is blocked waiting for the file output.
$fclose must be used inside a procedural block, like an initial block. That is why you get the syntax error when you place it right before endmodule.
If you want the file to be written until the end of the simulation, there is no need to call $fclose. The file will automatically be closed at the end of the sim.
Otherwise, you need to pick a specific time or a signal event and then close the file. But, keep in mind that $fmonitor will be active for the entire simulation. That means that if fir_out changes after you close the file, your simulator might generate error or warning messages.
$fmoniotor statement does not do much, except it schedules monitor events at the end of every simulation tick. As a result, the $fclose will close the file in the same time tick where $fmonitor was issued before the first execution of a scheduled monitor event.
initial begin
$fmonitor(...);
...
$fclose()
end
You can do several things:
Put a certain timing distance between $fmonitor and $fclose, giving a chance for simulation to do something before the file gets closed:
initial begin
$fmoniotor(..);
...
#1000 // add a simulation delay of some value before closing
$fclose(...);
end
you can place $fclose in the final block if you want to close it before exit:
initial begin
$fmonitor(...);
...
end
final begin
...
$fclose(...);
end
Or you can figure out some event scheme which will close your file when a certain event is generated.
initial
$fmonitor
always #* begin
if (condition)
$fclose()
end

How to set a signal at both posedge and negedge of a clock?

I'm trying to implement a controller with the function that sends out the same clock signal as its input clock. But the controller can also halt the output signal if needed. I'm implementing it on Xilinx ISE.
My idea is: At the negedge of the input clock, the output clock signal set to 0. At the posedge of the input clock, if I want to send out the clock I'll set the output clock to 1, but if I want to halt the output clock, I'll set the output clock to 0 so other devices (all posedge-triggered) won't detect the posedge.
Here's my design:
module controller(
input clk_in,
input reset,
output clk_out
//and other ports
);
always #(negedge clk_in)
clk_out<=0;
always #(posedge clk_in)
if(reset)
clk_out<=1;
else
begin
case(cases)
case1:
begin
//do something and halt the output clock
clk_out<=0;
end
case2:
begin
//do something and continue the output clock
clk_out<=1;
end
endcase
end
When I synthesized the design I had an error saying the signal clk_out is connected to multiple drivers. Is there any way to solve it?
You have two different always blocks which drive the same signal clk_out. This is what synthesis tells you about. All signals in a synthesizable rtl must be driven from a single block only.
It looks like you are trying to create some type of a gated clock. Instead of going through the trouble of detecting negedges of the clock, which most likely will not be synthesizable as well, you can use a simple logic to do so:
always #*
clk_out = enable & clk_in;
You just have to figure out how to generate enable.
BTW, never use NBAs (<=) in generating clock signals or you end up with clock/data race conditions.

How is the program block controlling the clock output in this code?

This is a simple SV program (I know an arbiter is much more complex, pardon me for naming this as one), but I don't know how the line repeat(4) #ar.cb; keeps controlling the entire clock. If I comment out that line, the clock stops even though I have put it in an 'always' block inside the top module. I can't understand how this works.
testbench.sv
interface arb_if(input bit clk);
logic [1:0] request;
logic [1:0] grant;
logic reset;
clocking cb #(posedge clk);
output request;
input grant;
endclocking
modport DUT(input request,clk,reset,output grant);
modport TB(clocking cb,output reset); endinterface
program automatic test(arb_if.TB ar);
initial begin
ar.reset <= 1;
ar.cb.request<=$urandom;
$display("[%0t]Request is sent",$time);
repeat(4) #ar.cb;
$display("[%0t]Grant=%0d",$time,ar.cb.grant);
end endprogram
module top;
bit clk;
always #5 clk=~clk;
arb_if arb(clk);
test tb(arb);
arbit a1(arb,clk); endmodule
design.sv
module arbit(arb_if.DUT arbiter,input bit clk); always #(posedge clk)
if(arbiter.reset==0)
arbiter.grant<=2'bxx;
else
#1 arbiter.grant<=arbiter.request;
endmodule
And in the design, the grant does not get assigned till the next cycle even if I use a blocking assignment (unless I give #1, in which case it does, of course after the delay).
I am struggling with understanding the synchronous circuit timings. It'd be a great help if someone can clear this up for me.
Without #1:
With #1:
The program terminates the simulation.
From IEEE Std 1800-2017, section 24.3 The program construct:
When all initial procedures within a program have reached their end,
that program shall immediately terminate all descendent threads of
initial procedures within that program. If there is at least one
initial procedure within at least one program block, the entire
simulation shall terminate by means of an implicit call to the $finish
system task immediately after all the threads and all their descendent
threads originating from all initial procedures within all programs
have ended.
With the repeat statement, the simulation ends at time 35. It waits for 4 positive edges of clk, then implicitly calls $finish.
Without the repeat statement, the simulation ends at time 0. It doesn't wait for any clk edges, then implicitly calls $finish.

In Verilog, can "always #(posegde)" or "always #(negegde)" work on a register variable?

I am a Verilog newbie and I am trying to implement some very simple logic to generates a pulse of a precise width. I am using an ICE40 FPGA dev board and IceStudio. I have a CLK signal with a period of ~83ns (12Mhz), and I want to generate pulses with a period of ~1245ns, but different lengths (i.e. a high time of ~415ns and a low time of ~830ns, for example).
I figured that I could do so by making a rotating shift register of 15 bits long and then toggle my output HIGH the rising edge of the first bit, then toggle it LOW on the falling edge of the fifth bit. Here is the code I came up with:
reg [14:0] shifter;
reg OUT;
initial begin
shifter <= 15'b01;
end
always #(posedge CLK) begin
shifter <= shifter << 1;
shifter[0] <= shifter[14];
end
always #(posedge shifter[0]) begin
OUT <= 1;
end
always #(negedge shifter[4]) begin
OUT <= 0;
end
If I assign the individual bits of "shifter" to an output, I am able to verify on a scope that that shift register is working as expected; but despite this, the OUT remains LOW as if the "always" blocks were never triggering.
Every tutorial I found online that discusses the "always #(posegde)" or "always #(negegde)" blocks do it on some external signal like CLK or RESET. I am wondering I am committing some sort of rookie mistake by assuming it could also work on an internal register variable like "shifter".
Can anyone explain to me whether this is the case or not?
UPDATE: The following code does what I want, but still curious why my original implementation doesn't work:
reg [14:0] shifter;
reg OUT;
initial begin
shifter <= 15'b01;
end
always #(posedge CLK) begin
shifter <= shifter << 1;
shifter[0] <= shifter[14];
OUT <= shifter[0] | shifter[1] | shifter[2] | shifter[3] | shifter[4] | shifter[5];
end
When making a register out of NAND gates, a rising edge triggered flip-flop takes less area, so that is what most people use.
Synthesis tools do not allow you to make assignments to the same variable from different (always) processes.
It is possible to declare a sensitivity on the edge of a register signal, but this should be avoided in FPGA workflows. Most FPGAs use separate routing networks for clock signals and logic, so "bridging" a logic signal to a clock network is complex and will result in a suboptimal design with poor timing properties. In some cases, there may even be limits on the number of signals that can be bridged this way.
It is generally not possible to perform nonblocking assignments to a register from multiple separate edge-triggered always blocks. This implies a register with multiple clock inputs, which isn't a component which exists in most FPGAs or ASIC cell libraries.

Unexpected delay in Verilog adder

I have written some Verilog code for an adder with 10 inputs. After simulation I am getting the output with one extra clock delay. Why am I getting this delay?
`timescale 1ns/1ps
module add_10(z0,z1,z2,z3,z4,z5,z6,z7,z8,z9,clk,reset,o);
input [7:0] z0,z1,z2,z3,z4,z5,z6,z7,z8,z9;
input clk,reset;
output reg[15:0] o;
always # (posedge clk or negedge reset)
begin
if (!reset)
o=16'b0000;
else
o = z0+z1+z2+z3+z4+z5+z6+z7+z8+z9;
end
endmodule
After asserting the reset, I am getting the output after one clock. But according to the code I wrote, it should come at the next posedge clk when reset=1.
It looks like it's working as it should to me.
I think you're misunderstanding how the reset signal is meant to be used. The reset signal should be kept high at all times. When it goes low, the output will be cleared immediately (it changes on the negative edge). When it goes high, the output will take on the sum of the inputs on the next clock cycle.
If you wanted to update on the positive edge of the reset signal, use the positive edge...
always # (posedge clk or posedge reset)
...
Just beware that doing so will likely affect your minimum cycle times.
I suggest you change the timing of reset with respect to clk in your testbench. The way you have it, reset and clk change simultaneously. I believe the simulator enters your always block as a result of posedge clk, while the value of reset is still 0, and therefore assigns 0 to your output.
I would shift the reset to the left or to the right of the posedge of the clock. That should give you the effect you are looking for.
Your code is probably working as expected, but it may not be. The issue is (a) that you're not showing how reset is generated, and (b) you're using blocking assignments (which you shouldn't be; use <=), so you may have a race elsewhere, in your reset generation.
Show the code that generates reset. If there are no race conditions, then your waveform is correct; edge A clears reset, but this isn't seen by your adder, which thinks that reset is still asserted; the adder sees it de-asserted on the next clock edge, so produces a result.

Resources