I am trying to encode conditional behavior for Verilog statements in a generate loop. For example, the code below returns an error.
module <something> (out);
parameter [4:0] someParam = 0;
output [5:0] out;
genvar l, m;
for(l=0; l<5; l=l+1) begin:STAGE_1
m = 0;
if(someParam[l] < 2)
m = l+2;
else begin
m = l-2;
end
if (m>16) assign out[l] = 1'b0;
else assign out[l] = 1'b1;
end
endmodule
The problem is that the variable m is not a constant and the code errors out. Is there any way I can use compile time variable inside a generate statement which would allow some functionality like the variable m above?
Thanks.
I didnt understand what you intended to calculate due to some errors in your code.
In general, for you to use a parameter in a statement you can use an always block with a if statement as following:
module <something> (out);
parameter [4:0] someParam = 0;
output out; // in this case out is only one bit. it can be more of course.
integer l,m; // no need for genver when not using generate
always (*) begin
m = 0;
for (l=0; l<5; l=l+1) begin:STAGE_1
if (someParam[l] == 1'b1) // nothing good comes for checking if a bit is less then 2
m = m+1; // just counting bits in someParam. doing +-2 does not make sense.
end
if (m >= 3)
out = 1'b1;
else
out = 1'b0;
end
The above is a majority function.
Good luck
Related
I am new one in Verilog and I need to write a simple test bench, but I get an error and I cannot understand why it is
Here is my code
`timescale 1 ns / 1 ns
module test_bench_lb2;
reg [12:0] in_lines_tb;
wire [4:0] out_lines_tb;
wire error_tb;
localparam PERIOD = 10;
initial
begin
genvar i;
for(i = 0; i <= 8000; i = i + 1)
begin
in_lines_tb = i;
#PERIOD;
end
#(PERIOD*20) $stop;
end
initial
begin
$monitor("time = %time in_lines = %b out_lines = %b error = %b",
$time, in_lines_tb, out_lines_tb, error_tb);
end
DESHIFRATOR inst1(.in_lines(in_lines_tb), .out_lines(out_lines_tb), .error(error_tb));
endmodule
This
genvar i;
should be this
integer i;
A genvar is a special kind of variable used in a construct called a generate loop. You code uses an ordinary for loop.
When implementing the below code in xilinx vivado syntax errors are occurring when calling the sub modules
FA5,FD2,fc2,com1,com2,com3
except for the modules FA4,FD1 and fc1.
All the sub modules are tested and working fine. How to adjust the MAU modules to call the given modules properly?
module MAU(clk,reset,Nmax,error_tol,omega,error,result);
input clk,reset;
input Nmax,error_tol,omega;
output error,result;
wire[15:0] Nmax,error_tol,omega,result;
reg[15:0] a,b,aplusb,c,zero,n;
wire[15:0] fc1,fc2,fc_out;
wire FA4,FA5,FD1,FD2,com1,com2,com3;
reg [15:0] bigNum1,bigNum2,bigNum3;
integer error;
always#*
begin
a<=16'b0000000000000000; //initial value of a
b<=16'b0111110000000000; //initial value of b
n<=16'b0111110000000000; //initial value of n
zero<=16'b0000000000000000;//loading the value of zero
end
begin //finding the initial C and fc_out
float_adder FA4(.num1(a),.num2(b),.result(aplusb)); //finding initial a+b
float_divider FD1(.num(aplusb),.result(c)); //finding initial c
fc_value fc1(.omega(omega),.x(c),.fc_out(fc_out)); //find iniitial fc_out
end
always#*
begin
while ((bigNum1[15:0]==fc_out[15:0]) |(bigNum2[15:0]==Nmax[15:0])) //consider two conditions
n <= n + 1'b1;
comparator com3(.num1(fc_out),.num2(zero),.bigNum(bigNum3)); //compare and output big value from fc_out and zero
if(fc_out[15:0]==bigNum3[15:0])//considering the condition
begin
assign a=c;
end
else
begin
assign b=c;
end
begin //updating C and fc_out
float_adder FA5(.num1(a),.num2(b),.result(aplusb)); //updating a+b
float_divider FD2(.num(aplusb),.result(c)); //updating c
fc_value fc2(.omega(omega),.x(c),.fc_out(fc_out)); //updating fc_out
comparator com1(.num1(fc_out),.num2(error_tol),.bigNum(bigNum1)); //compare and output big value from fc_out & error_tol
comparator com2(.num1(Nmax),.num2(n),.bigNum(bigNum2)); //compare and output big value from Nmax and n
end
end
always#*
if (bigNum1 != fc_out)
begin
assign error = 0 ;
end
else
begin
assign error = 1 ;
end
assign result = c;
endmodule
I think you should use wires, not registers in calling module outputs;
call it outside of always block;
don't use same wire in two output ports of called modules;
use clk in design of always blocks;
module accumulator (
input [7:0] A ,
input reset,
input clk,
output reg carryout,
output reg overflow,
output reg [8:0] S,
output reg HEX0,
output reg HEX1,
output reg HEX2,
output reg HEX3
);
reg signA;
reg signS;
reg [7:0] magA;
reg [7:0] magS;
reg Alarger;
initial begin
S = 9'b000000000;
end
always_ff # (posedge clk, posedge reset) begin
if (reset) begin
S = 9'b000000000;
end
else begin
begin
signA <= A[7]; //Is A negative or positive
signS <= S[7];
S <= A + S;
end
if (signA == 1) begin //A is negative so magnitude is of 2s compliment
magA <= (~A[7:0] + 1'b1);
end
else begin
magA <= A;
end
if (signS == 1) begin //sum is negative so magnitude is of 2s compliment
magS <= (~S[7:0] + 1'b1);
end
else begin
magS <= S;
end
if (magA > magS) begin
Alarger <= 1'b1; //Magnitude of A is larger than magnitude of sum
end
else begin
Alarger <= 1'b0;
end
if ((signA == 1) & (Alarger == 1) & (S[7] == 0)) begin
overflow <= 1'b1;
end
else begin
overflow <= 1'b0;
end
if ((signS == 1) & (Alarger == 0) & (S[7] == 0)) begin
overflow <= 1'b1;
end
else begin
overflow <= 1'b0;
end
if ((signS == 1) & (signA == 1) & (S[7] == 0)) begin
overflow <= 1'b1;
end
else begin
overflow <= 1'b0;
end
if ((signS == 0) & (signA == 0) & (S[7] == 1)) begin
overflow <= 1'b1;
end
else begin
overflow <= 1'b0;
end
if (S[8] == 1) begin //carryout occurred
carryout <= 1'b1;
overflow <= 1'b0;
S <= 9'b000000000; //sum no longer valid
end
else begin
carryout <= 1'b0;
end
display_hex h1 //display of A
(
.bin (magA),
.hexl (HEX2),
.hexh (HEX3)
);
display_hex h2 //display of sum
(
.bin (S[7:0]),
.hexl (HEX0),
.hexh (HEX1)
);
end
end
endmodule
I am trying to make an accumulator that adds A (8 digit binary value that can be signed or unsigned) repeatedly to the sum. Once the sum is computed, then sum and A should display the value on 4 hex display LEDs (2 LEDs for A and 2 LEDs for sum). However, I am having a hard time getting it to compile. I have searched the error code and it seems like a general error for a syntax error and can have several meanings.
The error is the result of these two lines:
display_hex h1 //display of A
(
.bin (magA),
.hexl (HEX2),
.hexh (HEX3)
);
display_hex h2 //display of sum
(
.bin (S[7:0]),
.hexl (HEX0),
.hexh (HEX1)
);
Here, it appears you have a module named display_hex which converts an 8-bit value into the needed digits for a seven segment display. You are trying to use the module as if it were a function and modules are very much NOT functions. Modules in Verilog (or SystemVerilog as you are using, but the difference is really token at this point) can be though of as a group of hardware that takes in some inputs and spits out some outputs; and its important to note that they are static things. They either exist in the design or they do not; just like using ICs on a breadboard. The top module is the breadboard and the modules you declare under that module are components you are plugging into the board. The inputs and outputs are the various connections (pins) you must wire up to make everything work.
That said, always blocks (like the always_ff you are using) form a way of describing the logic and registers inside modules. Thus, you do thinks like assign logic/reg variables inside them to describe how the hardware behaves. If you look at your logic, you'll notice that the module declarations are dependent on reset; ie if reset is asserted, these modules wont exist, which doesnt make any sense. Electrical signals don't make entire ICs in a circuit disappear! Thus, you need to pull your module declaration out of your logical description of your acculumator, like so:
module accumulator (
...
);
...
display_hex h1 //display of A
(
.bin (magA),
.hexl (HEX2),
.hexh (HEX3)
);
display_hex h2 //display of sum
(
.bin (S[7:0]),
.hexl (HEX0),
.hexh (HEX1)
);
...
always_ff #(posedge clk, posedge reset) begin
// Your accumulator logic here
...
end
endmodule
Notice that the module declarations for the display_hex modules are stand alone, as I am declaring these modules exist, not dependence on anything!
However, there are a number of issues with your design besides that:
As you are using SystemVerilog constructs (always_ff), you should declare all of your variables type logic, not reg or left blank (ie, input clk should be input logic clk, reg signA should be logic signA). The logic type just makes everything easier, so use it :)
In your always_ff block, you do reset correctly except that the assignment should really be NBA (use S <= 9'b0;, not S = 9'b0; in the if (reset))
You use NBA inside your always_ff, which is correct, however, it appears you need to use these values right away in the following logic. This will not work as you expect, or at least it will not act within the same clock cycle. To fix this, youll need to decide what should be a register and what should just be values resulting from intermediate logic, then create a separate always_comb for the intermediate values.
I am making the assumption that the HEX variables are meant for seven segment displays, so they should probably declared at least [6:0] HEXn
I was not able to reproduce the exact error, but moving the instantiations of display_hex outside always_ff resolves the main issue:
module accumulator
(
/* ... */
);
// ...
always_ff # (posedge clk, posedge reset) begin
/* ... */
end
display_hex h1 (
/* ... */
);
display_hex h2 (
/* ... */
);
endmodule
Another thing: The code drives variable S from initial as well as always. This creates multiple drivers and the code will not compile. To fix this, remove the initial completely, you don't need it since S will be set to 0 when reset is asserted.
OR
You can move all the logic into the initial block; it'd look something like this (but this, most probably, won't synthesize):
initial begin
S = 0;
forever begin
wait #(posedge clock);
// Do stuff here ..
end
end
I seem to have some issues anytime I try anything with I/O for verilog. Modelsim either throws function not supported for certain functions or does nothing at all. I simply need to read a file character by character and send each bit through the port. Can anyone assist
module readFile(clk,reset,dEnable,dataOut,done);
parameter size = 4;
//to Comply with S-block rules which is a 4x4 array will multiply by
// size so row is the number of size bits wide
parameter bits = 8*size;
input clk,reset,dEnable;
output dataOut,done;
wire [1:0] dEnable;
reg dataOut,done;
reg [7:0] addr;
integer file;
reg [31:0] c;
reg eof;
always#(posedge clk)
begin
if(file == 0 && dEnable == 2'b10)begin
file = $fopen("test.kyle");
end
end
always#(posedge clk) begin
if(addr>=32 || done==1'b1)begin
c <= $fgetc(file);
// c <= $getc();
eof <= $feof(file);
addr <= 0;
end
end
always#(posedge clk)
begin
if(dEnable == 2'b10)begin
if($feof(file))
done <= 1'b1;
else
addr <= addr+1;
end
end
//done this way because blocking statements should not really be used
always#(addr)
begin:Access_Data
if(reset == 1'b0) begin
dataOut <= 1'bx;
file <= 0;
end
else if(addr<32)
dataOut <= c[31-addr];
end
endmodule
I would suggest reading the entire file at one time into an array, and then iterate over the array to output the values.
Here is a snippet of how to read bytes from a file into a SystemVerilog queue. If you need to stick to plain old Verilog you can do the same thing with a regular array.
reg [8:0] c;
byte q[$];
int i;
// Read file a char at a time
file = $fopen("filename", "r");
c = $fgetc(file);
while (c != 'h1ff) begin
q.push_back(c);
$display("Got char [%0d] 0x%0h", i++, c);
c = $fgetc(file);
end
Note that c is defined as a 9-bit reg. The reason for is that $fgetc will return -1 when it reaches the end of the file. In order to differentiate between EOF and a valid 0xFF you need this extra bit.
I'm not familiar with $feof and don't see it in the Verilog 2001 spec, so that may be something specific to Modelsim. Or it could be the source of the "function not supported."
I have a simple verilog program that increments a 32 bit counter, converts the number to an ASCII string using $sformat and then pushes the string to the host machine 1 byte at a time using an FTDI FT245RL.
Unfortunately Xilinx XST keeps optimizing away the string register vector. I've tried mucking around with various initialization and access routines with no success. I can't seem to turn off optimization, and all of the examples I find online differ very little from my initialization routines. What am I doing wrong?
module counter(CK12, TXE_, WR, RD_, LED, USBD);
input CK12;
input TXE_;
output WR;
output RD_;
output [7:0] LED;
inout [7:0] USBD;
reg [31:0] count = 0;
reg [7:0] k;
reg wrf = 0;
reg rd = 1;
reg [7:0] lbyte = 8'b00000000;
reg td = 1;
parameter MEM_SIZE = 88;
parameter STR_SIZE = 11;
reg [MEM_SIZE - 1:0] str;
reg [7:0] strpos = 8'b00000000;
initial
begin
for (k = 0; k < MEM_SIZE; k = k + 1)
begin
str[k] = 0;
end
end
always #(posedge CK12)
begin
if (TXE_ == 0 && wrf == 1)
begin
count = count + 1;
wrf = 0;
end
else if (wrf == 0) // If we've already lowered the strobe, latch the data
begin
if(td)
begin
$sformat(str, "%0000000000d\n", count);
strpos = 0;
td = 0;
end
str = str << 8;
wrf = 1;
strpos = strpos + 1;
if(strpos == STR_SIZE)
td = 1;
end
end
assign RD_ = rd;
assign WR = wrf;
assign USBD = str[87:80];
assign LED = count[31:24];
endmodule
Loading device for application
Rf_Device from file '3s100e.nph' in
environment /opt/Xilinx/10.1/ISE.
WARNING:Xst:1293 - FF/Latch str_0
has a constant value of 0 in block
. This FF/Latch will be
trimmed during the optimization
process.
WARNING:Xst:1896 - Due to other
FF/Latch trimming, FF/Latch str_1
has a constant value of 0 in block
. This FF/Latch will be
trimmed during the optimization
process.
WARNING:Xst:1896 - Due to other
FF/Latch trimming, FF/Latch str_2
has a constant value of 0 in block
. This FF/Latch will be
trimmed during the optimization
process.
The $sformat task is unlikely to be synthesisable - consider what hardware the compiler would need to produce to implement this function! This means your 'str' register never gets updated, so the compiler thinks it can optimize it away. Consider a BCD counter, and maybe a lookup table to convert the BCD codes to ASCII codes.
AFAIK 'initial' blocks are not synthesisable. To initialize flops, use a reset signal. Memories need a 'for' loop like you have, but which triggers only after reset.