This is my main code. The function is switching the light on or off when I toggle.
Maybe the t filp-flop can help?
module demo(
input switch1,switch2,
output reg light=1'b0
);
always#(switch1 or switch2)
begin
light <= ~light;
end
endmodule
And the testbench
`timescale 1ns/100ps
module demo_test;
reg switch1,switch2;
wire light;
demo d1(.switch1(switch1),
.switch2(switch2),
.light(light));
initial
begin: in_set_blk
#0 switch1 =1'b0;
switch2 =1'b0;
$display ($time, "light=%d \n",light);
#10 switch1 =1'b1;
switch2 =1'b0;
$display ($time, "light=%d \n",light);
#10 switch1 =1'b0;
switch2 =1'b0;
$display ($time, "light=%d \n",light);
#10 switch1 =1'b0;
switch2 =1'b1;
$display ($time, "light=%d \n",light);
#10 switch1 =1'b0;
switch2 =1'b0;
$display ($time, "light=%d \n",light);
#10 $stop;
#10 $finish;
end
endmodule
This is the modelsim waveform diagram; I think it works well:
This is the diagram in RTL viewer; that is the strange part:
Diagram in RTL viewer is so strange; the input even didn't connect to the inverter.
Any error in my main Verilog code?
Yes, the problem is that your demo module Verilog code is not synthesizable.
Not all legal Verilog code is synthesizable. Synthesis tools recognize specific coding patterns, but your code does not match any of those patterns. There should be documentation with your FPGA tool set that shows what syntax is supported for synthesis.
This is why your RTL viewer tool gives you a strange diagram.
Here is how the simulation works. At time=0, you set light and the 2 switch inputs to 0. At time=10, you change switch1 to 1. This triggers the always block, executing the light <= ~light; assignment. This sets light=1.
Every time either of the inputs change, the always block is triggered, causing light to toggle.
If that is how you want the design to work, you should consider using edge detectors. However, that requires flip-flops and a clock.
Your code represents an implied latch, which is usually not synthesizable. This is a common mistake when you try to use always blocks with sensititivity lists (verilog 95). Your code will simulate correctly, but synthseis requres that all inputs of the always block are listed in the sensitivity list and all elements from the sensitivity list must be inputs to the block (flops excluded).
always#(switch1 or switch2)
begin
light <= ~light;
end
In the code above the result is not a function of the switch1,2 listed in the sensitivity list and sensitivity list does not include light.
In your case a flop is needed. light <= ~light represents a zero-delay loop if used in combinatorial logic or in a latch. It can only be resolved with a flop.
Flop needs a clock. Clock must be generated in test bench and flagged in synthesis.
The code can look like the following:
always#(posedge clk) begin
if (switch1 || switch2)
light <= ~light;
end
Flops are recognized by synthesis tools due to specific programming pattern and do not require listing of all inputs.
As a general suggestion: do not use sensitivity lists for combinatorial logic or latches (flops excluded). Modern verilog (v2k) allows you to use always #* construt instead.
Related
For Example, what is the difference between these two implementations?
with initial statment:
module with_initial();
reg clk,reset,enable,data;
initial begin
clk=0;
reset=0;
enable=0;
data=0;
end
always #(…)
..
end
endmodule
and here without using an initial statement:
module without_initial();
reg clk,reset,enable,data;
clk=0;
reset=0;
enable=0;
data=0;
always #(…)
..
end
endmodule
The code in without_initial is not legal syntax, and it should produce compile errors for you, as it does for the simulators on edaplayground.
Procedural assignments must be inside an initial or always block. Refer to IEEE Std 1800-2017, section 10.4 Procedural assignments.
Also, a reg can be declared with an initial value outside of an initial block:
module without_initial;
reg clk=0;
reg reset=0;
reg enable=0;
reg data=0;
endmodule
Refer to IEEE Std 1800-2017, section 6.8 Variable declarations.
Initial block is where your execution starts and they execute at
time 0. This is a non synthesiable procedural statement ( in the sense it cannot be modelled to hardware) . It is just used for initializing all the variable and drives them with specific values.
In veriog (HDL) it's however mandatory to have atleast one initial block . Maybe if you skip adding that block the error caused would be due to following reasons :
1) The compiler never knowing what to drive into the modelled gates used in your code .
2) The assignment to the variables never happen.
Not so damn sure about it. But this is what I feel happens behind the scenario.
I write simple code using ISE 14.7 to generate clock signal, but the output in iSim is always 1, until I change = with <= then the clock works, could you tell me why?
module nonblocking( clk );
output reg clk;
initial
#10 clk =0;
always # (clk)
#10 clk = ~ clk; // change to <= to work
endmodule
This code honestly doesn't make any sense.
Your current code states that based on clk, the value of clk should be ~clk.
When you use <= you are at least specifying a nonblocking assignment, which makes slightly more sense, but still doesn't.
If you want a clock generator for simulation, use the following within an initial block (giving a 10ns period):
forever begin
#5 clk <= ~clk;
end
If you want a clock generator for FPGA synthesis, either connect a physical oscillator to your device's clock input pin, or use a built-in oscillator (if available on your device). You can always use a DCM/PLL/CMT/MMCM/whatever your FPGA calls it to adjust the clock frequency.
I believe that SystemVerilog is a much higher level of abstraction in coding. Is it possible to interface a SystemVerilog module with a verilog module? Are they any aspects that should be kept in mind when trying to integrate them?
Verilog and SystemVerilog are the same language - that is, anything you know about Verilog exists in SystemVerilog. From a synthesis point of view, you will sill be connecting bit of signals with other bits of signals. Its just that with SystemVerilog, you will have more advanced ways of declaring those signals, and many more operators to manipulate those signals.
Without knowing any SystemVerilog, I suggest that you learn it by itself before trying to integrate older Verilog modules with SystemVerilog modules. It will be difficult to explain what to look out for.
One thing that does carry over from Verilog to SystemVerilog is the concept of nets(wires) and variables(regs). Make sure you have a clear understanding of that, plus the new semantics SystemVerilog adds. I have a small article on it. Verilog only allowed wires to pass through ports and did not enforce directions. SV allows variables to pass through ports (meaning variables on both sides of the port connection) but strongly enforces directionality.
Yes, it is possible to interface system verilog module to verilog module.
Before that you must have understanding regarding signals (variable) which are used in verilog module.
You have to create interface from which your verilog signals are connected to system verilog module.
So, data transfer between verilog and system verilog module is possible.
Here I provide verilog module and system verilog module. Main part of code is interface from which verilog and system verilog module are connected.
verilog module code :
module dff(qn,d,clk,reset);
output qn;
input d,clk,reset;
reg qn;
always#(posedge clk,negedge reset)
begin
if (!reset)
begin
qn=1'bx;
end
else if (d==0)
begin
qn=0;
end
else if (d==1)
begin
qn=1;
end
end
endmodule
System verilog module code :
interface melay_intf(input bit clk);
logic o,clk,rst,i;
clocking c1#(posedge clk);
input o;
output i,rst;
endclocking
endinterface
module top;
bit clk;
always
#1 clk = ~clk;
melay_intf i1(clk);
dff d1(.o(i1.o),.clk(i1.clk),.rst(i1.rst),.i(i1.i));
melay_tes(i1.tes);
endmodule
program melay_tes(melay_intf i1);
initial
#100 $finish;
initial
begin
i1.rst <= 0;
#4 i1.rst <= 1;
#4 i1.rst <= 0;
i1.i = 1;
#2 i1.i = 0;
#2 i1.i = 1;
#2 i1.i = 0;
#2 i1.i = 1;
#2 i1.i = 0;
repeat(10)
begin
i1.i = 1;
#2 i1.i = $urandom_range(0,1);
end
end
initial
$monitor("output = %d clk = %d rst = %d i = %d",i1.o,i1.clk,i1.rst,i1.i);
initial
begin
$dumpfile("mem.vcd");
$dumpvars();
end
endprogram
Here important part is interface and in it I used clocking block for synchronization purpose.
Here clocking c1#(posedge clk); so all signals which are mention inside the clocking block which are i,o,rst.All this signal change its value at every posedge of clk signal.
Here dff d1(.o(i1.o),.clk(i1.clk),.rst(i1.rst),.i(i1.i));
Important thing that you find in top module I made connection between verilog signals and system verilog signals.
You can find verilog module name is "dff".
I took the instance of dff verilog module and made the connection.
Here i1.o,i1.clk,i1.rst,i1.i is system verilog signals which are connected to o,clk,rst,i signals of verilog module of with dot convention.
System verilog (SV) is mainly used for design verification, so the thing is that the DUT (Device Under Test) is written in verilog mainly because verilog can be synthesized mostly. SV is then used to write verification environment for that DUT.
Interfaces are needed in between to connect the SV with the DUT which is verilog. Separate file is written is SV to specify what are the different connection between the two files. This file say INTERFACE file is included in all the separate blocks which need those connections.
You can refer the IEEE standard https://standards.ieee.org/getieee/1800/download/1800-2012.pdf for further information on SV.
I am new to Verilog, so this question might be quite dumb.
What I am trying: I have a component that has a clk, an 8 bit input and an 8 bit output. What it should do, is:
If the clock event is negative edge, it should set the output to 0
If the clock event is positive edge, it should set the output to whatever input is at this moment of the edge event. During the high phase of the clock, the output should NOT change, regardless changes on the input.
What I tried so far:
always #(negedge clk)
_ledOut <= 0;
always #(posedge clk)
_ledOut[RowSize-1:0] <= ledIn[RowSize-1:0];
This tells my, that it can't resolve multiple constant drivers for net _ledOut.
However, putting this together in an always #(negedge clk, posedge clk) tells me, it can't test for both conditions.
So I tried to make just one always #(clk) block and then used an if statement:
always #(clk) begin
if(clk == 0)
_ledOut <= 0;
else if(clk == 1)
_ledOut[RowSize-1:0] <= ledIn[RowSize-1:0];
end
But this didn't just switch on a clk event. During the high phase of the clock, it links _ledOut with ledIn, so that changes on ledIn do also have effect on _ledOut. What am I doing wrong here?
Best regards,
Michael
This tells my, that it can't resolve multiple constant drivers for net
_ledOut.
For synthesis you cannot assign reg types from multiple always blocks.
However, putting this together in an always #(negedge clk, posedge
clk) tells me, it can't test for both conditions.
This essentially describes a DDR register. While many FPGA devices have these they typically cannot be synthesized. Xilinx uses ODDR2 and IDDR2 primitives if you really need this functionality.
If the clock event is negative edge, it should set the output to 0 If
the clock event is positive edge, it should set the output to whatever
input is at this moment of the edge event. During the high phase of
the clock, the output should NOT change, regardless changes on the
input.
If this is all you need then you can use a D flip flop with an AND gate on the output. The flip-flop will sample ledIn on each rising edge of clk and the AND gate will mask the output whenever the clock is zero. This is not ideal as you generally do not want clocks to touch non-sequential logic but avoiding this would likely mean changing your requirements.
As toolic indicated, the code you posted will work but you should understand that code will synthesize to a multiplexer controlled by clk.
Ok, here is my working solution now. Maybe it's not the best verilog code you have seen out there. ;) This is, however, my first thing I do with it, as a project at my university. So as long as it does what I want it to do, this is a great success to me! ;)
Here is the code I used now, thanks to Adam12:
parameter RowSize = 8;
input clk;
input [RowSize-1:0] ledIn;
output [RowSize-1:0] ledOut;
reg[RowSize-1:0] _ledOut;
assign ledOut = _ledOut & {RowSize{clk}};
always #(posedge clk) begin
_ledOut[RowSize-1:0] <= ledIn[RowSize-1:0];
end
Consider the following stimulus:
module tb;
parameter RowSize = 8;
reg clk;
reg [7:0] ledIn, _ledOut;
always #(clk) begin
if(clk == 0)
_ledOut <= 0;
else if(clk == 1)
_ledOut[RowSize-1:0] <= ledIn[RowSize-1:0];
end
initial begin
$monitor($time, " clk=%b ledIn=%h _ledOut=%h", clk, ledIn, _ledOut);
ledIn = 0;
#22 ledIn = 8'h55;
#20 $finish;
end
always begin
#5 clk <= 0;
#5 clk <= 1;
end
endmodule
It produces this output:
0 clk=x ledIn=00 _ledOut=xx
5 clk=0 ledIn=00 _ledOut=00
10 clk=1 ledIn=00 _ledOut=00
15 clk=0 ledIn=00 _ledOut=00
20 clk=1 ledIn=00 _ledOut=00
22 clk=1 ledIn=55 _ledOut=00
25 clk=0 ledIn=55 _ledOut=00
30 clk=1 ledIn=55 _ledOut=55
35 clk=0 ledIn=55 _ledOut=00
40 clk=1 ledIn=55 _ledOut=55
Notice at time 22, when ledIn changes, the _ledOut output does not change. _ledOut only changes at the next posedge of clk at time 30. Therefore, the always #(clk) solution is doing what you want: the output only changes at the clock edge, as you specified.
This is a pretty unusual question, and it makes me advise you need to give more information about what you are actually trying to achieve, since it may well impact the timing performance and clock constraints if this is targeting an FPGA. Synthesis has been mentioned, but what will you be feeding the clock-gated output into? If it's a pin-pad, then you should read the DDR pad buffers in the device specifications and infer the specific primitive to be able to drive a DDR signal.
If you are keeping this signal within the chip then this is a very bizarre request. If I needed to generate that waveform, I would probably use a PLL to generate a phase-locked clock at twice the base frequency and put the gated data into that domain, with a toggle to apply the mast, so that the tooling will be able to properly analyse the clock crossings and the resulting data path is still effectively transitioning on a single edge.
The answers above to infer a register with a combinatorial multiplexer forced on the output is interesting, but whatever you feed this into will have to deal with awkward setup/hold conditions, and if on-chip, would only be sampling one edge anyway, so this is kind of redundant.
Which code is better in writing a RAM?
assigning data_out inside always block:
module memory(
output reg [7:0] data_out,
input [7:0] address,
input [7:0] data_in,
input write_enable,
input clk
);
reg [7:0] memory [0:255];
always #(posedge clk) begin
if (write_enable) begin
memory[address] <= data_in;
end
data_out <= memory[address];
end
endmodule
assigning data_out using assign statement:
module memory(
output [7:0] data_out,
input [7:0] address,
input [7:0] data_in,
input write_enable,
input clk
);
reg [7:0] memory [0:255];
always #(posedge clk) begin
if (write_enable) begin
memory[address] <= data_in;
end
end
assign data_out = memory[address];
endmodule
Any recommendations?
It depends on your requirements.
This registers your memory output. If you are synthesizing this to gates, you will have 8 more flip-flops than in case 2. That means you use a little more area. It also means your output will have less propagation delay relative to the clock than case 2. Furthermore, the output data will not be available until the next clock cycle.
Your output data will be available within the same clock cycle as it was written, albeit with longer propagation delay relative to the clock.
You need to decide which to use based on your requirements.
A third option is to use a generated RAM, which is a hard macro. This should have area, power and possibly timing advantages over both case 1 and 2.
to add to toolic's answer - if you use the asynchronous read method (case 2), it won't map to a RAM block in an FPGA, as the RAM blocks in all the major architectures I'm aware of have a synchronous read.
Both forms are valid, depending on the type of pipelining you want. I always recommend following the Xilinx RAM coding guidelines -- it's a good way to ensure that the code synthesizes into proper FGPA constructs.
For example, your example 1 would synthesize into into Xilinx BRAM (i.e., dedicated Block Ram), since it is synchronous read, and your example 2 would synthesize into Xilinx Distributed Ram (since it is asynchronous read).
See the coding guidelines in Xilinx document UG901 (Vivado Design Suite User Guide), in the RAM HDL Coding Techniques section. It also has a good description of the difference between synchronous read and asynchronous read for RAMs.
In the second program, there would be compilation error as we can not 'Assign' a value to 'Reg'.
It will give an error saying: 'Register is illegal in left-hand side of continuous assignment'