Multiple variables in Verilog case structure control expression - syntax

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

Related

Why am I getting errors in lines 56-61?

I am trying to set up a problem for state machines in lab and I keep receiving errors when trying to compile in Quartus
I have tried using commas, else statements and nothing seems to work
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.All;
ENTITY SM_VHDL IS -- Do not modify this entity statement!
PORT(X : IN STD_LOGIC_VECTOR(1 DOWNTO 0);
RESETN,
CLOCK : IN STD_LOGIC;
Z : OUT STD_LOGIC;
Q : OUT STD_LOGIC_VECTOR(1 DOWNTO 0) );
END SM_VHDL; -- Do not modify this entity statement!
ARCHITECTURE behavior of SM_VHDL IS
TYPE STATE_TYPE IS (A, B, C);
SIGNAL state : STATE_TYPE;
BEGIN
PROCESS(CLOCK, RESETN)
BEGIN
IF RESETN = '0' THEN
state <= A;
ELSIF CLOCK'EVENT AND CLOCK = '1' THEN
CASE state IS
WHEN A =>
CASE X IS
WHEN "00" =>
state <= B;
WHEN "11" =>
state <= C;
WHEN OTHERS =>
state <= A;
END CASE;
WHEN B =>
CASE X IS
WHEN "10" =>
state <= A;
WHEN "11" =>
state <= C;
WHEN OTHERS =>
state <= B;
END CASE;
WHEN C =>
CASE X IS
WHEN "00" =>
state <= B;
WHEN "01" =>
state <= A;
WHEN OTHERS =>
state <= C;
END CASE;
END CASE;
END IF;
END PROCESS;
Z <= '1' WHEN C;
'0' WHEN A;
'0' WHEN B;
Q <= "00" WHEN A;
"01" WHEN B;
"10" WHEN C;
"11" WHEN "-";
END behavior;
I need it to compile
WHEN can only be used with boolean conditions. A/B/C are all literals of STATE_TYPE. You need to create a boolean result by creating a comparison on the state signal:
Z <= '1' when STATE = C
else '0' when STATE = A -- This state not actually needed as a single ELSE would cover it
else '0';
Ill let you work out the statement for Q
The syntax for assigning to Z and Q is wrong for multiple issues:
Missing WITH state SELECT ... before assign
Uses ";" between when parts, use , instead
Cant use "-" (don't care) after last when, use OTHERS instead
So updated code:
WITH state SELECT Z <=
'1' WHEN C,
'0' WHEN A,
'0' WHEN B;
WITH state SELECT Q <=
"00" WHEN A,
"01" WHEN B,
"10" WHEN C,
"11" WHEN OTHERS;
Btw. consider using ModelSim Starter Edition as compiler/simulator before moving to Quartus, since the compile time is faster and messages often better.

Why does my selected signal assignment not work?

What did I do wrong with the selected signal assignment in my VHDL code?
with s select x <= a when (s = '1')
else y <= a when (s = '0');
I also tried this:
with s select x <= a when '1';
with s select y <= a when '0';
It's not completly clear what you want to do. From what you showed us, it seems to me that you want to create a demux controlled by signal s (1 input, 2 outputs), where x <= a when s='1' and y <= a when s='0'
The use of select should be done in cases when you want to create a mux (n inputs, 1 output). That is, the opposite of a demux!
I would recommend you to use a simple if statement to create a demux.
Example:
if s='1' then x <= a; else y <= a; end if;

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.

VHDL frequency divider code

I have this code:
architecture Behavioral of BlockName is
signal t: std_logic;
signal c : std_logic_vector (1 downto 0);
begin
process (reset, clk) begin
if (reset = '1') then
t <= '0';
c <= (others=>'0');
elsif clk'event and clk='l' then
if (c = din) then
t <= NOT(t);
c <= (others=>'0');
else
c <= c + 1;
end if;
end if;
end process;
dout <= t;
end Behavioral;
This code's role is to divide the frequency when it gets input (clock + value) and outputs a divided frequency.
Now my questions:
What does this c <= (others=>'0'); mean ?
What value does t get here t <= NOT(t); ? the last t value? does the <= work as = ?
c <= (others=>'0'); is equivalent to c <= "00";
t <= not(t); assigns to t the opposite of the current value in t.
= is an equality comparison in VHDL.
<= is signal assignment in VHDL.
since 'C' is taken as a vector and to store every bit of it with zero 'c <= (others=>'0');' was used and the concept of blocking and non blocking signals is not present in VHDL. here '=' is used to compare and '<=' is used to assign the signal.
In the your code 't' is declared as a signal and a signal will be updated at the end of the every iteration of the process block. so in the statement 't <= NOT(t);' the value of the t is still the old value and will be updated at the end of the current simulation tick.

VHDL mux implementation?

Is it possible to implement a mux with multiple control signals? For example, I want to do something like this:
with (sig1 & sig2) select
output <= A when "00",
B when "01",
C when "10",
D when "11",
'0' when others;
I know I could just assign them to a new signal and use that, but that's something I want to avoid if possible.
You need to enable VHDL2008 mode on your compiler to have it work.
An alternative (also 2008):
muxing: process (sig1, sig2) is
begin -- process muxing
case sig1 & sig2 is
when "00" => output <= '1';
when "01" => output <= '0';
when "10" => output <= '0';
when "11" => output <= '1';
when others => output <= '0';
end case;
end process muxing;
If you have no VHDL-2008 mode on your compiler it will fail with complaints of
Array type case expression must be of a locally static subtype.
or similar.
If your compiler can't be made to be VHDL-2008 compliant, you have to work around this by creating a type that you can use to surround the sig1 & sig2 to explicitly tell the compiler what's going on:
subtype twobits is bit_vector(0 to 1);
Then:
with twobits'(sig1 & sig2) select
output <= '1' when "00",
-- etc.
or:
case twobits'(sig1 & sig2) is
when "00" => -- etc.
See this, maybe it helps you
entity MUX is
port ( a, i0, i1 : in bit;
o : out bit );
end MUX;
architecture behave of MUX is
begin
process ( a, i0, i1 ) begin
if a = '1' then
o <= i1;
else
o <= i0;
end if;
end process;
end behave;

Resources