Verilog module for a smoke detector and a buzzer - module

I have Altera DE2-115 FPGA and I try to self-learn Verilog. I decided to make a smoke detector and whenever it smells smoke the buzzer rings (the smoke detector outputs a digital signal).
Here is my trial :
module fire(flag,clock,reset,fire,fire_state,firealarm);
input clock, reset, flag, fire;
output [2:0] fire_state;
output firealarm;
wire fire;
reg [2:0] fire_state;
assign firealarm = (fire_state == 1) ? (flag ? 0 : 1) : 0;
always # (posedge clock)
fire_state<= fire ? 1: 0;
end module
But it doesn't run and I think there are a lot of logic errors in this code, any help please? :)

endmodule is one word, you need to remove the space.
Almost all simulators these days support verilog-2001 or greater so I would encourage the use of the modern port style (ANSI) and not the old verilog 1995 style.
Your port list goes from:
module fire(flag,clock,reset,fire,fire_state,firealarm);
input clock, reset, flag, fire;
output [2:0] fire_state;
output firealarm; wire fire;reg[2:0] fire_state;
to :
module fire(
input clock,
input reset,
input flag,
input fire,
output reg [2:0] fire_state,
output firealarm
);
I have placed each port on a new line with it direction, this makes it much easier to maintain code, it also make it a lot more readable and therefore minimises the chance of typos in connections.
You have used this syntax a lot (flag?0:1), where you using a boolean to select a boolean there is no need to do this and makes it more difficult to read. If you need to invert it then is a bitwise invert (~). However it is not clear what you are using flag for.
for comparrisons and assignments you should be including the width.
assign firealarm = (fire_state == 3'b1)? (~flag) : 1'b0;
This could also be written out in a combinatorial always block:
always #* begin
if (fire_state==3'b001) begin
firealaram = ~flag;
else begin
firealaram = 1'b0;
end
end
fire is 1 bit, fire_state is 3 bits.
always # (posedge clock) begin
fire_state <= {2'b0, fire};
end

Related

I am getting error when check my systemverilog code in quartus II

I have this simple code checked with Quartus II. First, It gives me error 5000 iterations for loop limit then I try to change verilog constant loop limit variable in settings and now it is giving me this error
Error (293007): Current module quartus_map ended unexpectedly. Verify that you have sufficient memory available to compile your design. You can view disk space and physical RAM requirements on the System and Software Requirements page of the Intel FPGA website (http://dl.altera.com/requirements/).
Is this something related to tool limitation or am I doing something wrong with my code ?
Here is my code:
module Branch_status_table #(parameter BST_length = 16383) //16383
(
output reg [2:1] status,
output reg [32:1] PC_predict_o,
input wire [2:1] status_update,
input wire [32:1] PC_in, PC_update,
input wire [32:1] PC_predict_update,
input wire clk,en_1,RST
);
wire [14:1] PC_index, PC_index_update;
//Internal memory
reg [2:1] status_bits [BST_length:0];
reg [32:1] PC_predict [BST_length:0];
reg [16:1] PC [BST_length:0];
//Combinational
assign PC_index = PC_in [16:3];
assign PC_index_update = PC_update [16:3];
//
initial begin
for ( int i=0; i <= BST_length; i=i+1) begin
status_bits[i] <= 0;
PC_predict[i] <= 0;
PC[i]<=0;
end
end
//Prediction
always_ff #(posedge clk) begin
if ( (PC[PC_index]==PC_in[32:17]) && (status_bits[PC_index]!=0) ) begin
status <= status_bits [PC_index];
PC_predict_o <= PC_predict [PC_index];
end
else begin
status <= 0;
PC_predict_o <= 0;
end
end
//Update
always_ff #(posedge clk) begin
if (en_1==1) begin
status_bits[PC_index_update] <= status_update;
PC [PC_index_update] <= PC_update[32:17] ;
PC_predict[PC_index_update] <= PC_predict_update;
end
else begin
status_bits[PC_index_update] <= status_bits[PC_index_update] ;
PC [PC_index_update] <= PC [PC_index_update] ;
PC_predict[PC_index_update] <= PC_predict[PC_index_update] ;
end
end
endmodule
There a coding issue and maybe a resource utilization issue.
The coding issue:
The code infers block ram, and is attempting initialize/reset it.
In general you can't reset block rams using a single initial block.
That style of initialization of arrays can be done in a testbench, not in RTL.
Synthesis tools have physical limits.
To reset/initialize a block ram you must write 0 to each address. Use the same type of synchronous process (always #(posedge clk)) because the memory is a synchronous device. Put a mux in front of the write port and use a state machine a start up to write 0's to every address, then when the state machine finishes the state that move to an state where the BRAM behaves like you normally want it to.
This page discusses the issue.
https://www.edaboard.com/threads/how-to-clear-reset-my-bram-in-vhdl-xilinx.247572/
This is a Xilinx related answer; other vendors work the same way.
Summarizing the coding issue: You probably don't need to initialize and you can't do it this way:
initial begin
for ( int i=0; i <= BST_length; i=i+1) begin
status_bits[i] <= 0;
PC_predict[i] <= 0;
PC[i]<=0;
end
end
Potential Utilization Issue:
FPGAs' have finite resources.
The tool seems to be indicating that the code infers more block ram than the part has. To verify this, change parameter BST_length from 16K to something small like 8 and see if the utilization issue ("insufficient memory") goes away. If it goes away then re-design using less memory.
This can also be analyzed by hand knowing how much BRAM the part has and how much you are inferring. Don't infer more than the part has.
The tool is giving different answers with simple code changes because of two issues related to the same inference of BRAM. When the code changes a little the tool switches and informs about the other issue. This is how the tools work sometimes, a first error can mask a second by erroring out so that the 2nd error is not reached.

How to declare a global variable in Verilog?

I am writing to ask how to declare a global variable in Verilog. What declared by parameter and define keywords are essentially constants, not variables.
What I need is the following:
`define Glitch
module Cell ( Shift_In, Shift_Out_Screwed, Clk );
input Clk, Shift_In;
output Shift_Out_Screwed;
wire Shift_Out_Screwed;
wire Shift_Out;
Inverter INV1 ( Shift_In, Shift_Out, Clk );
assign Shift_Out_Screwed = Glitch ? ~Shift_Out : Shift_Out
endmodule
This is a very simple glitch insertion. When Glitch==1, the original output is reversed; when Glitch==0, the original output is kept unchanged. I want the signal Glitch to be defined in an external simulation testbench.v file although it is declared and used here, and I don't want to add the signal Glitch to the input port list of the module cell. This is because that my real circuit is a very complicated one, and if I add an input port to a certain cell, there will be many other cells affected.
Does anyone know how to declare a global variable in Verilog?
The problem you are wrestling with sounds like error injection. You want the ability to inject a bit error on an output port from within a testbench. You can do it like this:
module Cell ( Shift_In, Shift_Out_Screwed, Clk );
input Clk, Shift_In;
output Shift_Out_Screwed;
wire Shift_Out_Screwed;
wire Shift_Out;
Inverter INV1 ( Shift_In, Shift_Out, Clk );
`ifdef SIMULATION
// This logic is used in simulation, but not synthesis. Use care.
logic Glitch = 1'b0;
assign Shift_Out_Screwed = Glitch ? ~Shift_Out : Shift_Out
`else
// This logic is used in synthesis, but not simulation. Use care.
assign Shift_out_Screwed = Shift_out;
`endif
endmodule
Note that I use the "SIMULATION" preprocessor switch to hide the "Glitch" error injection from synthesis. Use this technique with care to avoid creating simulation/synthesis mismatches.
In your testbench, you can induce a glitch in a specific instance of your cell by referencing the "Glitch" signal in the design hierarchy, like this:
initial begin
...
#(posedge Clk); #1;
$top.u_foo.u_bar.u_cell.Glitch = 1'b1;
#(posedge Clk); #1;
$top.u_foo.u_bar.u_cell.Glitch = 1'b1;
...
end
The above code snippet will inject one cycle of "Glitch".
As an alternative: a more traditional way of injecting errors is to use the "force" statement in the testbench to override a driven in a device under test.

clock pulse generator for a PLC

I am working with PLCs trying to design a water tank. On one section of the design I am asked to create a clock pulse generator. I am currently trying to do this using ladder diagrams.
I believe I have the logic correct just cant seem to put it together. I want a counter to count the clock pulses that I generate, then I store these pulese in a data memory to ensure the count is retained if the system is switched off and on.
question is how do I design this clock pulse generator.
Kind regards
There are a few different ways to create a pulse generator (or commonly known in the plc world as a BLINK timer). As a matter of fact many plc programming softwares have this function block built in to their function block libraries. But if they don't or you just want to make your own you can do something like this
VAR
ton1: TON;
ton2: TON;
StartPulse: BOOL;
startPulseTrig: R_TRIG;
LatchPulseInitial: BOOL;
PulseOutput: BOOL;
Timer1Done: BOOL;
Timer2Done: BOOL;
PulseWidth:TIME:=t#500ms;
END_VAR
If you would like to count the number of pulses and store this value to a variable you can use a simple CTU (counter up) block available in all plc languages.
Review of functionality
The StartPulse variable can be anything you want that will start the counter. In my case I just used an internal bool variable that I turned on. If you want this timer to start automatically when the plc starts then just initialize this variable to true. Because StartPulse only works on the rising edge of the signal the LatchPulseInitial coil will only ever be set once.
When the LatchPulseInitial variable goes true this will start ton1 a Timer On Delay (TON) function block. This will delay the output of the block from turning on for the time of PT (in my case I have 500ms).
After 500ms has expired the ton1 outputs will turn on. this will turn on the Timer1Done variable and turn off the Timer2Done and LatchPulseInitial. Now that LatchPulseInitial has been turned off it will never interfere with the program again since it can only be turned on by the rising edge of StartPulse. Note: once the block has reached PT the outputs will stay on until the input to the block is removed.
Since Timer1Done is now on ton2 will start counting until PT is reached. Once PT is reached the outputs for that block will turn on. This will reset Timer1Done and set Timer2Done This will start ton1 again and thus starting the whole process over.
For the PulseOutput, which is the actual pulse output you are looking for, I have this being set to true when Timer2Done is true. This is because when this variable is true it is the high state of the pulse generator. When Timer1Done is true it is the low state of the pulse generator.
When the PulseOutput goes true it will trigger the input on the CTU which will increment the count of the variable in CV (current value) by 1.
If you are going to be using this logic in numerous places in your program or you plan on reusing it in the future I would make this into its own function block so you won't have to repeat this logic everytime you want to make this type of timer.
Once I had to create a BLINK FB. It is written in Structured Text. But it is suitable to use in a ladder logic program and IN/OUT Variables are named like TON style. The Blink starts with Q = TRUE. If you want to start with FALSE just invert Q and switch the Times!
FUNCTION_BLOCK BLINK
VAR_INPUT
IN : BOOL;
PT_ON : TIME;
PT_OFF : TIME;
END_VAR
VAR_OUTPUT
Q : BOOL;
ET : TIME;
END_VAR
VAR
rtIN : R_TRIG;
tonBlink : TON;
END_VAR
rtIN(CLK := IN);
IF tonBlink.Q OR rtIN.Q THEN
(*Toggle Output*)
Q := NOT Q;
(*Timer Reset call, important to call timer twice in same cycle for correct Blink Time*)
tonBlink(IN:= FALSE);
(*Set corresponding Time*)
IF Q THEN
tonBlink.PT := PT_ON;
ELSE
tonBlink.PT := PT_OFF;
END_IF
END_IF
(*Timer Run call*)
tonBlink(IN:= IN);
IF IN THEN
ET := tonBlink.ET;
ELSE
ET := T#0S;
Q := FALSE;
END_IF
In my opinion, this is the most straightforward way to do it, using 1 timer, up counter and modulo operator:
Blink function in ladder
Also note, if your PLC doesnt have modulo, then multiply by -1 each time.

verilog assigning to same variable not working

I am having a strange problem with Verilog HDL.
I found in my code that if I multiply a variable by two, but then
assign that value to the same variable, it gets all messed up.
Sometimes, the simv program even crashes. I originally needed to do this,
because I had a for loop for shifting or rotating a certain amount. But,
then I found that not only shifting the same variable did not work, but
also, addition, subtraction, multiplication, or division does not work either.
So in my code example, if you set a to 16'b0001_0000_1010_0101, and b to 3,
then you get an output of 16'b0000_0000_0000_0000. Just note that I am ignoring b for now... I should get 16'b0010_0001_0100_1010... but something is going wrong.
So, this is my code file test.v:
// ALU module.
module test(in1, in2, out1);
input [15:0] in1;
input [15:0] in2;
output reg [15:0] out1;
// Variables for shifting right and for rotating left or right.
reg [15:0] shiftedValue;
always#(in1, in2)
begin
assign shiftedValue = in1;
assign shiftedValue = shiftedValue * 2;
assign out1 = shiftedValue;
// This display value is correct!
// but it's still wrong in the test bench.
$display("out1 == %b", out1);
end
endmodule
module testStim;
reg [15:0] a;
reg [15:0] b;
wire [15:0] c;
// create ALU instance.
test myTest(a, b, c);
initial
begin
a = 16'b0001_0000_1010_0101;
b = 3;
#10
$display("op1In == %b, op1Out == %b", a, c);
$finish;
end
endmodule
This is the output after running simv (I stripped out the erroneous garbage...):
out1 == 0010000101001010
op1In == 0001000010100101, op1Out == 0000000000000000
Thanks,
Erik W.
You have done what is called as procedural continuous assignment.
The difference between regular continuous assignments and procedural continuous assignments is this:
Continuous assignment can only drive wire/net data type. Procedural assignment can drive only reg data type and not nets.
Continuous assignment should appear outside procedural blocks(always, initial etc), while latter must be inside procedural blocks.
Continuous assignment executes each time the right hand side expression changes. Procedural assignment depends on sensitivity list of always block.
As soon as the always block ends, the effect of assign statement is removed. You must add deassign statement to retain the values (which I think is not the real intent) or Just remove assign statement from the code. As shown below:
shiftedValue = in1;
shiftedValue = shiftedValue * 2;
out1 = shiftedValue;
More information about assign, deassign is available at this, this and this links.

Output skew when using clocking blocks

I am using a clocking block in my interface for signal aliasing. I want to concatenate some of the bits together to form a bus, and then drive this bus from my driver. So, for example:
interface bus_intf (clk);
input logic clk;
logic[1:0] x_lsb;
logic[1:0] x_msb;
clocking driver_bus #(posedge clk)
default input #1step output #0;
output x_bus = {x_msb, x_lsb};
endclocking
endinterface
Now the problem with this is, in one of my assertions, I need to read bus_intf.driver_bus.x_bus. As stated in the SV manual, an output variable from a clocking block should not be read by the testbench, and if it is, then simulator spits out an error (or warning in my case).
So I modified the interface:
interface bus_intf (clk);
input logic clk;
logic[1:0] x_lsb;
logic[1:0] x_msb;
clocking driver_bus #(posedge clk)
default input #1step output #0;
inout x_bus = {x_msb, x_lsb};
endclocking
endinterface
The problem now is, in my waveform I see two signals being created - x_bus and x_bus__o. I understand why Questasim did this - it is to separate the inout declaration so I can view both versions.
However, the problem now is all my clocking drive is delayed by one clock cycle! so x_bus__o which is connected to the DUT is one clock cycle later than x_bus. This is inspite of me explicitly stating that output skew is #0.
Any idea why this happens? Am I doing something wrong or have I misunderstood?
I've put your code on EDAPlayground and tried it out. It seems to be working as expected. Here's my test harness:
module top;
bit clk;
always #1 clk = ~clk;
bus_intf busif(clk);
initial begin
#busif.driver_bus;
$display("time = ", $time);
busif.driver_bus.x_bus <= 'hf;
repeat (2)
#(negedge clk);
$display("time = ", $time);
busif.driver_bus.x_bus <= 'ha;
#100;
$finish();
end
always #(busif.x_lsb)
$display("time = ", $time, " x_lsb = ", busif.x_lsb);
always #(busif.x_msb)
$display("time = ", $time, " x_msb = ", busif.x_msb);
endmodule
The link is here if you want to try it online: http://www.edaplayground.com/x/Utf
If I drive x_bus at a posedge, then the value will be written immediately, as would be expected due to the #0 output delay. If I drive x_bus at a negedge (or at any other time aside from a posedge), then it will wait until the next posedge to drive the value. I see this behavior regardless of whether x_bus is declared as output or inout.
Check to see when you are scheduling your writes; this might be the reason you see some delays on your waves.
When you have bidirectional flow through a clocking block, the signal from the verification to the hardware and back has to go through two virtual D-FFs. So the original observation is correct. The input of 1-step is one D-FF to the design; then the return is one more D-FF back appearing 0ns (i.e., just after the clock). Clocking blocks are not useful in the situation of a signal that requires a single-cycle turn-around, and for that reason, you avoid them if that is a requirement. For most designs, it is simply not necessary. Monitors will observe the signals with a pipeline delay of one cycle, which is generally not a problem.