For loop generation in always block - verilog

I'm trying to create 32 color stripes via VGA.
generate
genvar i;
always #(posedge vga_clk) begin
if (x_num == 10'h3FF)
RGB = 16'b00000_000011_00011;
for (i = 1; i < 32; i = i + 1) begin: rgb_gen
40: else if ((i * 20 < x_num) && (x_num < (i + 1) * 20)) begin
RGB = RGB << i;
end
end
end
endgenerate
But there is an error:
Error (10170): Verilog HDL syntax error at top.v(40) near text "else"; expecting "end"
In my mind, result have to be following:
always #(posedge vga_clk) begin
if (x_num == 10'h3FF)
RGB = 16'b00000_000011_00011;
else if ((0 < x_num) && (x_num < 20))
RGB = RGB << 0;
else if ((20 < x_num) && (x_num < 40))
RGB = RGB << 1;
..................
end
What am I doing wrong?

You cannot embed a generate block in the middle of a procedural block of code. I think what you want is
integer i;
always #(posedge vga_clk) begin
RGB = 0;
if (x_num == 10'h3FF)
RGB = 16'b00000_000011_00011;
else
for (i = 1; i < 32; i = i + 1)
if ((i * 20 < x_num) && (x_num < (i + 1) * 20))
RGB = RGB << i;
end

Related

CS50 Wk4 Blur Pset

void blur(int height, int width, RGBTRIPLE image[height][width])
{
for (int i = 0; i < height; i++)
{
for (int j = 0; j < width; j++)
{
int red_total = 0;
int blue_total = 0;
int green_total = 0;
int number_counted = 0;
for (int k = -1; k <= 1; k++)
{
for (int l = -1; l <= 1; l++)
{
if (i + k <= height && i + k >= 0 && j + l <= width && j + l >= 0)
{
blue_total += image[i+k][j+l].rgbtBlue;
red_total += image[i+k][j+l].rgbtRed;
green_total += image[i+k][j+l].rgbtGreen;
number_counted ++;
}
}
}
image[i][j].rgbtBlue = blue_total / number_counted;
image[i][j].rgbtRed = red_total / number_counted;
image[i][j].rgbtGreen = green_total / number_counted;
}
}
return;
}
Why is that section && operators?
if (i + k <= height && i + k >= 0 && j + l <= width && j + l >= 0)
I ran it with || operators because my understanding is that under the guise of the problem IF any of those conditions are satisfied there is no block to add. Yet why is it that when I run it under || it returns segmentation fault whereas if I run it with && the problem works out?
Thank you for answering!
All of those conditions have to be true or else the array operations will be invalid.
e.g. if i+k > height then image[i+k] is invalid.
Also I think you have some "off by one problems. image is [height][width] so valid values are [0..height-1] and [0..width-1] so the checks should be more like if (i + k < height && i + k >= 0 && j + l < width && j + l >= 0)

Faulty outputs for JK flip flop state diagram implementation

I am trying to implement a simple FSM of JK flip flop in verilog. However I see that the outputs 'q' and 'q_not' are wrong for multiple time instants. I am presenting the code and the output below. Could some one please let me know what's wrong with the code. Especially I would like to know what's wrong with this implementation even though there are other ways to implement JK flip flops.
modules of JK flip flop and testbench
`timescale 1ns/100ps
module jk_ff(j, k, clk, reset, q, q_not);
input j, k, clk, reset;
output reg q, q_not;
reg present_state, next_state;
parameter state_a = 1'b0;
parameter state_b = 1'b1;
always # (present_state or j or k)
begin:comb_logic
next_state = state_a;
//next_state = 0;
case(present_state)
state_a: begin
if (j == 1'b0 && k == 1'b0) begin
next_state = state_a;
end
else if (j == 1'b0 && k == 1'b1) begin
next_state = state_a;
end
else if (j == 1'b1 && k == 1'b0) begin
next_state = state_b;
end
else if (j == 1'b1 && k == 1'b1) begin
next_state = state_b;
end
end
state_b: begin
if (j == 1'b0 && k == 1'b0) begin
next_state = state_b;
end
else if (j == 1'b0 && k == 1'b1) begin
next_state = state_a;
end
else if (j == 1'b1 && k == 1'b0) begin
next_state = state_b;
end
else if (j == 1'b1 && k == 1'b1) begin
next_state = state_a;
end
end
default: next_state = state_a;
endcase
end
always # (posedge clk or reset)
begin: seq_logic
if (reset) begin
q <= 1'b0;
q_not <= 1'b1;
present_state <= state_a;
end
else begin
present_state <= next_state;
case(present_state)
state_a: begin
q <= 1'b0;
q_not <= 1'b1;
end
state_b: begin
q <= 1'b1;
q_not <= 1'b0;
end
default: present_state <= state_a;
endcase
end
end
endmodule
//testbench
module jk_ff_tb;
reg j, k, clk, reset;
wire q, q_not;
jk_ff DUT(.j(j), .k(k), .clk(clk), .reset(reset), .q(q), .q_not(q_not));
initial begin
clk =0;
forever #5 clk = !clk;
end
initial begin
$monitor("j = %b, k = %b, q = %b, q_not = %b", j, k, q, q_not);
$dumpfile("jk_ff_wave.vcd");
$dumpvars;
reset = 1;
j=1'b0;
k=1'b1;
#10 reset = 0;
#15 j=1'b1;
#15 k=1'b0;
#15 j=1'b0;
#15 k=1'b1;
#15 j=1'b1;
#15 k=1'b1;
#10 $finish;
end
endmodule
output of the test bench simulation showing values of inputs and primary outputs
j = 0, k = 1, reset = 1, q = 0, q_not = 1
j = 0, k = 1, reset = 0, q = 0, q_not = 1
j = 1, k = 1, reset = 0, q = 0, q_not = 1
j = 1, k = 1, reset = 0, q = 1, q_not = 0
j = 1, k = 0, reset = 0, q = 1, q_not = 0
j = 1, k = 0, reset = 0, q = 0, q_not = 1
j = 0, k = 0, reset = 0, q = 1, q_not = 0
j = 0, k = 1, reset = 0, q = 1, q_not = 0
j = 1, k = 1, reset = 0, q = 0, q_not = 1
j = 1, k = 1, reset = 0, q = 1, q_not = 0
j = 1, k = 1, reset = 0, q = 0, q_not = 1
enter code here
Thank you!
You've got all sorts of problems here:
In seq_logic, you assign present_state with a blocking assignment, and the next statement is case(present_state). This tests the old value of present_state, which isn't what you want
Your 'comb_logic' process is sensitive to present_state, but your seq_logic process changes present_state on rising clock edges. At first sight, that seems the right thing to do, but it's not - draw it out. The way you've written this, comb_logic should be sensitive to only J and K
Those two are enough to get the right result, but this is far too complicated for a JK - start again, put everything in one clocked process, dump the next logic process, just use the behaviour of a JK - load, set, or toggle. You should also add the current time to your $monitor.

Function to calculate a value inside a Verilog generate loop

I am trying to create a parametrized circuit for the multiplication stage of a BCD Wallace Tree Multiplier, which I implemented in Orcad. The trouble I'm having is that I need to calculate the bit positions that each two digits that result from BCD multiplication will inhabit.
Here is my code:
module bcd_mult_1_n #(parameter N = 8)
(input [N * 4 - 1:0] num1, num2, output reg [2 * 4 * N * N - 1:0] partProds);
genvar i, j;
generate
for(i = 0; i < N; i = i + 1) begin : dig1
for(j = 0; j < N; j = j + 1) begin : dig2
localparam lsd = posLSD(i, j);
localparam msd = posMSD(i, j);
bcd_mult_1 bcd_mult(num1[i * 4 + 3:i * 4], num2[j * 4 + 3:j * 4],
partProds[msd * 4 + 3:msd * 4], partProds[lsd * 4 + 3: lsd * 4]);
end
end
endgenerate
In the above code, numPrev(i + j) needs to return a value calculated something like this
int numPrev(int x) {
int acc = 0;
for(int i = x; i > 0; i++) acc = acc + 2 * i;
return acc;
}
Thanks to help from #Morgan I have created the following function; the logic is meant to count up and down a sort of triangle of values which rise from 1 to N and back down to 1.
function integer posLSD;
input integer x, y;
integer weight;
integer acc;
integer num;
integer i;
weight = x + y;
acc = 0;
if(weight >= N) num = N - 1;
else num = weight;
for(i = num; i > 0; i = i - 1)
acc = acc + 2 * i;
if(weight >= N) begin
for(i = 2 * N - weight; i <= N; i = i + 1) begin
acc = acc + 2 * i;
end
acc = acc + N - weight + y - 1;
end
else
acc = acc + y;
posLSD = acc;
endfunction
function integer posMSD;
input integer x, y;
integer acc;
integer weight;
acc = posLSD(x, y);
weight = x + y;
if(weight < N) acc = acc + weight + 1;
else acc = acc + 2 * N - weight - 1;
posMSD = acc;
endfunction
How could I achieve this functionality? If needed, I could use SystemVerilog constructs.
When I change to use a function I get the error Packed dimension must specify a range. I think you need to think about your partProds width and connections.
Using a function:
module bcd_mult_1_n #(
parameter N = 8
) (
input [N * 4 - 1:0] num1,
input [N * 4 - 1:0] num2,
output reg [2 * 4 * N * N] partProds
);
integer prev = 1;
genvar i, j;
generate
for(i = 0; i < N; i = i + 1) begin : dig1
for(j = 0; j < N; j = j + 1) begin : dig2
bcd_mult_1
bcd_mult(
num1[i * 4 + 3:i * 4],
num2[j * 4 + 3:j * 4],
partProds[numPrev(i+j) + 2*j + i + 1],
partProds[numPrev(i+j) + j]
);
end
end
endgenerate
function numPrev;
input integer x ;
integer acc;
begin
acc = 0;
for(int ij = x; ij > 0; ij++) begin
acc = acc + 2 * ij;
end
numPrev = acc;
end
endfunction
endmodule
module bcd_mult_1(
input [3:0]a,
input [3:0]b,
input c,
input d
);
endmodule
Example on EDA Playground.

Rewrite code using generate statement (Verilog HDL)

I'm trying to rewrite this code using generate statements (Verilog HDL):
integer j;
always#(posedge cpu_clk) begin
// ACCU_RST
if(RAM[3][7]) begin
RAM[3][7] <= 1'b0;
for(j = 10; j <= 15; j = j + 1)
RAM[j] <= 8'b0;
end
// CPU write
RAM[addr + 0] <= in_valid && cmd && (addr + 0 <= 9 || addr + 0 >= 16) ? data_in[8 * 0 + 7:8 * 0] : RAM[addr + 0];
RAM[addr + 1] <= in_valid && cmd && (addr + 1 <= 9 || addr + 1 >= 16) ? data_in[8 * 1 + 7:8 * 1] : RAM[addr + 1];
RAM[addr + 2] <= in_valid && cmd && (addr + 2 <= 9 || addr + 2 >= 16) ? data_in[8 * 2 + 7:8 * 2] : RAM[addr + 2];
RAM[addr + 3] <= in_valid && cmd && (addr + 3 <= 9 || addr + 3 >= 16) ? data_in[8 * 3 + 7:8 * 3] : RAM[addr + 3];
//CPU read
out_valid <= !cmd && in_valid;
out_data[8 * 0 + 7:8 * 0] <= !cmd && in_valid ? RAM[addr + 0] : out_data[8 * 0 + 7:8 * 0];
out_data[8 * 1 + 7:8 * 1] <= !cmd && in_valid ? RAM[addr + 1] : out_data[8 * 1 + 7:8 * 1];
out_data[8 * 2 + 7:8 * 2] <= !cmd && in_valid ? RAM[addr + 2] : out_data[8 * 2 + 7:8 * 2];
out_data[8 * 3 + 7:8 * 3] <= !cmd && in_valid ? RAM[addr + 3] : out_data[8 * 3 + 7:8 * 3];
end
Yet I recieve the following errors if I try this:
// CPU write
for(i = 0; i <= 3; i = i + 1) begin
if(in_valid && cmd && (addr + i <= 9 || addr + i >= 16))
RAM[addr + i] <= data_in[8 * i + 7:8 * i];
end
//CPU read
out_valid <= !cmd && in_valid;
for(i = 0; i <= 3; i = i + 1) begin
if(in_valid && !cmd)
out_data[8 * i + 7:8 * i] <= RAM[addr + i];
end
ERROR: i is not a constant value.
(error points to data_in[8 * i + 7:8 * i] and out_data[8 * i + 7:8 * i])
Another try, using two always blocks, one for generate, one for ACCU_RST yields multiple drivers for RAM (duh).
Last try:
genvar i;
always#(posedge cpu_clk) begin
if(ACCU_RST) begin
RAM[3][7] <= 1'b0;
for(j = 10; j <= 15; j = j + 1)
RAM[j] <= 8'b0;
end
// CPU write cmd
for(i = 0; i <= 3; i = i + 1) begin :CPU_W
if(in_valid && cmd && (addr + i <= 9 || addr + i >= 16))
RAM[addr + i] <= data_in[8 * i + 7:8 * i];
end
//CPU read cmd
out_valid <= !cmd && in_valid;
for(i = 0; i <= 3; i = i + 1) begin :CPU_R
if(in_valid && !cmd)
out_data[8 * i + 7:8 * i] <= RAM[addr + i];
end
end
That yields:
ERROR: Procedural assignment to a non-register i is not permitted,
left-hand side should be reg/integer/time/genvar
(and points to i = 0 and to i = i + 1).
For this you shouldn't use a generate block. The generate for loop must exist outside of an always block. And a values must only be assigned in one always block to be synthesizable. Take the below example, RAM[2] can be assigned when addr==0 on the third loop (i==2), when addr==1 on the second loop (i==1), and when addr==2 on on the first loop (i==0). Three separate always blocks which is a synthesizable error.
genvar i;
generate
for(i=0; i<4; i++) begin
always #(posedge clk)
if (in_valid && cmd && (addr + i <= 9 || addr + i >= 16))
RAM[addr + i] <= data_in[8*i + 7 : 8*i];
end
endgenerate
Skip the generate and use a standard for loop inside the always block. Use indexed part-select (references here and here):
integer i; // <-- not genvar
always #(posedge cpu_clk) begin
/* ... your other code ... */
// CPU write cmd
for (i = 0; i < 4; i = i + 1) begin :CPU_W
if (in_valid && cmd && (addr + i <= 9 || addr + i >= 16))
RAM[addr + i] <= data_in[ 8*i +: 8];
end
//CPU read cmd
out_valid <= !cmd && in_valid;
for (i = 0; i < 4; i = i + 1) begin :CPU_R
if (in_valid && !cmd)
out_data[ 8*i +: 8] <= RAM[addr + i];
end
end

Verilog Image Filter

I've been playing around in verilog trying to implement a little image filter that adds a blur effect, mirrors an image, or rotates it 90*. I'm pretty new to this stuff so please bear with me.
I've noticed while running simulations that the registers have a big delay before they change to their new values, this has cause some problems for me so far. I've managed to get mirroring and rotation to work, then added the blur filter. Now it won't work anymore for some odd reason, even after removing the new added code. It keeps showing me that the output are X...
I'm using a 64x64 grayscale image, and doing some simple matrix operations. Still i can't seem to get to work properly, the blur filter specifically, and now i have this mysterious all outputs are X while in simulation mode for some reason.
Here is the code for the process:
`timescale 1ns / 1ps
module process(
input clk, // clock
input [1:0] op, // 0 - filtrul de tip blur; 1 - oglindire; 2 - rotire
input [7:0] in_pix, // valaorea pixelului de pe pozitia [in_row, in_col] din imaginea de intrare
output reg [5:0] in_row, in_col, // selecteaza un rand si o coloana din imaginea de intrare
output reg [5:0] out_row, out_col, // selecteaza un rand si o coloana din imaginea de iesire
output reg out_we, // activeaza scrierea pentru imaginea de iesire (write enable)
output reg [7:0] out_pix, // valoarea pixelului care va fi scrisa in imaginea de iesire pe pozitia [out_row, out_col]
output reg done // semnaleaza cand s-a terminat procesarea unei imagini
);
// TODO add your finite state machines here
`define INIT 3'b000
`define MOVE_PIXEL 3'b001
`define INC_INDEX 3'b010
`define DONE 3'b011
`define DIVISION 3'b100
reg [6:0] index_col,index_row,index1_col,index1_row; // indicatori cu care se parcurg matricea imagine pentru input si output.
reg [2:0] state; // registru de stare pentru automate
reg [7:0] pixel; // registru in care stocam valoarea de pixel pentru intrare si iesire
reg [7:0] pixel_q; // registru folosit pentru memorarea catului la impartirea prin 5.
reg [10:0] sum; // folosit pentru insumarea pixelilor vecini dupa care este inmultita cu 0.2 pentru a face sum/5. este pe 11 biti deoarece 255*5 este 1275, deci 2^11 = 2048 ca sa nu avem overflow
reg [3:0] timer; // timer pentru sincronizarea datelor , am ales sa astept 6 ciclii pentru realizarea sincronizarii
always#(posedge clk) begin
/*if(op == 0) begin // Pentru marginile imaginii am decis sa fac cazuri speciale
state <= `INIT; // astfel adun doar elementele care exista langa pixelul curent
// de exemplu in coltul 0.0 avem elemente doar la 0.1 si 1.0.
case(state)
`INIT: begin
index_row <= 0;
index_col <= 0;
done <= 0;
timer <= 0;
pixel_q <= 0;
state <= `MOVE_PIXEL;
end
`MOVE_PIXEL: begin
sum <= 0;
in_row <= index_row;
in_col <= index_col;
pixel <= in_pix;
if(timer < 6) begin
timer <= timer + 1;
state <=`MOVE_PIXEL;
end else begin
sum <= sum + pixel;
if(index_row == 0 && index_col == 0) begin // cazuri speciale: colturile si marginile; coltul 0.0
in_row <= index_row + 1;
pixel <= in_pix;
sum <= sum + pixel;
in_row <= index_row - 1;
in_col <= index_col + 1;
pixel <= in_pix;
sum <= sum + pixel;
// sum <= sum * 0.2;
in_col <= index_col - 1;
state <= `DIVISION;
end else if (index_row == 0 && index_col == 63) begin // coltul 0.63
in_row <= index_row + 1;
pixel <= in_pix;
sum <= sum + pixel;
in_row <= index_row - 1;
in_col <= index_col - 1;
pixel <= in_pix;
sum <= sum + pixel;
// sum <= sum * 0.2;
in_col <= index_col + 1;
state <= `DIVISION;
end else if(index_row == 63 && index_col == 0) begin //coltul 63.0
in_row <= index_row - 1;
pixel <= in_pix;
sum <= sum + pixel;
in_row <= index_row + 1;
in_col <= index_col + 1;
pixel <= in_pix;
sum <= sum + pixel;
// sum <= sum * 0.2;
in_col <= index_col - 1;
state <= `DIVISION;
end else if(index_row == 63 && index_col == 63) begin // coltul 63.63
in_row <= index_row - 1;
pixel <= in_pix;
sum <= sum + pixel;
in_row <= index_row + 1;
in_col <= index_col - 1;
pixel <= in_pix;
sum <= sum + pixel;
// sum <= sum * 0.2;
in_col <= index_col + 1;
state <= `DIVISION;
end else if(in_row == 0 && in_col > 0) begin // marginea de sus
in_row <= index_row + 1;
pixel <= in_pix;
sum <= sum + pixel;
in_row <= index_row - 1;
in_col <= index_col + 1;
pixel <= in_pix;
sum <= sum + pixel;
in_col <= index_col - 2;
pixel <= in_pix;
sum <= sum + pixel;
// sum <= sum * 0.2;
in_col <= index_col + 1;
state <= `DIVISION;
end else if(in_col == 0 && in_row > 0) begin // marginea din stanga
in_row <= index_row + 1;
pixel <= in_pix;
sum <= sum + pixel;
in_row <= index_row - 1;
in_col <= index_col + 1;
pixel <= in_pix;
sum <= sum + pixel;
in_col <= index_col - 1;
in_row <= index_row - 1;
pixel <= in_pix;
sum <= sum + pixel;
// sum <= sum * 0.2;
in_col <= index_row + 1;
state <= `DIVISION;
end else if(in_row == 63 && in_col > 0) begin //marginea de jos
in_row <= index_row - 1;
pixel <= in_pix;
sum <= sum + pixel;
in_row <= index_row + 1;
in_col <= index_col + 1;
pixel <= in_pix;
sum <= sum + pixel;
in_col <= index_col - 2;
pixel <= in_pix;
sum <= sum + pixel;
// sum <= sum * 0.2;
in_col <= index_col + 1;
state <= `DIVISION;
end else if(in_col == 63 && in_row > 0) begin // marginea din dreapta
in_row <= index_row + 1;
pixel <= in_pix;
sum <= sum + pixel;
in_row <= index_row - 1;
in_col <= index_col - 1;
pixel <= in_pix;
sum <= sum + pixel;
in_col <= index_col + 1;
in_row <= index_row - 1;
pixel <= in_pix;
sum <= sum + pixel;
// sum <= sum * 0.2;
in_col <= index_row + 1;
state <= `DIVISION;
end else begin //interiorul matricii // 0 (index_row -1).index_col 0
in_row <= index_row + 1; // index_row.(index_col - 1) index_row.index_col index_row.(index_col + 1)
pixel <= in_pix; // 0 (index_row + 1).index_col 0
sum <= sum + pixel; // Structura in care sunt alesi pixelii pentru blur.
in_row <= index_row - 1;
in_col <= index_col - 1;
pixel <= in_pix;
sum <= sum + pixel;
in_col <= index_col + 1;
in_row <= index_row - 1;
pixel <= in_pix;
sum <= sum + pixel;
in_col <= index_col + 1;
in_row <= index_row - 1;
pixel <= in_pix;
sum <= sum + in_pix;
// sum <= sum * 0.2;
in_col <= index_col - 1;
state <= `DIVISION;
out_row <= index_row;
out_col <= index_col;
out_we <= 1;
out_pix <= pixel;
state <= `INC_INDEX;
end
end
end
`DIVISION: begin
if(sum >= 5) begin
sum <= sum - 5;
pixel_q <= pixel_q + 1;
state <= `DIVISION;
end else begin
out_row <= index_row;
out_col <= index_col;
out_we <= 1;
out_pix <= pixel_q;
state <= `INC_INDEX;
end
end
`INC_INDEX: begin
index_col <= index_col + 1;
if( index_col == 63 ) begin
index_row <= index_row + 1;
state <= `MOVE_PIXEL;
end else if (index_row == 63 && index1_row == 63) begin
state <= `DONE;
end else begin
state <= `MOVE_PIXEL;
end
end
`DONE: begin
done <= 1;
state <= `INIT;
end
endcase
end */
if(op == 1) begin // pixelii sunt inversati ca pozitie, pixelii din prima coloana trec in ultima si invers, procedeul se repeta secvential.
state <= `INIT;
case(state)
`INIT: begin
index_row <= 0;
index_col <= 0;
index1_row <= 0;
index1_col <= 63;
// timer <= 0;
done <= 0;
state <= `MOVE_PIXEL;
end
`MOVE_PIXEL: begin
in_row <= index1_row;
in_col <= index1_col;
pixel <= in_pix;
// if(timer < 6) begin
// timer <= timer + 1;
// state <=`MOVE_PIXEL;
// end else begin
out_row <= index_row;
out_col <= index_col;
out_we <= 1;
out_pix <= pixel;
out_we <= 0;
state <= `INC_INDEX;
// end
end
`INC_INDEX: begin
index_col <= index_col + 1;
index1_col <= index1_col - 1;
if( index_col == 63 && index1_col == 0) begin
index_row <= index_row + 1;
index1_row <= index1_row +1;
state <= `MOVE_PIXEL;
end else if (index_row == 63 && index1_row == 63) begin
state <= `DONE;
end else begin
state <= `MOVE_PIXEL;
end
end
`DONE: begin
done <= 1;
state <= `INIT;
end
endcase
end
if(op == 2) begin // liniile devine coloane, se incepe de la ultima linie care se scrie ca prima coloana si se repeta procedeul.
state <= `INIT;
case(state)
`INIT: begin
index_row <= 0;
index_col <= 0;
index1_row <= 63;
index1_col <= 0;
// timer <= 0;
done <= 0;
state <= `MOVE_PIXEL;
end
`MOVE_PIXEL: begin
in_row <= index1_row;
in_col <= index1_col;
pixel <= in_pix;
// if(timer < 6) begin
// timer <= timer + 1;
// state <=`MOVE_PIXEL;
// end else begin
out_row <= index_row;
out_col <= index_col;
out_we <= 1;
out_pix <= pixel;
out_we <= 0;
state <= `INC_INDEX;
// end
end
`INC_INDEX: begin
index_row <= index_row + 1;
index1_col <= index1_col + 1;
if( index_row == 63 && index1_col == 63) begin
index_col <= index_col + 1;
index1_row <= index1_row - 1;
state <= `MOVE_PIXEL;
end else if (index_col == 63 && index1_row == 0) begin
state <= `DONE;
end else begin
state <= `MOVE_PIXEL;
end
end
`DONE: begin
done <= 1;
state <= `INIT;
end
endcase
end
end
endmodule
It interacts with an image module:
`timescale 1ns / 1ps
module image(
input clk, // clock
input[5:0] row, // selecteaza un rand din imagine
input[5:0] col, // selecteaza o coloana din imagine
input we, // write enable (activeaza scrierea in imagine la randul si coloana date)
input[7:0] in, // valoarea pixelului care va fi scris pe pozitia data
output[7:0] out // valoarea pixelului care va fi citit de pe pozitia data
);
reg[7:0] data[63:0][63:0];
assign out = data[row][col];
always #(posedge clk) begin
if(we)
data[row][col] <= in;
end
endmodule
Could anyone give me any help ? I apologize if my question is in the incorrect format, first time posting here.
LE: I've redesigned the state machine for the blur filter but i'm getting some odd warnings. For instance it says for Timer_3 (i assume its talking about timer from the third FSM which handles rotation) "FF/Latch (without init value) has a constant value of 0 in block . This FF/Latch will be trimmed during the optimization process."
And this one as well " Signal is assigned but never used. This unconnected signal will be trimmed during the optimization process." I don't get it how is it not used? I clearly use it to go to INIT_BLUR and from there to CURRENT_PIXEL.
`timescale 1ns / 1ps
module process(
input clk, // clock
input [1:0] op, // 0 - filtrul de tip blur; 1 - oglindire; 2 - rotire
input [7:0] in_pix, // valaorea pixelului de pe pozitia [in_row, in_col] din imaginea de intrare
output reg [5:0] in_row, in_col, // selecteaza un rand si o coloana din imaginea de intrare
output reg [5:0] out_row, out_col, // selecteaza un rand si o coloana din imaginea de iesire
output reg out_we, // activeaza scrierea pentru imaginea de iesire (write enable)
output reg [7:0] out_pix, // valoarea pixelului care va fi scrisa in imaginea de iesire pe pozitia [out_row, out_col]
output reg done // semnaleaza cand s-a terminat procesarea unei imagini
);
// TODO add your finite state machines here
`define INIT_BLUR 4'b0000
`define CURRENT_PIXEL 4'b0001
`define TOP_PIXEL 4'b0010
`define BOTTOM_PIXEL 4'b0011
`define LEFT_PIXEL 4'b0100
`define RIGHT_PIXEL 4'b0101
`define DIVISION 4'b0110
`define INC_INDEX_BLUR 4'b0111
`define DONE_BLUR 4'b1000
`define INIT 3'b000
`define MOVE_PIXEL 3'b001
`define INC_INDEX 3'b010
`define DONE 3'b011
reg [6:0] index_col,index_row,index1_col,index1_row; // indicatori cu care se parcurg matricea imagine pentru input si output.
reg [2:0] state; // registru de stare pentru automate
reg [3:0] blur_states;
reg [7:0] pixel; // registru in care stocam valoarea de pixel pentru intrare si iesire
reg [7:0] pixel_q; // registru folosit pentru memorarea catului la impartirea prin 5.
reg [10:0] sum; // folosit pentru insumarea pixelilor vecini dupa care este inmultita cu 0.2 pentru a face sum/5. este pe 11 biti deoarece 255*5 este 1275, deci 2^11 = 2048 ca sa nu avem overflow
reg [3:0] timer; // timer pentru sincronizarea datelor , am ales sa astept 6 ciclii pentru realizarea sincronizarii
always#(posedge clk) begin
if(op == 0) begin // Pentru marginile imaginii am decis sa fac cazuri speciale
blur_states <= `INIT_BLUR; // astfel adun doar elementele care exista langa pixelul curent
// de exemplu in coltul 0.0 avem elemente doar la 0.1 si 1.0.
case(state)
`INIT_BLUR: begin
index_row <= 0;
index_col <= 0;
index1_row <= 0;
index1_col <= 0;
done <= 0;
timer <= 0;
pixel_q <= 0;
state <= `CURRENT_PIXEL;
end
`CURRENT_PIXEL: begin
sum <= 0;
in_row <= index_row;
in_col <= index_col;
pixel <= in_pix;
sum <= sum + pixel;
if(timer < 6) begin
timer <= timer + 1;
state <=`CURRENT_PIXEL;
end else begin
if(index_row == 0 && index_col == 0) begin // cazuri speciale: colturile si marginile; coltul 0.0
blur_states <= `RIGHT_PIXEL;
end else if (index_row == 0 && index_col == 63) begin // coltul 0.63
blur_states <= `BOTTOM_PIXEL;
end else if(in_row == 0 && in_col > 0) begin // marginea de sus
blur_states <= `RIGHT_PIXEL;
end else begin //interiorul matricii
blur_states <= `TOP_PIXEL;
// 0 (index_row -1).index_col 0
// in_row <= index_row + 1; // index_row.(index_col - 1) index_row.index_col index_row.(index_col + 1)
// pixel <= in_pix; // 0 (index_row + 1).index_col 0
// sum <= sum + pixel; // Structura in care sunt alesi pixelii pentru blur.
// in_row <= index_row - 1;
// in_col <= index_col - 1;
// pixel <= in_pix;
// sum <= sum + pixel;
// in_col <= index_col + 1;
// in_row <= index_row - 1;
// pixel <= in_pix;
// sum <= sum + pixel;
// in_col <= index_col + 1;
// in_row <= index_row - 1;
// pixel <= in_pix;
// sum <= sum + in_pix;
// sum <= sum * 0.2;
// in_col <= index_col - 1;
// state <= `DIVISION;
/*
out_row <= index_row;
out_col <= index_col;
out_we <= 1;
out_pix <= pixel;
state <= `INC_INDEX; */
end
end
end
`TOP_PIXEL: begin
index1_row <= index_row + 1;
index1_col <= index_col;
pixel <= in_pix;
sum <= sum + pixel;
if( index_col == 63 && index_row == 63) begin
blur_states <= `LEFT_PIXEL;
end else if( index_col == 63) begin
blur_states <= `BOTTOM_PIXEL;
end else begin
blur_states <= `RIGHT_PIXEL;
end
end
`RIGHT_PIXEL: begin
index1_row <= index_row;
index1_col <= index_col + 1;
pixel <= in_pix;
sum <= sum + pixel;
if( index_row == 63 && index_col == 0) begin
blur_states <= `DIVISION;
end else if(index_row == 63) begin
blur_states <= `LEFT_PIXEL;
end else begin
blur_states <= `BOTTOM_PIXEL;
end
end
`BOTTOM_PIXEL: begin
index1_row <= index_row - 1;
index1_col <= index_col;
pixel <= in_pix;
sum <= sum + pixel;
if (index_col == 0) begin
blur_states <= `DIVISION;
end else begin
blur_states <= `LEFT_PIXEL;
end
end
`LEFT_PIXEL: begin
index1_row <= index_row;
index1_col <= index_col - 1;
pixel <= in_pix;
sum <= sum + pixel;
blur_states<= `DIVISION;
end
`DIVISION: begin
if(sum >= 5) begin
sum <= sum - 5;
pixel_q <= pixel_q + 1;
state <= `DIVISION;
end else begin
out_row <= index_row;
out_col <= index_col;
out_we <= 1;
out_pix <= pixel_q;
state <= `INC_INDEX;
end
end
`INC_INDEX_BLUR: begin
out_we <= 0;
index_col <= index_col + 1;
if( index_col == 63 ) begin
index_row <= index_row + 1;
state <= `MOVE_PIXEL;
end else if (index_row == 63 && index1_row == 63) begin
state <= `DONE;
end else begin
state <= `MOVE_PIXEL;
end
end
`DONE_BLUR: begin
done <= 1;
state <= `INIT_BLUR;
end
endcase
end
if(op == 1) begin // pixelii sunt inversati ca pozitie, pixelii din prima coloana trec in ultima si invers, procedeul se repeta secvential.
state <= `INIT;
case(state)
`INIT: begin
index_row <= 0;
index_col <= 0;
index1_row <= 0;
index1_col <= 63;
timer <= 0;
done <= 0;
state <= `MOVE_PIXEL;
end
`MOVE_PIXEL: begin
in_row <= index1_row;
in_col <= index1_col;
pixel <= in_pix;
if(timer < 6) begin
timer <= timer + 1;
state <=`MOVE_PIXEL;
end else begin
out_row <= index_row;
out_col <= index_col;
out_we <= 1;
out_pix <= pixel;
out_we <= 0;
state <= `INC_INDEX;
end
end
`INC_INDEX: begin
index_col <= index_col + 1;
index1_col <= index1_col - 1;
if( index_col == 63 && index1_col == 0) begin
index_row <= index_row + 1;
index1_row <= index1_row +1;
state <= `MOVE_PIXEL;
end else if (index_row == 63 && index1_row == 63) begin
state <= `DONE;
end else begin
state <= `MOVE_PIXEL;
end
end
`DONE: begin
done <= 1;
state <= `INIT;
end
endcase
end
if(op == 2) begin // liniile devine coloane, se incepe de la ultima linie care se scrie ca prima coloana si se repeta procedeul.
state <= `INIT;
case(state)
`INIT: begin
index_row <= 0;
index_col <= 0;
index1_row <= 63;
index1_col <= 0;
timer <= 0;
done <= 0;
state <= `MOVE_PIXEL;
end
`MOVE_PIXEL: begin
in_row <= index1_row;
in_col <= index1_col;
pixel <= in_pix;
if(timer < 6) begin
timer <= timer + 1;
state <=`MOVE_PIXEL;
end else begin
out_row <= index_row;
out_col <= index_col;
out_we <= 1;
out_pix <= pixel;
out_we <= 0;
state <= `INC_INDEX;
end
end
`INC_INDEX: begin
index_row <= index_row + 1;
index1_col <= index1_col + 1;
if( index_row == 63 && index1_col == 63) begin
index_col <= index_col + 1;
index1_row <= index1_row - 1;
state <= `MOVE_PIXEL;
end else if (index_col == 63 && index1_row == 0) begin
state <= `DONE;
end else begin
state <= `MOVE_PIXEL;
end
end
`DONE: begin
done <= 1;
state <= `INIT;
end
endcase
end
end
endmodule
Sorry to say, but I think you're still conceptually far from a solution, and not really understanding how verilog works.
Taking for an example this small snippet of code:
if(index_row == 0 && index_col == 0) begin
in_row <= index_row + 1;
pixel <= in_pix;
sum <= sum + pixel;
in_row <= index_row - 1;
in_col <= index_col + 1;
pixel <= in_pix;
sum <= sum + pixel;
sum <= sum * 0.2;
in_col <= index_col - 1;
state <= `DIVISION;
This looks as if you took a C algorithm and assumed that you can just replicate it in verilog, but verilog does not work this way. You need to understand that all 10 assignments you have here happen at the same time. That means that you're simultaneously assigning sum <= sum + pixel, sum <= sum - pixel, and sum <= sum * 0.2. The last assignment wins, and the earlier statements are effectively discarded.
Understanding this, looking at your algorithm, many of the statements have no effect, and your code effectively reduces to this:
if(index_row == 0 && index_col == 0) begin
------------------------
------------------------
------------------------
in_row <= index_row - 1;
------------------------
pixel <= in_pix;
------------------------
sum <= sum * 0.2;
in_col <= index_col - 1;
state <= `DIVISION;
So it's no surprise that it doesn't work the way you expect. In general, if you have 10 'C-like' statements that you want to execute in sequence, then you need a 10 stage state machine, and execute one state each clock.

Resources