How to simplify inputs for a decoder in verilog hdl - boolean

I'm making a decoder for an FPGA. The verilog code compiles, but the switches don't do anything. I quadruple-checked the pin assignments, and they are correct, so I guess there are some logic problems with my code.
The truth table is:
enable p a1 a0 y0 y1 y2 y3
0 0 0 0 1 0 0 0
0 0 0 1 0 1 0 0
0 0 1 0 0 0 1 0
0 0 1 1 0 0 0 1
0 1 0 0 0 1 1 1
0 1 0 1 1 0 1 1
0 1 1 0 1 1 0 1
0 1 1 1 1 1 1 0
1 x x x x z z z
This is my code:
module decoder2x4(
input enable,
input p,
input [1:0] a,
output [3:0] y
);
assign y[0] = (( ~p & ~a[1] & ~a[0]) | (~a[1] & a[0]) |(a[1] & ~a[0]) | ( p & a[1] & a[0]) ) & ~enable;
assign y[1] = (( ~p & ~a[1] & a[0]) | ( p & ~a[1] & ~a[0]) |( p & a[1] & ~a[0])| ( p & a[1] & a[0])) & ~enable;
assign y[2] = (( ~p & a[1] & ~a[0]) | ( p & ~a[1] & ~a[0]) |( p & ~a[1] & a[0])| ( p & a[1] & a[0])) & ~enable;
assign y[3] = (( ~p & a[1] & a[0]) | ( p & ~a[1] & ~a[0]) |( p & ~a[1] & a[0])| ( p & a[1] & ~a[0])) & ~enable;
endmodule

That is not the way you use HDL code, unless it is a school assignment.
I have copied this from the work Pierre.Vriens did to you table:
enable p a1 a0 y0 y1 y2 y3
0 0 0 0 1 0 0 0
0 0 0 1 0 1 0 0
0 0 1 0 0 0 1 0
0 0 1 1 0 0 0 1
0 1 0 0 0 1 1 1
0 1 0 1 1 0 1 1
0 1 1 0 1 1 0 1
0 1 1 1 1 1 1 0
1 x x x x z z z <<< Probably a typo here
The bottom line is a bit special so I use an if for that. The reset we can put in a case:
always #( * )
begin
if (enable)
{y0, y1, y2, y3} = 4'hz; // **
else
case ( {p, a1, a0 } )
3'b000 : {y0, y1, y2, y3} = 4'b1000;
3'b001 : {y0, y1, y2, y3} = 4'b0100;
3'b010 : {y0, y1, y2, y3} = 4'b0010;
3'b011 : {y0, y1, y2, y3} = 4'b0001;
3'b100 : {y0, y1, y2, y3} = 4'b0111;
3'b101 : {y0, y1, y2, y3} = 4'b1011;
3'b110 : {y0, y1, y2, y3} = 4'b1101;
3'b111 : {y0, y1, y2, y3} = 4'b1110;
endcase
end // always
Note that this copies the orignal table as much as possible, which reduced the possibilities of errors. An editor with column editing helps a lot!
** I assume you want all outputs to be 'z'. In your table you have xzzz.

Related

How to create this particular fractal pattern in MATLAB?

I need to make an array of zeros and ones in this particular fractal pattern:
0 0 0 0 0 1 0 0 0 0 0 0
0 0 1 1 1 1 1 1 1 0 0 0
0 1 0 0 0 1 0 0 0 1 0 0
0 1 0 0 1 1 1 0 0 1 0 0
0 1 0 1 0 1 0 1 0 1 0 0
1 1 1 1 1 1 1 1 1 1 1 1
0 1 0 1 0 1 0 1 0 1 0 0
0 1 0 0 1 1 1 0 0 1 0 0
0 1 0 0 0 1 0 0 0 1 0 0
0 0 1 1 1 1 1 1 1 0 0 0
0 0 0 0 0 1 0 0 0 0 0 0
0 0 0 0 0 1 0 0 0 0 0 0
The actual array should be 100 x 100. The pattern should start from the middle (x,y) coordinate, and expand to look like the pattern (using loops).
So far, I have only managed to make a pattern that looks like a '+' sign. I am not sure how to continue it.
This is my code so far:
n = zeros(16); % using 16x16 array for practice
x = length(n)/2;
y = length(n)/2;
z = length(n) - 1;
xso = length(n)/2; % x axis south movement
xno = length(n)/2; % x axis north movement
yea = length(n)/2; % y axis east movement
ywe = length(n)/2; % y axis west movement
for i = 1:1:z
newyea = move('east', x, yea);
n(x, newyea) = 1;
yea = newyea;
newywe = move('west', x, ywe);
n(x, newywe) = 1;
ywe = newywe;
newxso = move('south', xso, y);
n(newxso, y) = 1;
xso = newxso;
newxno = move('north', xno, y);
n(newxno, y) = 1;
xno = newxno;
end
I also have a user defined function:
function newval = move(dir, x, y)
switch dir
case 'east'
newval = y + 1;
case 'west'
newval = y - 1;
case 'south'
newval = x + 1;
case 'north'
newval = x - 1;
end
Since there were no restrictions given on the appearance of the loop, I would propose the below solution. But, before, let's have a look at your given example:
Either you should restrict the desired dimension d to be odd, i.e. d = 11, 13, 15, ... or you should specify, how the pattern should be continued in case of an even dimension d, like here d = 12. For my solution, I decided to rely on the dimension d to be odd.
Here's the code:
d = 15; % Dimension
A = zeros(d); % Initialize output array A
c = (d + 1) / 2; % Calculate center index (row, column)
A(:, c) = 1; % Add: Cross
A(c, :) = 1;
J = 0; % Auxiliary index
for I = (c+2):2:d % For every second row (or column) from center to border
J = J + 1;
l = 4 * J - 1; % Calculate length of line to draw
s = c - (l-1)/2; % Calculate start point of line
e = c + (l-1)/2; % Calculate end point of line
A(I, s:e) = 1; % Add: "South" line
A(s:e, I) = 1; % Add: "East" line
A(c - 2*J, s:e) = 1; % Add: "North" line
A(s:e, c - 2*J) = 1; % Add: "West" line
end
figure(1); % Show image
imagesc(A);
Output for d = 15 (to compare to given example):
Output for d = 99:
Hope that helps!
If you have some more stricter limitations on the for loop, let me/us know. Then, I will try to modify my code accordingly.

Generating discrete signal on Matlab

I am trying to generate a constant signal x[n] = 1 for n = 1, 2, 3 and x[n] = 0 otherwise using matlab.
N = -5:1:5;
X = -5:1:5;
i = 1;
for n = N
if (n >= 1 && n <= 3)
X[i] = 1;
else
X[i] = 0;
end
i = i + 1;
end
But it does not work. I am really new using Matlab for discrete signals, so any help would be welcome.
Thank you.
There is no need to use a for iteration in this case. You can accomplish the same using an indexed approach as follows:
N1 = -5:5;
X1 = zeros(1,numel(N1));
X1(N1 >= 1 & N1 <= 3) = 1
N2 = -8:2;
X2 = zeros(1,numel(N2));
X2(N2 >= 1 & N2 <= 3) = 1
N3 = 1:11;
X3 = zeros(1,numel(N3));
X3(N3 >= 1 & N3 <= 3) = 1
This will output:
X1 =
0 0 0 0 0 0 1 1 1 0 0
X2 =
0 0 0 0 0 0 0 0 0 1 1
X3 =
1 1 1 0 0 0 0 0 0 0 0

Hopfield Network Implementation using Perceptron Learning Rule

I am stuck on implementation of the Hopfiled network with perceptron learning rule. The idea here is to learn the weights for a pattern (binary vector) using single-layer perceptron, and then perform associative memory task using standard Hopfield algorithm. However, after I try to recall a stored vector, the output does not converge to the correct pattern.
See the link, Section 13.4, for more detail on Perceptron implementation the code follows.
w = rand(1,21); %weights
d = [0 0 0 0 0 0]; %desired output
eta = .7; %learning rate
x =[1 1 0 0 0 0]; %memorized pattern
z = zeros(6, 21);
z(1,:) = [x(2) x(3) x(4) x(5) x(6) 0 0 0 0 0 0 0 0 0 0 -1 0 0 0 0 0];
z(2,:) = [x(1) 0 0 0 0 x(3) x(4) x(5) x(6) 0 0 0 0 0 0 0 -1 0 0 0 0];
z(3,:) = [0 x(1) 0 0 0 x(2) 0 0 0 x(4) x(5) x(6) 0 0 0 0 0 -1 0 0 0];
z(4,:) = [0 0 x(1) 0 0 0 x(2) 0 0 x(3) 0 0 x(5) x(6) 0 0 0 0 -1 0 0];
z(5,:) = [0 0 0 x(1) 0 0 0 x(2) 0 0 x(3) 0 x(4) 0 x(6) 0 0 0 0 -1 0];
z(6,:) = [0 0 0 0 x(1) 0 0 0 x(2) 0 0 x(3) 0 x(4) x(5) 0 0 0 0 0 -1];
for t = 1:100
index = randperm(6);
for i=1:6
Y(t,index(i)) = z(index(i),:)*w';
y(t,index(i)) = sgn(Y(t,index(i)));
w = w + eta*(d(index(i)) - y(t,index(i)))*z(index(i),:);
end
end
n = 6;
probe = input('Enter the probe vector: ');
signal_vector = 2*probe-1; % Convert probe to bipolar form
flag = 0; % Initialize flag
old = signal_vector; %save original input
while flag ~= 6; % test if old vector is same as new vector
index = randperm(n); %make sequence for asynchronous update
for j = 1:n
v =z(index(j),:)*w';
if v > 0
signal_vector(index(j)) = 1;
x(index(j)) = 1;
elseif v < 0
signal_vector(index(j)) = -1;
x(index(j)) = -1;
end
end
flag = signal_vector*old';
end
disp('The recalled vector is ')
0.5*(signal_vector + 1)
function y = sgn(x)
if x > 0
y = 1;
else
y = -1;
end
end

How to multiple matrix column in next columns and set in a new matrix?

I want to make second matrix from the first matrix in MATLAB. Please see the following image:
AB = A and B
AC = A and C
BC = B and C
====>>>
code:
transactions={{'A','C'};{'A','B'};{'A','B','C'}};
items = unique([transactions{:}]); % A,B,C
for i = 1:size(transactions,1)
T(i,ismember(items,transactions{i,:})) = 1; %convert transactions to matrix
end
.
.
T1 = zeros(size(transactions,1), nchoosek(length(items),2));
for k=1:5
for i=1: length(items)
for j=i+1 : length(items)
z = bitand(T(k,i),T(k,j)))
% set z in matrix T1 %
end
end
end
How to set the new values and How to concate label in the result matrix?
Simply use Matlab's & operator (see documentation). Because Matlab is an interpreted language, it will automatically convert the 0's and 1's to a logical matrix.
For example:
X = [1 0 1; 1 0 0; 1 1 1; 1 0 0; 1 1 0];
Y(:,1) = X(:,1) & X(:,2);
Y(:,2) = X(:,1) & X(:,3);
Y(:,3) = X(:,2) & X(:,3);
Matrix Y will be of type logical and be the desired output:
>> Y
Y =
0 1 0
0 0 0
1 1 1
0 0 0
1 0 0
Alternatively, you can use a struct for readability:
>> X.A = [1 1 1 1 1];
>> X.B = [0 0 1 0 1];
>> X.C = [1 0 1 0 0];
>> Y.AB = X.A & X.B;
>> Y.AC = X.A & X.C;
>> Y.BC = X.B & X.C;
>> Y
Y =
AB: [0 0 1 0 1]
AC: [1 0 1 0 0]
BC: [0 0 1 0 0]
If you want to automate the process, you could do the following:
X.A = [1 1 1 1 1]';
X.B = [0 0 1 0 1]';
X.C = [1 0 1 0 0]';
names = fieldnames(X);
N = length(names);
combos = nchoosek(1:N,2);
for i=1:N
Y.(char([names(combos(i,1)) names(combos(i,2))])) = ...
X.(char(names(combos(i,1)))) & X.(char(names(combos(i,2))));
end
struct2table(Y)
Which gives the following:
ans =
AB AC BC
_____ _____ _____
false true false
false false false
true true true
false false false
true false false

Indexing of 2D array in matlab

I have a 6X4 matrix M1 containing only zeros.
I also have two 1D arrays Y1 and Y2 each with length 4.The two arrays contain the desired index values. Now, I want to set(convert to 1) the elements of matrix M1 such that
M1(Y1:Y2) is equal to 1
for ex: Y1=[1 2 2 1] and Y2=[3 4 5 3]
then, M1 should be
1 0 0 1
1 1 1 1
1 1 1 1
0 1 1 0
0 0 1 0
0 0 0 0
I can do this using for loop. But is there any optimised way to do it? (I intend to use much bigger matrices)
use cumsum!
>> szM = size(M1);
>> M1( sub2ind( szM, Y1, 1:szM(2) ) ) = 1
M1 =
1 0 0 1
0 1 1 0
0 0 0 0
0 0 0 0
0 0 0 0
0 0 0 0
>> M1( sub2ind( szM, Y2+1, 1:szM(2) ) ) = -1
M1 =
1 0 0 1
0 1 1 0
0 0 0 0
-1 0 0 -1
0 -1 0 0
0 0 -1 0
>> M = cumsum(M,1)
M =
1 0 0 1
1 1 1 1
1 1 1 1
0 1 1 0
0 0 1 0
0 0 0 0
A pitfall:
If any of Y2 equals 6 than setting Y2+1 to -1 will exceed matrix dimension.
To fix this you can add two lines before setting to -1 the elements of M:
>> cols = 1:szM(2);
>> sel = Y2 < szM(1);
>> M1( sub2ind( szM, Y2(sel)+1, cols(sel) ) ) = -1
A spin-off for Pavan Yalamanchili's answer using bsxfun: (hover to see:)
using bsxfun without offsets:
M1 = bsxfun( #ge, (1:size(M1,1))', Y1 ) & bsxfun( #le, (1:size(M1,1))', Y2 );
There may be other techniques, but this uses element wise operations which are insanely parallel.
A very simple solution. Thanks #Shai
>> [rows, cols] = size(M);
>> Y1=[1 2 2 1]; Y2=[3 4 5 3];
>> M = bsxfun(#ge, (1:rows)', Y1) & bsxfun(#le, (1:rows)', Y2)
M =
1 0 0 1
1 1 1 1
1 1 1 1
0 1 1 0
0 0 1 0
0 0 0 0
Unnecessarily complicated code
[rows, cols] = size(M);
offsets = ((1 : cols) - 1) * rows
Y1 = offsets + Y1;
Y2 = offsets + Y2;
M = reshape(1:numel(M), rows, cols);
M = bsxfun(#ge, M, Y1) & bsxfun(#le, M, Y2);