How to test primality in Verilog? - verilog

I have the Verilog code shown below, and if I try to compile it I get an error message. The point is that I'm trying to manipulate an input, which as long as I know cannot be done in Verilog. The point is that I need check the following condition in Verilog:
static int prime(unsigned long long n)
{
unsigned long long val = 1;
unsigned long long divisor = 5;
if (n == 2 || n == 3)
return 1;
if (n < 2 || n%2 == 0 || n%3 == 0)
return 0;
for ( ; divisor<=n/divisor; val++, divisor=6*val-1)
{
if (n%divisor == 0 || n%(divisor+2) == 0)
return 0;
}
return 1;
}
At the moment I have the following code:
module prime(clk, rst, start, A, ready, P);
input clk, rst, start;
input [7:0] A;
output ready, P;
reg ready, P;
wire [7:0] divisor;
assign divisor = 5;
wire [7:0] val;
assign val = 1;
always # (posedge clk or posedge rst) begin
if (!rst) begin
P <= 0;
end
else if (start) begin
case (A)
0 : P <= 1;
1 : P <= 1;
2 : P <= 1;
3 : P <= 1;
endcase
if (A%2 == 0 && A != 2) begin
P <= 0;
end
else begin
for( ; divisor <= A/divisor; val=val+1, divisor=6*val-1) begin
if (A%divisor == 0 || A%(divisor+2) == 0) begin
P <= 0;
end
end
// need to set P to 1
end
end
end
endmodule
Please also note I need to test primes in the form of 6n+1 or 6n-1, and I also need to assume in my code that 0 and 1 are also primes.
If I try the above code I get an error message saying:
Enhanced FOR loop is not enabled for verilog
If anyone can help me solve the error and finish my logic in Verilog, I would be glad.

The Verilog BNF does not allow empty or compound statements in for(;;). Change the file to *.sv to compile it under SystemVerilog rules. Otherwise change your for loop statement to have simple statements
for( divisor =5; divisor <= A/divisor; divisor=6*val-1) begin
if (A%divisor == 0 || A%(divisor+2) == 0) begin
P <= 0;
end
val++;
end
Also, you can't make procedural assignments to wires. make them variables.

Related

Reduction or with stride

I'd like to make an or of some bits, but they are not on a contiguous array. See |ack[i-1:0][j] in the following example, where | is the bitwise reduction or.
module cb #(
parameter PORTS = 4
)(
input dest[PORTS][PORTS],
output ack[PORTS][PORTS]
);
generate
genvar i, j, used[PORTS];
for ( i = 0; i < PORTS; i++ )
begin
for ( j = 0; j < PORTS; j++)
begin
assign ack[i][j] = dest[i][j] && ! (|ack[i-1:0][j]);
end
end
endgenerate
endmodule
In this concrete case, what I really want is for the ack[i][j] bit to be 1 for the first dest[i][j] that is 1 in each "column".
Obviously, this gives a "range not allowed in a prefix" error. How could I implement this behaviour?
You can use an auxiliary signal, I guess this is what you tried to do with the genvar used[PORTS], genvars are processed during compilation time so they can't hold values that depends on the inputs, this is why we must use a signal.
used[i][j] is will iteratively compute ack[0][j] | ... | ack[i-1][j]
module cb #(
parameter PORTS = 4
)(
input dest[PORTS][PORTS],
output ack[PORTS][PORTS]
);
logic used[PORTS][PORTS];
generate
genvar i, j;
for ( i = 0; i < PORTS; i++ )
begin
for ( j = 0; j < PORTS; j++)
begin
assign used[i][j] = i == 0 ? 1'b0: ack[i][j] | used[i-1][j];
assign ack[i][j] = dest[i][j] && ! used[i-1][j];
end
end
endgenerate
endmodule
Generate block just cause creation of 16 separate assignments in your case. they do not make much sense here. There is a simpler solution with a single procedural block.
module cb #(
parameter PORTS = 4
)(
input dest[PORTS][PORTS],
output logic ack[PORTS][PORTS]
);
always #* begin
logic flag;
flag = 0;
for ( int i = 0; i < PORTS; i++ ) begin
for ( int j = 0; j < PORTS; j++) begin
if (dest[i][j] == 1'b1)
flag = 1;
ack[i][j] = flag;
end
end
end
endmodule
You set flag when dest condition is right. It is persistent till the end of the block, setting value of ack. It works according to your description.
I ended up combining both answers to get the following code:
module cb #(
parameter PORTS = 4
)(
input dest[PORTS][PORTS],
output ack[PORTS][PORTS]
);
logic used[PORTS][PORTS];
always_comb begin
logic used[PORTS];
// First resetting to 0
for ( int j = 0; j < PORTS; j++ )
used[j] = 0;
for ( int i = 0; i < PORTS; i++ )
begin
for ( int j = 0; j < PORTS; j++)
begin
ack[i][j] = dest[i][j] && !used[j];
used[j] = used[j] | ack[i][j];
end
end
end
endmodule
This code takes into account that at most one port can be used “per column” (and not just one at all).

Verilog synthesis is giving me an error that I don't understand

I am getting this error when synthesizing my code, but I don't know what it means. It reads:
Error- net "Count[0] or a directly connected net is driven by more
than one source and not all drivers are three state.
It says the same errors for vectors count[0] - count[4] as well as for my load and k values. The code is my representation of an SPI Master. The SPI master has an instantiation of a shift register that is used to push out information.
module SPIMaster(output reg SCLK, CS, MOSI,
input EN, CLK, MISO,
input [7:0] m_data);
wire master_out;
reg [4:0] count;
wire [7:0] data_buff;
wire SCLK1;
reg master_in, c_sw, k, state, load;
shiftReg register_out (master_out, data_buff, load, (~SCLK), master_in, m_data);
assign SCLK1 = (~c_sw) | CLK;
always#(posedge CLK) begin
if(state) begin
if (k == 1) begin
state <= 0;
c_sw <= 0;
CS <= 1;
count <= 0;
k <= 0;
load <= 0;
end
else begin
state <= 1;
c_sw <= 1;
CS <= 0;
end
end
else begin
if (EN == 1) begin
state <= 1;
c_sw <= 1;
CS <= 0;
count <= 0;
k <= 0;
load <= 1;
end
else begin
state <= 0;
c_sw <= 0;
CS <= 1;
count <= 0;
k <= 0;
load <= 0;
end
end
end
always#(posedge SCLK1) begin
if (CS == 0) master_in <= MISO;
if (count == 7) begin
load <= 0;
end
else if (count == 15)begin
load <= 0;
end
else begin
load <= 1;
end
end
always#(negedge SCLK1) begin
if (count == 23) k <= 1;
else k <= 0;
if (CS == 0) begin
MOSI <= master_out;
count <= count + 1;
end
end
endmodule
Your code does not adhere to good synthesis coding practices because you assign to count from 2 different always blocks and those 2 blocks are triggered by different clock signals. You should make all assignments to count from the same always block.
The same is true of load and k.

Failed to use "generate" for memory

I'm using Verilog-2001 with Vivado 2015.4. There is my code:
parameter SHIFT = 16;
wire integrators_reset;
reg [INTEGRATOR_WIDTH - 1 : 0] sum_mem [SHIFT - 1 : 0];
reg [SHIFT - 1 : 0] full_mem;
wire [SHIFT - 1 : 0] equal;
genvar i;
generate
for(i = 0; i < SHIFT; i = i + 1) begin
always #(negedge equal[i]) begin
if(integrators_reset) begin
sum_mem[i] <= 0;
full_mem[i] <= 0;
end
else begin
if(sum_mem[i] == INTEGRATOR_MAX)
full_mem[i] <= 1;
else
sum_mem[i] <= sum_mem[i] + 1;
end
end
end
endgenerate
There is the error:
ERROR: [DRC 23-20] Rule violation (MDRV-1) Multiple Driver Nets- Net sum_mem[0][0] has multiple drivers
If i'm not using "generate" all is fine. For example:
always #(negedge equal[0]) begin
if(integrators_reset) begin
sum_mem[0] <= 0;
full_mem[0] <= 0;
end
else begin
if(sum_mem[0] == INTEGRATOR_MAX)
full_mem[0] <= 1;
else
sum_mem[0] <= sum_mem[0] + 1;
end
end
And there is not errors during implementation.
This seems like a tool limitation. You should be able to assign different fixed elements of an unpacked array from different always blocks. One workaround would be to move the declaration of sum_mem into the generate block.
for(I = 0; I < SHIFT; i = i + 1) begin : block_name
reg [INTEGRATOR_WIDTH - 1 : 0] sum_mem;
always #(negedge equal[I]) begin
if(integrators_reset) begin
sum_mem <= 0;
full_mem[i] <= 0;
end
else begin
if(sum_mem[i] == INTEGRATOR_MAX)
full_mem[i] <= 1;
else
sum_mem <= sum_mem + 1;
end
end
end
Now you have block_name[0].sum_mem, block_name[1].sum_mem, but you can not access block_name with a variable index.

Gate instantiation in if else statement in verilog

I am designing Signed comparator that uses the unisgned comparator module. i.e. if A and B are 4 bit vectors and
if A[3] ==1 and B[3]==0 then
Gout = 0, Eout = 0 and Lout = 1.
if A[3]==0 and B[3]==1 then
Gout = 1, Eout = 0 and Lout = 0;
else if both A[3] and B[3] are same then
the unisigned comparator module has to be instantiated.
How can I write this gate instantiation inside a if else statement?
module SCOMP(A,B,Great_in,Equal_in,Less_in,Great_out,Equal_out,Less_out);
input[3:0] A;
input[3:0] B;
input Great_in,Equal_in,Less_in;
output Great_out,Equal_out,Less_out;
reg[3:0] X;
reg[3:0] Y;
reg p,q,r;
wire x,y,z;
initial
begin
X = 0000& A[2:0];
Y = 0000& B[2:0];
end
COMP4 g1(X,Y,Gin,Ein,Lin,x,y,z);
always #(*)
begin
if ((A[3]==0)&& (B[3]==1))
begin
assign p = 1;
assign q = 0;
assign r =0;
end
else if ((A[3]== 1)&&(B[3]==0))
begin
assign p = 0;
assign q = 0;
assign r = 1;
end
else
begin
assign p = x;
assign q = y;
assign r = z;
end
end
assign Great_out = p;
assign Equal_out = q;
assign Less_out = r;
endmodule
Verilog is a Hardware Description Language. Hardware either exists or it doesn't. Instantiation of anything is like soldering a chip to a PCB. Instantiating something inside an if statement would be like designing a PCB where the chips can magically appear or disappear depending on some input to the PCB.
Your "unsigned comparator module" has to exist for all time - it has to be instantiated unconditionally. You then need to use your if statements to decide whether to use the outputs from this "unsigned comparator module" or to ignore them, eg:
// the instance of the "unsigned comparator module"
unsigned_comparator_module UCM ( ... .gout(ucm_gout), .eout(ucm_eout), .lout(ucm_lout) ... );
always #* begin
if (A[3] == 1 && B[3] == 0) begin
Gout = 0; Eout = 0; Lout = 1;
end else if (A[3] == 0 && B[3] == 1) begin
Gout = 1; Eout = 0; Lout = 0;
end else if (A[3] == B[3]) begin
Gout = ucm_gout; Eout = ucm_eout; Lout = ucm_lout;
end
end
the best way to do that inside the if condition write the comparator code where u want. for eaxample
else if both A[3] and B[3] are same then
the unisigned comparator module has to be written here.

How to check unknown logic in Verilog?

I'm checking primality of a number in a form of 6n+1 or 6n-1. I have the below code, but it doesn't seem to be generated correct result.
module prime(clk, rst, start, A, ready, P);
input clk, rst, start;
input [7:0] A;
output ready, P;
reg ready, P;
reg [7:0] divisor;
reg val;
always # (posedge clk or negedge rst) begin
if (!rst) begin
P <= 1'bx;
end
else if (start)
begin
case (A)
-1 : P <= 1;
0 : P <= 1;
1 : P <= 1;
2 : P <= 1;
3 : P <= 1;
5 : P <= 1;
endcase
if (A%2 == 0 && A != 2) begin
P <= 0;
ready <= 1;
end
else if(A > 6)
begin
for(divisor = 5; divisor <= A/divisor; divisor=divisor+6) begin
if (A%divisor == 0 || A%(divisor+2) == 0) begin
P <= 0;
end
end
if (P != 0 && P == 1'bx) begin // need to fix
P <= 1;
end
end
end
end
endmodule
The point is that this part doesn't seem to be working:
if (P != 0 && P == 1'bx)
How can I check whether a variable includes unknown logic, meaning x. Checking as the above
P == 1'bx
doesn't seem to be working.
You should rather use case equality operator (===), which tests 4-state logical equality, then logical equality operator (==).
For the == operator, the result is x, if either operand contains an x or a z.
For the === operator bits with x and z are included in the comparison.

Resources