Optimization of continuous assignment by mixing combinational and behavioral logics? - optimization

I am trying to wrap my head around a mix of combinational and behavioral logic. I've got small FPGA with 4 LEDs and a 66 MHz clock input. The idea was to make two of them glowing (one rising, one falling) and another two blinking. So I came up with the following code:
module ledflash(input wire CLK,
input wire USER_RESET,
output wire LED[3:0]);
reg [26:0] cnt;
reg [4:0] pwm;
wire led_enable = ~USER_RESET;
always #(posedge CLK)
begin
if (led_enable)
begin
cnt <= cnt + 1;
pwm <= pwm[3:0] + (cnt[26] ? cnt[25:22] : ~cnt[25:22]);
end
else
begin
cnt <= 0;
pwm <= 0;
end
end
assign LED[0] = led_enable ? (cnt[26] ? pwm[4] : ~pwm[4]) : 0;
assign LED[1] = led_enable ? (cnt[26] ? ~pwm[4] : pwm[4]) : 0;
assign LED[2] = led_enable ? cnt[25] : 0;
assign LED[3] = led_enable ? ~cnt[25] : 0;
endmodule
I did not want to use a vendor specific DCM, and so simple bit adders with 66MHz clock works out the magic. Perhaps the whole design is wrong in a first place (for instance, I could have used two clock dividers and simply flip a bit of two registers to achieve (almost) the same thing), but I ran into this situation which made me wondering...
From a regular software developer's point of view, there are some parts in continuous assignments that seem redundant. For example, an extra register can be used and so it would seem that less work is performed. For instance:
module ledglow(input wire CLK,
input wire USER_RESET,
output wire LED[3:0]);
reg [26:0] cnt;
reg [4:0] pwm;
reg led_pair1;
reg led_pair2;
wire led_enable = ~USER_RESET;
always #(posedge CLK)
begin
if (led_enable)
begin
cnt <= cnt + 1;
pwm <= pwm[3:0] + (cnt[26] ? cnt[25:22] : ~cnt[25:22]);
end
else
begin
cnt <= 0;
pwm <= 0;
end
led_pair1 <= cnt[26] ? pwm[4] : ~pwm[4];
led_pair2 <= cnt[25];
end
assign LED[0] = led_enable ? led_pair1 : 0;
assign LED[1] = led_enable ? ~led_pair1 : 0;
assign LED[2] = led_enable ? led_pair2 : 0;
assign LED[3] = led_enable ? ~led_pair2: 0;
endmodule
I was trying to dig into synthesizer report differences for two approaches above and look at HDL schematics, but it way too complex for such an inexperienced guy like me.
No doubt synthesis tool optimizes the combinational logic very well, but assuming the the right hand side expressions are very complicated to be one-liners etc, is there a way to say something like this?
if (some_reg_var) begin
assign net0 = 1;
assign net1 = 0;
end
else
begin
assign net0 = 0;
assign net1 = 1;
end
Or does it even make sense to do so? If not, does it make sense to introduce registers in such cases to simplify the behavioral part? I am sure there are some rules or thumb at least. Any help is appreciated.

Your question is a bit verbose, but I think I understand what you're getting at (correct me if I'm wrong).
You wish to know if there is a way to break up long assign statements to use if/else logic, similar to regs in an always block?
Verilog always seemed slightly funny to me in this way, but just because you declare something a 'reg' datatype does not mean that it gets synthesized to a register. It only actually creates a register if there is some state to store. Having said that, the following two statements should synthesize to exactly the same thing:
Case 1:
wire a;
wire b;
assign a = b ? 0 : 1;
Case 2:
reg a;
wire b;
always #(b)
if(b)
a <= 0;
else
a <= 1;
Both of these should create the exact same logic (simply, an inverter with a = !b). Even in the second case where you have declared a reg, it doesn't actually instance a register, because there's nothing to remember (all of the inputs are in the sensitivity list).
Because of this, you are free to write complex if/else logic to simplify your code, and this doesn't mean you're paying a penalty of synthesizing extra registers. So feel free to write it which ever way is most comfortable for you. (If you do use an always block, make sure to have an assignment for all possible cases, or you will infer a latch which you probably don't want).

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.

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.

Verilog module for a smoke detector and a buzzer

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

Can SystemVerilog represent a flip-flop with asynchronous set and reset without adding unsynthesizable code?

I'm coming from a Verilog-95 background, and I'm trying to figure out what Verilog-95 hoops I don't have to jump through anymore.
The obvious way to write a flip flop with async set and reset in Verilog-95 is:
always #(posedge clk or negedge resetb or negedge setb) begin
if (!resetb) q <= 0;
else if (!setb) q <= 1;
else q <= d;
end
This works in synthesis. But, this doesn't work in simulation if we ever assert both resetb and setb, and then de-assert resetb before de-asserting setb, since there's no posedge trigger for either of those signals. We need to add the following (which varies depending on your synthesis tool), to get simulation to match synthesis:
// synopsys translate_off
always #(resetb or setb)
if (resetb && !setb) force q = 1;
else release q;
// synopsys translate_on
Is there a SystemVerilog construct that will let you do this without this extra junk? Better yet, is there a straightforward way to do it in Verilog-95?
Flip-flops with multiple asynchronous controls are best avoided. The timing checks necessary to ensure they function properly are complex and easy to mess up. If you really need to use them, then it's probably best to instantiate them by hand where needed. If you let your synthesis tool infer them, it may use them in places you don't intend, which increases the risk that the timing checks don't get done properly.
One final aside, there is a similar simulation-synthesis mismatch issue with all asynchronous flops, if the active edge of reset is at time zero and is simulated before the flop is initialized to x, and the clock isn't running in reset. I believe some simulators have special cases to ensure the logic is not initialized in this order.
That said, I had luck moving the priority logic outside the sequential always block. Note I'm using active-high signals for simplicity.
assign s_int = s && !c;
always #(posedge clk or posedge s_int or posedge c) begin
if (c)
q <= 1'b0;
else if (s_int)
q <= 1'b1;
else
q <= d;
end
This is something I wish SystemVerilog had improved. If you want to allow both being low at the same time, then stick with the current method.
The other option is to create a design rule stating the asynchronous signals can not be active at the same time and enforce the rule with an assertion. Assertions are suppose to be ignored by synthesizers, so translate_off/on should not be be necessary.
Here is an example using an inline assertion:
always_ff #(posedge clk, negedge resetb, negedge setb) begin : dff_asyncRbSb
if (!resetb) q <= 0;
else if (!setb) q <= 1;
else q <= d;
asrt_setrst : assert(resetb||setb)
else $error("resetb and setb can not be low at the same time.");
end : dff_asyncRbSb
I don't know any SV, so this isn't an answer, but the issue here is that
Verilog (and, I think, SV) event expressions are basically broken. The problem
is that, when you have multiple conditions in an event expression:
event_expression ::=
expression
| hierarchical_identifier
| posedge expression
| negedge expression
| event_expression or event_expression
| event_expression , event_expression
then there's no bullet-proof way to determine which expression caused the
event, since the only thing you can do is to check the current state of the
expression. So, if you've got #(posedge clk, posedge rst), for example, you
look at the current levels of clk and rst and hope this is sufficient to do
the job. In general, it isn't, but your example is the only practical case (I
think) that causes a problem.
VHDL handles this by having signal attributes, which let you determine whether
a signal has caused an event. In VHDL, you get an event when any signal in
your sensitivity list changes, and you then check their 'event attribute to
determine whether they fired the process. No confusion, no posedge or negedge,
and it all works.
I've just had a quick look at the SV LRM, and SV attributes appear to be the
same as Verilog attributes, so I think you're out of luck.
with no edge defined, the assertion and de-assertion of reset and set signals should be able to trigger this code in simulation.
always_ff should be able to create a flop at synthesis.
Below code is compilation clean using synopsys VCS tool.
always_ff #(posedge clk, resetb, setb) begin
if (!resetb) q <= 0;
else if (!setb) q <= 1;
else q <= d;
end
Try this:
always_ff #(posedge clk or negedge resetb or negedge setb)
systemverilog uses always_ff for clock triggered logic and always_comb for combo logic

Specifying variable range in Verilog using for loop

I am trying to write this code:
for (i = 0; i <= CONST - 1'b1; i = i + 1'b1)
begin : loop_inst
if (i < 3)
begin
if (changed[i] & !done_q[i])
begin
writedata[3-i] = en[i];
writedata[2-i:0] = readdata[2-i:0];
writedata[15:4-i] = readdata[15:4-i];
end
end
else
...
Basically, the location of the bit I am trying to write to (en) changes depending on which address I am talking to, depending on i. This code is not synthesizable because i is not a constant.
Is there any other workaround to this? The only workaround I know is writing out those three statements CONST times. I am hoping I DON'T have to do that in the end. Is there any other solution?
It looks like you're trying to copy readdata to writedata all the time, but fill in the LSBs with en if certain special case conditions are met. I'm also going to assume that the for loop you have is in an always block, and that you're intending to build combo logic.
The for loop as you've it written doesn't make much sense to me from a hardware perspective. A for loop is used for building arrays of logic, and as you've
written it you'll have at least 3 logic cones trying to set values on the entire writedata bus. (If it generates anything at all, it'll be some weird priority structure).
That said, it's probably the range selects that your compiler is complaining about, ie the writedata[2-i:0] rather than the writedata[3-i] = en[i]; (anything with : in the part select). If you want to do something along those lines, you can use 'indexed part selects' ( +: or -:) but there are better solutions in this case.
I'd rewrite it as follows - assuming I've assumed correctly :)
always #( /*whatever*/ ) begin
// default assignment
writedata = readdata;
// overwrite some bits in writedata for special cases
for(i=0; i<3; i++) begin
if( changed[i] & !done_q[i] )
writedata[3-i] = en[i];
end
end
In this code, I'm setting writedata to readdata, and then tweaking the resulting value of writedata if the special cases are in play. The for loop is building 3 logic cones, one for each of the bits in writedata[3:1]. I'd double-check if the bit mapping is what you intend -ie, mapping en[2:0] on to writedata[1:3].