How to determine the register with the greatest content - max

what is the best way to figure out which register contains the largest number?
reg [7:0] A;
reg [7:0] B;
reg [7:0] C;
reg [7:0] D;
reg [7:0] M;
always #(posedge CLK) begin
M <= max(A,B,C,D);
end

always #(posedge CLK)
begin
if(A > B && A > C && A > D)
begin
M <= A;
end
else if(B > A && B > C && B > D)
begin
M <= B;
end
else if(C > A && C > B && C > D)
begin
M <= C;
end
else if(D > A && D > B && D > C)
begin
M <= D;
end
//else
// there are two or more regs have the same value
end

Related

Multiple variables in Verilog case structure control expression

I am using case statement to write my Verilog logic. I wanted to know if we can AND multiple variables in the case's control expression.
reg a;
reg [5:0] b;
reg c;
case(a & b)
1'b0 & 6'd0: c <= 1'b1;
1'b1 & 6'd1: c <= 1'b0;
default: c <= 1'b0;
endcase
What you want is a concatenation {} not and &
case({a,b})
{1'b0 , 6'd0}: c <= 1'b1;
{1'b1 , 6'd1}: c <= 1'b0;
default: c <= 1'b0;
endcase

Sorting in verilog with one cycle

i was trying to sort 9 random numbers in verilog. I use bubble sort(nested for loops) algorithm but i have a challenge. I want to sort them in one clk cycle but it does not do what i want. It needs at least 9 cycle to sort them.
always #(posedge clk)
begin
if(m >= 68 && sort_valid == 0) begin
pool_sort[0] <= pool_buffer[66];
pool_sort[1] <= pool_buffer[65];
pool_sort[2] <= pool_buffer[64];
pool_sort[3] <= pool_buffer[34];
pool_sort[4] <= pool_buffer[33];
pool_sort[5] <= pool_buffer[32];
pool_sort[6] <= pool_buffer[2];
pool_sort[7] <= pool_buffer[1];
pool_sort[8] <= pool_buffer[0];
sort_valid <= 1;
end
if(sort_valid == 1) begin
for(k=0;k<8;k=k+1) begin
if(pool_sort[k] < pool_sort[k+1]) begin
pool_sort[k] <= pool_sort[k+1];
pool_sort[k+1] <= pool_sort[k];
end
end
if(sort_counter == 0) begin
sort_valid <= 0;
pool_out <= pool_sort[0];
end
end
end
always #(posedge clk)
begin
if(sort_valid == 1) begin
sort_counter <= sort_counter - 1;
end
if(sort_counter == 0) begin
sort_counter <= 8;
end
end
endmodule
This is my sorting algorithm so far.
Here's a paramaterizable 1-clock cycle sorter for Verilog (inspired from here but I parameterized the module, reduced the number of cycles, and did some cleanup).
It'll do what you want in simulation but it'll probably be pretty big and ugly when you synthesize it.
module sort #(
parameter NUM_VALS = 5,
parameter SIZE = 16
)( input wire clk,
input wire [NUM_VALS*SIZE-1:0] in,
output reg [NUM_VALS*SIZE-1:0] out
);
reg [NUM_VALS*SIZE-1:0] sorted_bus;
always #(posedge clk) begin
out <= sorted_bus;
end
integer i, j;
reg [SIZE-1:0] temp;
reg [SIZE-1:0] array [1:NUM_VALS];
always #* begin
for (i = 0; i < NUM_VALS; i = i + 1) begin
array[i+1] = in[i*SIZE +: SIZE];
end
for (i = NUM_VALS; i > 0; i = i - 1) begin
for (j = 1 ; j < i; j = j + 1) begin
if (array[j] < array[j + 1]) begin
temp = array[j];
array[j] = array[j + 1];
array[j + 1] = temp;
end
end
end
for (i = 0; i < NUM_VALS; i = i + 1) begin
sorted_bus[i*SIZE +: SIZE] = array[i+1];
end
end
endmodule
And a testbench:
module sort_tb;
reg clk;
reg [16-1:0] in1, in2, in3, in4, in5;
wire [16-1:0] out1, out2, out3, out4, out5;
sort #(.NUM_VALS(5), .SIZE(16)) dut (
.clk(clk),
.in ({in1, in2, in3, in4, in5}),
.out({out1, out2, out3, out4, out5})
);
always #(posedge clk) begin
in1 <= $random;
in2 <= $random;
in3 <= $random;
in4 <= $random;
in5 <= $random;
end
always #(posedge clk) begin
$display("In: %0d %0d %0d %0d %0d", in1, in2, in3, in4, in5);
$display("Out: %0d %0d %0d %0d %0d", out1, out2, out3, out4, out5);
end
initial begin
#100;
$finish;
end
always begin
clk = 1'b0; #5;
clk = 1'b1; #5;
end
endmodule
Think upfront if you will need to sort many rounds of 9 numbers.
You can do sorting within 1 cycle, but the top frequency could be significantly limited. But then, it doesn't really matter if you spent 1 clock cycle at low frequency, or 9 clocks at much higher frequency.
If you will have many rounds, then you can pipeline sorting stages, getting new result on every clock cycle, with a few clock latency for a first result.
See also https://en.wikipedia.org/wiki/Bitonic_sorter, as more suitable for parallel sorting in hw with small number of inputs.

Verilog syntax error after if control statement

I am trying to make a zero check module in Verilog for my several different select modules.
module check_zero (input [63:0] a, b, [1:0] select, output reg [63:0] out);
if ((a[51:0] == 0) && (b[51:0] == 0)) begin
out <= 0;
state <= done;
end else if (a[51:0]==0 && select==0) begin
out <= b;
state <= done;
end else if (b[51:0]==0 && select==0) begin
out <= a;
state <= done;
end else if (a[51:0]==0 && select==1) begin
out[63] <= ~b[63];
out[62:0] <= ~b[62:0];
state <= done;
end else if (b[51:0]==0 && select==1) begin
out <= a;
state <= done;
end else if (a[51:0]==0 && select==2) begin
out <= 0;
state <= done;
end else if (b[51:0]==0 && select==2) begin
out <= 0;
state <= done;
end
end else if (a[51:0]==0 && select==3) begin
out <= 0;
state <= done;
end else if (b[51:0]==0 && select==3) begin
out[63] <= 1;
out[62:52] <= 2047;
out[51] <= 1;
out[50:0] <= 0;
state <= done;
end
endmodule
I am getting 2 errors in Modelsim:
1. (vlog-13069) syntax error, unexpected '<=' in line 2 after out
2. (vlog-13205) syntax error found in the scope following out, is there a missing '::'
You have an extra "end" there.
end else if (b[51:0]==0 && select==2) begin
out <= 0;
state <= done;
end // this is extra, delete it

Which data type in verilog is equivalent to "variable" in VHDL?

How do I write equivalent verilog code for the below VHDL code?
I show my verilog code behind the VHDL code. The verilog code does compile, but aux is invalid during the entire simulation.
VHDL: (classic_multiplier_parameters.vhd defines m = 8)
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;
use work.classic_multiplier_parameters.all;
entity poly_multiplier is
port (
a, b: in std_logic_vector(M-1 downto 0);
d: out std_logic_vector(2*M-2 downto 0)
);
end poly_multiplier;
architecture simple of poly_multiplier is
type matrix_ands is array (0 to 2*M-2) of STD_LOGIC_VECTOR(2*M-2 downto 0);
signal a_by_b: matrix_ands;
signal c: std_logic_vector(2*M-2 downto 0);
begin
gen_ands: for k in 0 to M-1 generate
l1: for i in 0 to k generate
a_by_b(k)(i) <= A(i) and B(k-i);
end generate;
end generate;
gen_ands2: for k in M to 2*M-2 generate
l2: for i in k to 2*M-2 generate
a_by_b(k)(i) <= A(k-i+(M-1)) and B(i-(M-1));
end generate;
end generate;
d(0) <= a_by_b(0)(0);
gen_xors: for k in 1 to 2*M-2 generate
l3: process(a_by_b(k),c(k))
variable aux: std_logic;
begin
if (k < M) then
aux := a_by_b(k)(0);
for i in 1 to k loop aux := a_by_b(k)(i) xor aux; end loop;
else
aux := a_by_b(k)(k);
for i in k+1 to 2*M-2 loop aux := a_by_b(k)(i) xor aux; end loop;
end if;
d(k) <= aux;
end process;
end generate;
end simple;
Verilog:
module mul(
a, b,
d);
parameter M = 8;
input [M-1:0] a, b;
output [2*M-2:0] d;
wire [2*M-2:0] a_by_b [2*M-2:0];
wire aux;
//`UNPACK_ARRAY(2*M-2, 2*M-2, pack_a_by_b, a_by_b)
//the first and
genvar i, k;
generate
for(k=0; k<=M-1; k=k+1) begin: for1_outer
for(i=0; i<=k; i=i+1) begin: for1_inner
assign a_by_b[k][i] = a[i] & b[k-i];
end
end
endgenerate
//second and
generate
for(k=M; k<=2*M-2; k=k+1) begin: for2_outer
for(i=k; i<=2*M-2; i=i+1) begin: for2_inner
assign a_by_b[k][i] = a[k-i+(M-1)] & b[i-(M-1)];
end
end
endgenerate
assign d[0] = a_by_b[0][0];
// xors
generate
for(k=1; k<=2*M-2; k=k+1) begin: for3_outer
if(k < M) begin
assign aux = a_by_b[k][0];
for(i=1; i<=k; i=i+1) begin: for3_inner1
assign aux = a_by_b[k][i] ^ aux;
end
end
else begin
assign aux = a_by_b[k][k];
for(i=k+1; i<=2*M-2; i=i+1) begin: for3_inner2
assign aux = a_by_b[k][i] ^ aux;
end
end
assign d[k] = aux;
end
endgenerate
endmodule
Verilog: (aux as reg type)
module mul(
a, b,
d);
parameter M = 3;
input [M-1:0] a, b;
output [2*M-2:0] d;
wire [2*M-2:0] a_by_b [2*M-2:0];
reg aux = 1'b1;
//`UNPACK_ARRAY(2*M-2, 2*M-2, pack_a_by_b, a_by_b)
//the first and
genvar i, k;
generate
for(k=0; k<=M-1; k=k+1) begin: for1_outer
for(i=0; i<=k; i=i+1) begin: for1_inner
assign a_by_b[k][i] = a[i] & b[k-i];
end
end
endgenerate
//second and
generate
for(k=M; k<=2*M-2; k=k+1) begin: for2_outer
for(i=k; i<=2*M-2; i=i+1) begin: for2_inner
assign a_by_b[k][i] = a[k-i+(M-1)] & b[i-(M-1)];
end
end
endgenerate
assign d[0] = a_by_b[0][0];
// xors
generate
for(k=1; k<=2*M-2; k=k+1) begin: for3_outer
if(k < M) begin
always #(*) begin
aux = a_by_b[k][0];
end
for(i=1; i<=k; i=i+1) begin: for3_inner1
always #(*) begin
aux <= a_by_b[k][i] ^ aux;
end
end
end
else begin
always #(*) begin
aux <= a_by_b[k][k];
end
for(i=k+1; i<=2*M-2; i=i+1) begin: for3_inner2
always #(*) begin
aux <= a_by_b[k][i] ^ aux;
end
end
end
assign d[k] = aux;
end
endgenerate
endmodule
Sounds like you are looking for "reg". So for instance, reg aux instead of wire aux, and get rid of the "assigns" when you assign it.
(That said, that doesn't seem to be the only problem with this code.)

VHDL convert to verilog

I would like to convert the following VHDL code into Verilog. But I ran into some problems as I mentioned herecompilation error.
Could some one give me some hints of how to properly write the same function in Verilog?
Thank you!
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;
use work.classic_multiplier_parameters.all;
entity poly_multiplier is
port (
a, b: in std_logic_vector(M-1 downto 0);
d: out std_logic_vector(2*M-2 downto 0)
);
end poly_multiplier;
architecture simple of poly_multiplier is
type matrix_ands is array (0 to 2*M-2) of STD_LOGIC_VECTOR(2*M-2 downto 0);
signal a_by_b: matrix_ands;
signal c: std_logic_vector(2*M-2 downto 0);
begin
gen_ands: for k in 0 to M-1 generate
l1: for i in 0 to k generate
a_by_b(k)(i) <= A(i) and B(k-i);
end generate;
end generate;
gen_ands2: for k in M to 2*M-2 generate
l2: for i in k to 2*M-2 generate
a_by_b(k)(i) <= A(k-i+(M-1)) and B(i-(M-1));
end generate;
end generate;
d(0) <= a_by_b(0)(0);
gen_xors: for k in 1 to 2*M-2 generate
l3: process(a_by_b(k),c(k))
variable aux: std_logic;
begin
if (k < M) then
aux := a_by_b(k)(0);
for i in 1 to k loop aux := a_by_b(k)(i) xor aux; end loop;
else
aux := a_by_b(k)(k);
for i in k+1 to 2*M-2 loop aux := a_by_b(k)(i) xor aux; end loop;
end if;
d(k) <= aux;
end process;
end generate;
end simple;
The code section below should do it.
Notes :
in your code, constant M is defined is a separate package, I've moved it to be a parameter (Verilog) or generic (VHDL)
Verilog is case-sensitive, so you have to fix the spelling of M, a and b
Verilog code:
module poly_multiplier(a, b, d);
parameter M = 0;
input [M - 1:0] a;
input [M - 1:0] b;
output [2 * M - 2:0] d;
wire [M - 1:0] a;
wire [M - 1:0] b;
reg [2 * M - 2:0] d;
wire [2 * M - 2:0] a_by_b[0:2 * M - 2];
wire [2 * M - 2:0] c;
generate
genvar k0;
for (k0 = 0; k0 <= M - 1; k0=k0+1) begin : gen_ands
genvar i0;
for (i0 = 0; i0 <= k0; i0=i0+1) begin : l1
assign a_by_b[k0][i0] = a[i0] & b[k0 - i0];
end
end
endgenerate
generate
genvar k1;
for (k1 = M; k1 <= 2 * M - 2; k1=k1+1) begin : gen_ands2
genvar i1;
for (i1 = k1; i1 <= 2 * M - 2; i1=i1+1) begin : l2
assign a_by_b[k1][i1] = a[k1 - i1 + M - 1] & b[i1 - M + 1];
end
end
endgenerate
always #(*) begin
d[0] = a_by_b[0][0];
end
generate
genvar k2;
for (k2 = 1; k2 <= 2 * M - 2; k2=k2+1) begin : gen_xors
reg aux;
integer i;
always #(*) begin : P2
if ((k2 < M)) begin
aux = a_by_b[k2][0];
for(i = 1; i <= k2; i = i + 1) begin
aux = a_by_b[k2][i] ^ aux;
end
end
else begin
aux = a_by_b[k2][k2];
for(i = k2 + 1; i <= 2 * M - 2; i = i + 1) begin
aux = a_by_b[k2][i] ^ aux;
end
end
d[k2] = aux;
end
end
endgenerate
endmodule

Resources