Multiple nested IIFs - nested

I think I need a nested IIF in SSRS for my goal as written in pseudo code below:
If GoalType.Value = ImplementED And
SavingsGoal.Value <= ImplementEDSavings.Value OR
If GoalType.Value = ImplementABLE And
SavingsGoal.Value <= ImplementABLESavings.Value
Then display zero dollars
ELSE
If GoalType = ImplementED And
SavingsGoal.Value > ImplementEDSavings.value Then
Display SavingsGoal.Value minus ImplementABLESavings
ELSE
If GoalType = ImplementABLE And
SavingsGoal.Value > ImplementABLESavings.Value Then
Display SavingsGoal.Value minus ImplementABLESavings
I've gotten this much to work:
=IIF(First(Fields!GoalType.Value, "Project_Details") = "Implemented" AND
Sum(Fields!SavingsGoal.Value, "Project_Details") <= Sum(Fields!ImplementedSavings.Value, "dsInitiatives") OR
(First(Fields!GoalType.Value, "Project_Details") = "Implementable" AND
Sum(Fields!SavingsGoal.Value, "Project_Details") <= Sum(Fields!ImplementableSavings.Value, "dsInitiatives")),0,
Sum(Fields!SavingsGoal.Value, "Project_Details") - Sum(Fields!ImplementedSavings.Value, "dsInitiatives"))
All I need to to figure out how to get that final "ELSE" in there, realizing I need some more IIFs or Switches or something... I've tried several ways and my deadline is officially tight. Thanks to anyone who can help. Note that I'm really new at SSRS reports.
UPDATE:
Here are a couple of methods that I've tried. I keep getting this error with every try:
error BC30057 Too many arguments to 'Public Function IIf(Expression As Boolean, TruePart As Object, FalsePart As Object) As Object' SSRS
=iif(
(First(Fields!GoalType.Value, "Project_Details") = "Implemented" AND
Sum(Fields!SavingsGoal.Value, "Project_Details") <= Sum(Fields!ImplementedSavings.Value, "dsInitiatives")),0
) OR
iif(
(First(Fields!GoalType.Value, "Project_Details") = "Implementable" AND
Sum(Fields!SavingsGoal.Value, "Project_Details") <= Sum(Fields!ImplementableSavings.Value, "dsInitiatives")),0,
) OR
iif(
(First(Fields!GoalType.Value, "Project_Details") = "Implemented" AND
Sum(Fields!SavingsGoal.Value, "Project_Details") > Sum(Fields!ImplementedSavings.Value, "dsInitiatives")),
Sum(Fields!SavingsGoal.Value, "Project_Details") - Sum(Fields!ImplementedSavings.Value, "dsInitiatives"),
) OR
iif(
(First(Fields!GoalType.Value, "Project_Details") = "Implementable AND
Sum(Fields!SavingsGoal.Value, "Project_Details") > Sum(Fields!ImplementableSavings.Value, "dsInitiatives")),
Sum(Fields!SavingsGoal.Value, "Project_Details") - Sum(Fields!ImplementableSavings.Value, "dsInitiatives")
)
OR
=IIF(First(Fields!GoalType.Value, "Project_Details") = "Implemented" AND
Sum(Fields!SavingsGoal.Value, "Project_Details") <= Sum(Fields!ImplementedSavings.Value, "dsInitiatives") OR
(First(Fields!GoalType.Value, "Project_Details") = "Implementable" AND
Sum(Fields!SavingsGoal.Value, "Project_Details") <= Sum(Fields!ImplementableSavings.Value, "dsInitiatives")),0,
Switch(First(Fields!GoalType.Value, "Project_Details") = "Implemented",
Sum(Fields!SavingsGoal.Value, "Project_Details") - Sum(Fields!ImplementedSavings.Value, "dsInitiatives")
Switch(First(Fields!GoalType.Value, "Project_Details") = "Implementable",
Sum(Fields!SavingsGoal.Value, "Project_Details") - Sum(Fields!ImplementableSavings.Value, "dsInitiatives"))))
personal comment, if these systems wouldn't assume that everyone is a born programmer and give errors that speak English, I wouldn't have to come to these sites for translations. Ok, soapbox over. Thanks again to anyone who can help

Here's a slight modification on your first update.
=iif( (First(Fields!GoalType.Value, "Project_Details") = "Implemented" AND Sum(Fields!SavingsGoal.Value, "Project_Details") <= Sum(Fields!ImplementedSavings.Value, "dsInitiatives")),0,
iif( (First(Fields!GoalType.Value, "Project_Details") = "Implementable" AND Sum(Fields!SavingsGoal.Value, "Project_Details") <= Sum(Fields!ImplementableSavings.Value, "dsInitiatives")),0,
iif( (First(Fields!GoalType.Value, "Project_Details") = "Implemented" AND Sum(Fields!SavingsGoal.Value, "Project_Details") > Sum(Fields!ImplementedSavings.Value, "dsInitiatives")), Sum(Fields!SavingsGoal.Value, "Project_Details") - Sum(Fields!ImplementedSavings.Value, "dsInitiatives"),
iif( (First(Fields!GoalType.Value, "Project_Details") = "Implementable" AND Sum(Fields!SavingsGoal.Value, "Project_Details") > Sum(Fields!ImplementableSavings.Value, "dsInitiatives")), Sum(Fields!SavingsGoal.Value, "Project_Details") - Sum(Fields!ImplementableSavings.Value, "dsInitiatives") )
)))
Instead of using OR's, I've nested the subsequent iif statements in the false argument of the preceding iif. About that error you were getting, "Too many arguements" - you actually had too few.
Here's the first (simplified) block of your code:
=iif( First(GoalType) = "Implemented" AND Sum(SavingsGoal) <= Sum(ImplementedSavings),0 ) OR
Note that you have the Boolean correct, but you only supply a single argument afterwards "0" for the true. The iif needs two arguments, a true and false. In your instance, you want the next iif statement to be in the false (else) portion.
Updated code:
=iif( First(GoalType) = "Implemented" AND Sum(SavingsGoal) <= Sum(ImplementedSavings),0, iif(boolean, true, iif(boolean, true, false)))

Related

Why am I getting an inferring latch error?

I'm trying to create a vending machine in System Verilog using an FSM, and during synthesis, the software warned me with this error:
[Synth 8-327] inferring latch for variable
'FSM_sequential_statoProssimo_reg' ["MacchinettaMerendine.sv":87]
The code is:
...
module FSM_50_Cent (
input logic Clk100_MHz, Reset,
input logic Cent20, Cent50, Euro1, Confirm,
input logic [7:0] Switch50,
output logic Er, r10, r20, r40, r50
);
enum logic [4:0] {S0, S1, S2, S3, S4, S5, S6, S7, S8, S9,
S10, S11, S12, S13, S14, S15, S16, S17} Stati; //STATES
logic [4:0] Stato, statoProssimo; //STATE AND NEXTSTATE
always_ff #(posedge Clk100_MHz, posedge Reset) //FLIP FLOP
begin
if(Reset) Stato <= S0;
else Stato <= statoProssimo;
end
always_comb //NEXT STATE LOGIC
begin
if((|Switch50) == 1)
begin
case(Stato)
S0: if (Cent20) statoProssimo = S1;
else if (Cent50) statoProssimo = S3;
else if (Euro1) statoProssimo = S8;
else if (Confirm) statoProssimo = S0;
S1: if (Cent20) statoProssimo = S2;
else if (Cent50) statoProssimo = S5;
else if (Euro1) statoProssimo = S9;
else if (Confirm) statoProssimo = S1;
S2: if (Cent20) statoProssimo = S4;
else if (Cent50) statoProssimo = S7;
else if (Euro1) statoProssimo = S10;
else if (Confirm) statoProssimo = S2;
S3: if (Confirm) statoProssimo = S0;
S4: if (Confirm) statoProssimo = S0;
S5: if (Confirm) statoProssimo = S0;
S6: if (Confirm) statoProssimo = S0;
S7: if (Confirm) statoProssimo = S0;
S8: if (Confirm) statoProssimo = S0;
S9: if (Confirm) statoProssimo = S0;
S10: if (Confirm) statoProssimo = S0;
default statoProssimo = S0;
endcase
end
end
...
endmodule
...
And the error is on this line: S0: if (Cent20) statoProssimo = S1;
Why?
To avoid a latch, the always_comb block must assign a value to statoProssimo under all conditions.
However, the block does not assign a value to statoProssimo when Switch50 is 0, for example. Therefore, the Verilog simulation will retain the value of statoProssimo. This infers a memory element (a latch).
You could add an else clause and assign a value. For example:
always_comb //NEXT STATE LOGIC
begin
if((|Switch50) == 1)
begin
case(Stato)
...
endcase
end
else statoProssimo = S0;
end
The same applies for each of the case items. You should use an else clause to assign a value.
S0: if (Cent20) statoProssimo = S1;
else if (Cent50) statoProssimo = S3;
else if (Euro1) statoProssimo = S8;
else statoProssimo = S0;
You need to decide what value to assign in each case.
Go through the toolic explanation of answer and see the always_comb section of this code.
module FSM_50_Cent (
input logic Clk100_MHz, Reset,
input logic Cent20, Cent50, Euro1, Confirm,
input logic [7:0] Switch50,
output logic Er, r10, r20, r40, r50
);
typedef enum logic [4:0] {S0, S1, S2, S3, S4, S5, S6, S7, S8, S9,
S10, S11, S12, S13, S14, S15, S16, S17} Stati; //STATES
Stati Stato, statoProssimo; //STATE AND NEXTSTATE
//STATE FLIP FLOPS
always_ff #(posedge Clk100_MHz, posedge Reset)
if(Reset) Stato <= S0;
else Stato <= statoProssimo;
//NEXT STATE LOGIC
always_comb begin
statoProssimo = Stato;
if((|Switch50) == 1)
case(Stato)
S0: if (Cent20) statoProssimo = S1;
else if (Cent50) statoProssimo = S3;
else if (Euro1) statoProssimo = S8;
else if (Confirm) statoProssimo = S0;
S1: if (Cent20) statoProssimo = S2;
else if (Cent50) statoProssimo = S5;
else if (Euro1) statoProssimo = S9;
else if (Confirm) statoProssimo = S1;
S2: if (Cent20) statoProssimo = S4;
else if (Cent50) statoProssimo = S7;
else if (Euro1) statoProssimo = S10;
else if (Confirm) statoProssimo = S2;
S3,S4,
S5,S6,
S7,S8,
S9,S10: if (Confirm) statoProssimo = S0;
default statoProssimo = S0;
endcase
end

$display not working properly in testbench

I am working on 4-bit adder/subtractor (depends on my input). I used 4-bit ripple carry adder method to achieve that. I am testbenching all 4-bit numbers so there is a overflow in some cases. I want the testbench to $display("overflow") whenever the overflow appears as 1 on output. I am attaching the testbench code here.
module yxz;
reg [3:0] A;
reg [3:0] B;
wire [3:0] S;
reg Op;
wire V;
U2_add_sub xyz(.A(A), .B(B), .S(S), .Op(Op), .V(V));
initial begin
Op = 0; // Op = 0 ->adder; Op = 1 ->subtractor
if (V == 1) begin
$display("overflow");
end
A = 4'b0000; B = 4'b0000; #10
A = 4'b0000; B = 4'b0001; #10
A = 4'b0000; B = 4'b0010; #10
A = 4'b0000; B = 4'b0011; #10
A = 4'b0000; B = 4'b0100; #10
A = 4'b0000; B = 4'b0101; #10
A = 4'b0000; B = 4'b0110; #10
A = 4'b0000; B = 4'b0111; #10
A = 4'b0000; B = 4'b1000; #10
A = 4'b0000; B = 4'b1001; #10
A = 4'b0000; B = 4'b1010; #10
A = 4'b0000; B = 4'b1011; #10
A = 4'b0000; B = 4'b1100; #10
A = 4'b0000; B = 4'b1101; #10
A = 4'b0000; B = 4'b1110; #10
A = 4'b0000; B = 4'b1111; #10
A = 4'b0001; B = 4'b0000; #10
A = 4'b0001; B = 4'b0001; #10
A = 4'b0001; B = 4'b0010; #10
A = 4'b0001; B = 4'b0011; #10
A = 4'b0001; B = 4'b0100; #10
A = 4'b0001; B = 4'b0101; #10
A = 4'b0001; B = 4'b0110; #10
A = 4'b0001; B = 4'b0111; #10
A = 4'b0001; B = 4'b1000; #10
A = 4'b0001; B = 4'b1001; #10
A = 4'b0001; B = 4'b1010; #10
A = 4'b0001; B = 4'b1011; #10
A = 4'b0001; B = 4'b1100; #10
A = 4'b0001; B = 4'b1101; #10
A = 4'b0001; B = 4'b1110; #10
A = 4'b0001; B = 4'b1111; #10
A = 4'b0010; B = 4'b0000; #10
A = 4'b0010; B = 4'b0001; #10
A = 4'b0010; B = 4'b0010; #10
A = 4'b0010; B = 4'b0011; #10
A = 4'b0010; B = 4'b0100; #10
A = 4'b0010; B = 4'b0101; #10
A = 4'b0010; B = 4'b0110; #10
A = 4'b0010; B = 4'b0111; #10
A = 4'b0010; B = 4'b1000; #10
A = 4'b0010; B = 4'b1001; #10
A = 4'b0010; B = 4'b1010; #10
A = 4'b0010; B = 4'b1011; #10
A = 4'b0010; B = 4'b1100; #10
A = 4'b0010; B = 4'b1101; #10
A = 4'b0010; B = 4'b1110; #10
A = 4'b0010; B = 4'b1111; #10
A = 4'b0011; B = 4'b0000; #10
A = 4'b0011; B = 4'b0001; #10
A = 4'b0011; B = 4'b0010; #10
A = 4'b0011; B = 4'b0011; #10
A = 4'b0011; B = 4'b0100; #10
A = 4'b0011; B = 4'b0101; #10
A = 4'b0011; B = 4'b0110; #10
A = 4'b0011; B = 4'b0111; #10
A = 4'b0011; B = 4'b1000; #10
A = 4'b0011; B = 4'b1001; #10
A = 4'b0011; B = 4'b1010; #10
A = 4'b0011; B = 4'b1011; #10
A = 4'b0011; B = 4'b1100; #10
A = 4'b0011; B = 4'b1101; #10
A = 4'b0011; B = 4'b1110; #10
A = 4'b0011; B = 4'b1111; #10
A = 4'b0100; B = 4'b0000; #10
A = 4'b0100; B = 4'b0001; #10
A = 4'b0100; B = 4'b0010; #10
A = 4'b0100; B = 4'b0011; #10
A = 4'b0100; B = 4'b0100; #10
A = 4'b0100; B = 4'b0101; #10
A = 4'b0100; B = 4'b0110; #10
A = 4'b0100; B = 4'b0111; #10
A = 4'b0100; B = 4'b1000; #10
A = 4'b0100; B = 4'b1001; #10
A = 4'b0100; B = 4'b1010; #10
A = 4'b0100; B = 4'b1011; #10
A = 4'b0100; B = 4'b1100; #10
A = 4'b0100; B = 4'b1101; #10
A = 4'b0100; B = 4'b1110; #10
A = 4'b0100; B = 4'b1111; #10
A = 4'b0101; B = 4'b0000; #10
A = 4'b0101; B = 4'b0001; #10
A = 4'b0101; B = 4'b0010; #10
A = 4'b0101; B = 4'b0011; #10
A = 4'b0101; B = 4'b0100; #10
A = 4'b0101; B = 4'b0101; #10
A = 4'b0101; B = 4'b0110; #10
A = 4'b0101; B = 4'b0111; #10
A = 4'b0101; B = 4'b1000; #10
A = 4'b0101; B = 4'b1001; #10
A = 4'b0101; B = 4'b1010; #10
A = 4'b0101; B = 4'b1011; #10
A = 4'b0101; B = 4'b1100; #10
A = 4'b0101; B = 4'b1101; #10
A = 4'b0101; B = 4'b1110; #10
A = 4'b0101; B = 4'b1111; #10
A = 4'b0110; B = 4'b0000; #10
A = 4'b0110; B = 4'b0001; #10
A = 4'b0110; B = 4'b0010; #10
A = 4'b0110; B = 4'b0011; #10
A = 4'b0110; B = 4'b0100; #10
A = 4'b0110; B = 4'b0101; #10
A = 4'b0110; B = 4'b0110; #10
A = 4'b0110; B = 4'b0111; #10
A = 4'b0110; B = 4'b1000; #10
A = 4'b0110; B = 4'b1001; #10
A = 4'b0110; B = 4'b1010; #10
A = 4'b0110; B = 4'b1011; #10
A = 4'b0110; B = 4'b1100; #10
A = 4'b0110; B = 4'b1101; #10
A = 4'b0110; B = 4'b1110; #10
A = 4'b0110; B = 4'b1111; #10
A = 4'b0111; B = 4'b0000; #10
A = 4'b0111; B = 4'b0001; #10
A = 4'b0111; B = 4'b0010; #10
A = 4'b0111; B = 4'b0011; #10
A = 4'b0111; B = 4'b0100; #10
A = 4'b0111; B = 4'b0101; #10
A = 4'b0111; B = 4'b0110; #10
A = 4'b0111; B = 4'b0111; #10
A = 4'b0111; B = 4'b1000; #10
A = 4'b0111; B = 4'b1001; #10
A = 4'b0111; B = 4'b1010; #10
A = 4'b0111; B = 4'b1011; #10
A = 4'b0111; B = 4'b1100; #10
A = 4'b0111; B = 4'b1101; #10
A = 4'b0111; B = 4'b1110; #10
A = 4'b0111; B = 4'b1111; #10
A = 4'b1000; B = 4'b0000; #10
A = 4'b1000; B = 4'b0001; #10
A = 4'b1000; B = 4'b0010; #10
A = 4'b1000; B = 4'b0011; #10
A = 4'b1000; B = 4'b0100; #10
A = 4'b1000; B = 4'b0101; #10
A = 4'b1000; B = 4'b0110; #10
A = 4'b1000; B = 4'b0111; #10
A = 4'b1000; B = 4'b1000; #10
A = 4'b1000; B = 4'b1001; #10
A = 4'b1000; B = 4'b1010; #10
A = 4'b1000; B = 4'b1011; #10
A = 4'b1000; B = 4'b1100; #10
A = 4'b1000; B = 4'b1101; #10
A = 4'b1000; B = 4'b1110; #10
A = 4'b1000; B = 4'b1111; #10
A = 4'b1001; B = 4'b0000; #10
A = 4'b1001; B = 4'b0001; #10
A = 4'b1001; B = 4'b0010; #10
A = 4'b1001; B = 4'b0011; #10
A = 4'b1001; B = 4'b0100; #10
A = 4'b1001; B = 4'b0101; #10
A = 4'b1001; B = 4'b0110; #10
A = 4'b1001; B = 4'b0111; #10
A = 4'b1001; B = 4'b1000; #10
A = 4'b1001; B = 4'b1001; #10
A = 4'b1001; B = 4'b1010; #10
A = 4'b1001; B = 4'b1011; #10
A = 4'b1001; B = 4'b1100; #10
A = 4'b1001; B = 4'b1101; #10
A = 4'b1001; B = 4'b1110; #10
A = 4'b1001; B = 4'b1111; #10
A = 4'b1010; B = 4'b0000; #10
A = 4'b1010; B = 4'b0001; #10
A = 4'b1010; B = 4'b0010; #10
A = 4'b1010; B = 4'b0011; #10
A = 4'b1010; B = 4'b0100; #10
A = 4'b1010; B = 4'b0101; #10
A = 4'b1010; B = 4'b0110; #10
A = 4'b1010; B = 4'b0111; #10
A = 4'b1010; B = 4'b1000; #10
A = 4'b1010; B = 4'b1001; #10
A = 4'b1010; B = 4'b1010; #10
A = 4'b1010; B = 4'b1011; #10
A = 4'b1010; B = 4'b1100; #10
A = 4'b1010; B = 4'b1101; #10
A = 4'b1010; B = 4'b1110; #10
A = 4'b1010; B = 4'b1111; #10
A = 4'b1011; B = 4'b0000; #10
A = 4'b1011; B = 4'b0001; #10
A = 4'b1011; B = 4'b0010; #10
A = 4'b1011; B = 4'b0011; #10
A = 4'b1011; B = 4'b0100; #10
A = 4'b1011; B = 4'b0101; #10
A = 4'b1011; B = 4'b0110; #10
A = 4'b1011; B = 4'b0111; #10
A = 4'b1011; B = 4'b1000; #10
A = 4'b1011; B = 4'b1001; #10
A = 4'b1011; B = 4'b1010; #10
A = 4'b1011; B = 4'b1011; #10
A = 4'b1011; B = 4'b1100; #10
A = 4'b1011; B = 4'b1101; #10
A = 4'b1011; B = 4'b1110; #10
A = 4'b1011; B = 4'b1111; #10
A = 4'b1100; B = 4'b0000; #10
A = 4'b1100; B = 4'b0001; #10
A = 4'b1100; B = 4'b0010; #10
A = 4'b1100; B = 4'b0011; #10
A = 4'b1100; B = 4'b0100; #10
A = 4'b1100; B = 4'b0101; #10
A = 4'b1100; B = 4'b0110; #10
A = 4'b1100; B = 4'b0111; #10
A = 4'b1100; B = 4'b1000; #10
A = 4'b1100; B = 4'b1001; #10
A = 4'b1100; B = 4'b1010; #10
A = 4'b1100; B = 4'b1011; #10
A = 4'b1100; B = 4'b1100; #10
A = 4'b1100; B = 4'b1101; #10
A = 4'b1100; B = 4'b1110; #10
A = 4'b1100; B = 4'b1111; #10
A = 4'b1101; B = 4'b0000; #10
A = 4'b1101; B = 4'b0001; #10
A = 4'b1101; B = 4'b0010; #10
A = 4'b1101; B = 4'b0011; #10
A = 4'b1101; B = 4'b0100; #10
A = 4'b1101; B = 4'b0101; #10
A = 4'b1101; B = 4'b0110; #10
A = 4'b1101; B = 4'b0111; #10
A = 4'b1101; B = 4'b1000; #10
A = 4'b1101; B = 4'b1001; #10
A = 4'b1101; B = 4'b1010; #10
A = 4'b1101; B = 4'b1011; #10
A = 4'b1101; B = 4'b1100; #10
A = 4'b1101; B = 4'b1101; #10
A = 4'b1101; B = 4'b1110; #10
A = 4'b1101; B = 4'b1111; #10
A = 4'b1110; B = 4'b0000; #10
A = 4'b1110; B = 4'b0001; #10
A = 4'b1110; B = 4'b0010; #10
A = 4'b1110; B = 4'b0011; #10
A = 4'b1110; B = 4'b0100; #10
A = 4'b1110; B = 4'b0101; #10
A = 4'b1110; B = 4'b0110; #10
A = 4'b1110; B = 4'b0111; #10
A = 4'b1110; B = 4'b1000; #10
A = 4'b1110; B = 4'b1001; #10
A = 4'b1110; B = 4'b1010; #10
A = 4'b1110; B = 4'b1011; #10
A = 4'b1110; B = 4'b1100; #10
A = 4'b1110; B = 4'b1101; #10
A = 4'b1110; B = 4'b1110; #10
A = 4'b1110; B = 4'b1111; #10
A = 4'b1111; B = 4'b0000; #10
A = 4'b1111; B = 4'b0001; #10
A = 4'b1111; B = 4'b0010; #10
A = 4'b1111; B = 4'b0011; #10
A = 4'b1111; B = 4'b0100; #10
A = 4'b1111; B = 4'b0101; #10
A = 4'b1111; B = 4'b0110; #10
A = 4'b1111; B = 4'b0111; #10
A = 4'b1111; B = 4'b1000; #10
A = 4'b1111; B = 4'b1001; #10
A = 4'b1111; B = 4'b1010; #10
A = 4'b1111; B = 4'b1011; #10
A = 4'b1111; B = 4'b1100; #10
A = 4'b1111; B = 4'b1101; #10
A = 4'b1111; B = 4'b1110; #10
A = 4'b1111; B = 4'b1111;
$monitor($time, ": %b + %b = %b, %b", A, B, S, Op, V);
end
endmodule
Your testbench currently only checks if V is 1 at time 0 because the check is done only once in the initial block. Move the code out of the initial block into its own always block:
always #* if (V == 1) $display($time, " overflow");
Every time V changes, the check will be done. I added $time to your message because it is helpful for debugging.
You can simplify your testbench using for loops:
integer i, j;
initial begin
for (i=0; i<16; i=i+1) begin
for (j=0; j<16; j=j+1) begin
A = i;
B = j;
#10;
end
end
end

system verilog HDL - 4bit input logical calculator

I'm trying to design a logical calculator that can plus, multiply, division, ...
but I stuck at 1 part when I try to run it on the DE 10 board it doesn't act as the logic I though
My logic is that when count = 0, the operand A will be at HEX 4,5 and count = 1 DoOpt will be at 2, and count = 2 operand B will display at HEX 1,0, then count will be reset. However when I run it only shows operand B only. can you figure for me what is wrong with my code?
module group_project (
input logic clk, Set, AC,
input logic [3:0] Operand,
input logic [2:0] DoOp,
output logic [6:0] Seg5, Seg4, Seg3, Seg2, Seg1, Seg0
);
logic [1:0] count;
always_ff#(posedge clk) begin
if(!AC) begin
Seg5 = 7'b000_1000;
Seg4 = 7'b000_0110;
Seg3 = 7'b000_1000;
Seg2 = 7'b100_0000;
Seg1 = 7'b001_0001;
Seg0 = 7'b011_1111;
count <= 2'b00;
end
if(!Set && count == 2'b00) begin
count <= count + 1;
Seg3 = 7'b111_1111;
Seg2 = 7'b111_1111;
Seg1 = 7'b111_1111;
Seg0 = 7'b111_1111;
if(Operand < 4'b1010) begin
Seg5 = 7'b100_0000;
case (Operand)
4'b0000: Seg4 = 7'b100_0000;
4'b0001: Seg4 = 7'b111_1001;
4'b0010: Seg4 = 7'b010_0100;
4'b0011: Seg4 = 7'b011_0000;
4'b0100: Seg4 = 7'b001_1001;
4'b0101: Seg4 = 7'b001_0010;
4'b0110: Seg4 = 7'b000_0010;
4'b0111: Seg4 = 7'b111_1000;
4'b1000: Seg4 = 7'b000_0000;
4'b1001: Seg4 = 7'b001_0000;
endcase
end
else begin
Seg5 = 7'b111_1001;
case (Operand)
4'b1010: Seg4 = 7'b100_0000;
4'b1011: Seg4 = 7'b111_1001;
4'b1100: Seg4 = 7'b010_0100;
4'b1101: Seg4 = 7'b011_0000;
4'b1110: Seg4 = 7'b001_1001;
4'b1111: Seg4 = 7'b001_0010;
endcase
end
end
if(!Set && count == 2'b01) begin
count <= count + 1;
Seg5 = 7'b111_1111;
Seg4 = 7'b111_1111;
Seg3 = 7'b111_1111;
Seg1 = 7'b111_1111;
Seg0 = 7'b111_1111;
case(DoOp)
3'b001: Seg2 = 7'b111_1001;
3'b010: Seg2 = 7'b010_0100;
3'b011: Seg2 = 7'b011_0000;
3'b100: Seg2 = 7'b001_1001;
3'b101: Seg2 = 7'b001_0010;
endcase
end
/*else if(!Set && count == 2'b10) begin
Seg5 = 7'b111_1111;
Seg4 = 7'b111_1111;
Seg3 = 7'b111_1111;
Seg2 = 7'b111_1111;
count <= count;
if(Operand < 4'b1010) begin
Seg1 = 7'b100_0000;
case (Operand)
4'b0000: Seg0 = 7'b100_0000;
4'b0001: Seg0 = 7'b111_1001;
4'b0010: Seg0 = 7'b010_0100;
4'b0011: Seg0 = 7'b011_0000;
4'b0100: Seg0 = 7'b001_1001;
4'b0101: Seg0 = 7'b001_0010;
4'b0110: Seg0 = 7'b000_0010;
4'b0111: Seg0 = 7'b111_1000;
4'b1000: Seg0 = 7'b000_0000;
4'b1001: Seg0 = 7'b001_0000;
endcase
end
else begin
Seg1 = 7'b111_1001;
case (Operand)
4'b1010: Seg0 = 7'b100_0000;
4'b1011: Seg0 = 7'b111_1001;
4'b1100: Seg0 = 7'b010_0100;
4'b1101: Seg0 = 7'b011_0000;
4'b1110: Seg0 = 7'b001_1001;
4'b1111: Seg0 = 7'b001_0010;
endcase
end
end
end
endmodule
There's something to do with AC and Set.
If AC is used as initial reset only, and after that Set is constant low, then count will at last stay at 2. It only lasts 1 clk cycle for count = 0 and 1. So as long as clk is fast enough, you'll be unable to notice count = 0 and 1, and only see count = 2 state.
Perhaps you need to deassert AC periodically, and control Set to see the transition of each count state.

trying to write single cycle verilog code?

I am trying to write a single cycle mips verilog code which only contains selected instructions, to pass a simple test, it took two days for me to write below code but I checked instruction per instruction but getting to branch( first branch) instruction I really became desperate( the new pc value doesn't update correctly ).I would be so appreciated by any suggestion from you.
PS: the instructions before first branch are executed correctly.
here is the main code
`timescale 1ns/10ps
// R Format funcs
`define ADDU 6'b100001
`define ADD 6'b100000
`define SUB 6'b100011
`define AND 6'b100100
`define XOR 6'b100110
`define NOR 6'b100111
`define SLT 6'b101010
`define MULT 6'b011000
`define SLTU 6'b101011
`define MULTU 6'b011001
`define JALR 6'b001001
`define JR 6'b001000
`define MFHI 6'b010000
`define MFLO 6'b010010
// I & J Format op
`define ADDI 6'b001000
`define ADDIU 6'b001001
`define ORI 6'b001101
`define XORI 6'b001110
`define ANDI 6'b001100
`define SLTI 6'b001010
`define SLTIU 6'b001011
`define LUI 6'b001111
`define LW 6'b100011
`define SW 6'b101011
`define BEQ 6'b000100
`define BNE 6'b000101
`define J 6'b000010
`define JAL 6'b000011
// ALU OP
`define alu_add 4'b0000
`define alu_sub 4'b0001
`define alu_and 4'b0010
`define alu_or 4'b0011
`define alu_xor 4'b0100
`define alu_nor 4'b0101
`define alu_sltu 4'b0110
`define alu_slt 4'b0111
`define alu_addu 4'b1000
module single_cycle_mips(
input clk,
input reset
);
wire alu_z;
reg [3:0] alu_op;
reg [1:0] aluSrcB ,RegDst ;
reg [2:0] WD_e;
reg [4:0] Regno , flag=0;
reg aluSrcA, SE_ZEn, rf_wrt;
reg pc_wrt, ir_wrt, IorD, mar_wrt ,mult_s ,is_s,mem_wrt;
wire [31:0] rf_rd_1, rf_rd_2, alu_result ,s1,s2,mem_addr,mem_write_data,mem_read_data;
reg [31:0] pc, MemtoReg, ir,mar, aluB , aluA ,A ,B ,HI ,LO;
// CONTROLLER Starts Here
wire [5:0] ir_op = ir[31:26];
wire [5:0] funct = ir[5:0];
always #(ir) begin : MAIN
//nxt_state = 'bx;
alu_op = 'bx; aluSrcB = 'bx; aluSrcA = 'bx; SE_ZEn = 'bx;
rf_wrt = 1'b0; pc_wrt = 1'b0; ir_wrt = 1'b0; WD_e = 'bx;
mem_wrt = 1'b0; mult_s = 'bx; mar_wrt = 1'b0; Regno = 'bx;
is_s = 'bx; RegDst = 'bx ;
IorD = 0;
ir_wrt = 1'b1; // load IR by memory data
//aluSrcA = 1'b0; //
//aluSrcB = 2'b01; //
//alu_op = `alu_addu; //
//pc_wrt = 1'b1; // pc <- pc + 4
pc = pc + 4;
#8
case(ir_op)
6'b000000:begin // R-format
if(funct == `MFHI) begin
WD_e = 3'b010;
rf_wrt = 1'b1;
RegDst = 2'b01;
//nxt_state = FETCH1;
end
else if(funct == `MFHI) begin
WD_e = 3'b011;
rf_wrt = 1'b1;
RegDst = 2'b01;
//nxt_state = FETCH1;
end
else if((funct == `JALR) || (funct== `JR)) begin
A =rf_rd_1;
if(funct == `JALR) begin
rf_wrt = 1'b1;
WD_e = 3'b100;
RegDst = 2'b01;
end
pc = A;
end
else begin
A = rf_rd_1;
B = rf_rd_2;
#3
rf_wrt = 1'b1;
aluSrcA = 1'b1;
aluSrcB = 2'b00;
WD_e = 3'b001;
RegDst = 2'b01;
case(funct[5:0])
`ADD: begin alu_op = `alu_add; end
`ADDU: begin alu_op = `alu_addu; end
`SUB: begin alu_op = `alu_sub; end
`AND: begin alu_op = `alu_and; end
`XOR: begin alu_op = `alu_xor; end
`NOR: begin alu_op = `alu_nor; end
`SLTU: begin alu_op = `alu_sltu; end
`SLT: begin alu_op = `alu_slt; end
`MULT: begin
if(flag <=18 && flag!=0)
flag= flag+1;
else if(flag == 18) begin
HI <= #0.1 s2;
LO <= #0.1 s1;
flag = 0;
end
else if(flag==0) begin
mult_s = 1'b1;
is_s = 1'b1;
end
end
`MULTU: begin
if(flag <=18 && flag!=0)
flag= flag+1;
else if(flag == 18) begin
HI <= #0.1 s2;
LO <= #0.1 s1;
flag = 0;
//nxt_state = FETCH1;
end
else if(flag==0) begin
mult_s = 1'b1;
is_s = 1'b1;
end
end
endcase
end
end
`ADDI ,`ADDIU ,`ORI ,`XORI ,`ANDI ,`SLTI, `SLTIU: // I format
begin
A = rf_rd_1;
#3
rf_wrt = 1'b1;
aluSrcA = 1'b1;
aluSrcB = 2'b10;
WD_e = 3'b001;
RegDst = 2'b00;
case(ir_op)
`ADDI:begin
SE_ZEn =1'b1;
alu_op = `alu_add;
//nxt_state = FETCH1;
end
`ADDIU:begin
SE_ZEn =1'b0;
alu_op = `alu_addu;
//nxt_state = FETCH1;
end
`ANDI:begin
SE_ZEn =1'b1;
alu_op = `alu_and;
//nxt_state = FETCH1;
end
`ORI:begin
SE_ZEn =1'b0;
alu_op = `alu_or;
//nxt_state = FETCH1;
end
`XORI:begin
SE_ZEn =1'b0;
alu_op = `alu_xor;
//nxt_state = FETCH1;
end
`SLTI:begin
SE_ZEn =1'b1;
alu_op = `alu_slt;
//nxt_state = FETCH1;
end
`SLTIU:begin
SE_ZEn =1'b0;
alu_op = `alu_sltu;
//nxt_state = FETCH1;
end
endcase
end
`LUI: begin
WD_e = 3'b101;
rf_wrt = 1'b1;
RegDst = 2'b00;
end
`LW: begin
A = rf_rd_1;
mar_wrt = 1'b1;
aluSrcA = 2'b1;
aluSrcB = 2'b10;
SE_ZEn = 1;
alu_op = `alu_add;
#3
IorD = 1;
#8
rf_wrt = 1'b1;
WD_e = 3'b000;
RegDst = 2'b00;
//nxt_state = FETCH1;
end
`SW: begin
A = rf_rd_1;
B = rf_rd_2;
mar_wrt = 1'b1;
aluSrcA = 1'b1;
aluSrcB = 2'b10;
SE_ZEn =1'b1;
alu_op = `alu_add;
#3
IorD = 1;
ir_wrt = 0;
mem_wrt = 1;
#4 begin IorD = 0; mem_wrt = 0; ir_wrt = 1; end
//disable MAIN;
//nxt_state = FETCH1;
end
`BEQ ,`BNE: begin
A = rf_rd_1;
B = rf_rd_2;
aluSrcA = 1'b1;
aluSrcB = 2'b00;
alu_op = `alu_xor;
#3
if( ((alu_z == 0) && ((ir_op)== `BEQ) ) || ((alu_z == 1) && ((ir_op)== `BNE)))
disable MAIN;
//nxt_state = FETCH1;
else
begin
SE_ZEn =1'b1;
aluSrcA = 1'b0;
aluSrcB = 2'b11;
alu_op = `alu_add;
pc_wrt = 1'b1;
//nxt_state = FETCH1;
end
end
`J: begin
pc = {7'b00000,ir[25:0]};
//nxt_state = FETCH1;
end
`JAL: begin
rf_wrt = 1'b1;
RegDst = 2'b10;
WD_e = 3'b100;
pc = {7'b00000,ir[25:0]};
//nxt_state = FETCH1;
end
endcase
end
// CONTROLLER Ends Here
// DATA PATH Starts Here
always #(posedge clk)
if(reset) begin
pc <= #0.1 32'h00000000;
IorD = 0;
ir_wrt = 1'b1;
end
else if(pc_wrt)
pc <= #0.1 alu_result;
always #(posedge clk) if(ir_wrt) ir <= #0.1 mem_read_data;
always #* if(mar_wrt) mar <= #0.1 alu_result;
assign mem_write_data = B;
assign mem_addr = IorD ? mar : pc;
wire [31:0] SZout = SE_ZEn ? {{16{ir[15]}}, ir[15:0]} : {16'h0000, ir[15:0]};
always #(*) begin
case (aluSrcB)
2'b00: aluB <= B;
2'b01: aluB <= 32'h4;
2'b10: aluB <= SZout;
2'b11: aluB <= SZout << 2;
endcase
case (aluSrcA)
1'b0: aluA = pc;
1'b1: aluA = A;
endcase
case(RegDst)
2'b00: Regno <= ir[20:16];
2'b01: Regno <= ir[15:11];
2'b10: Regno <= 31;
endcase
case(WD_e)
3'b000: MemtoReg <= mem_read_data;
3'b001: MemtoReg <= alu_result;
3'b010: MemtoReg <= HI;
3'b011: MemtoReg <= LO;
3'b100: MemtoReg <= pc;
3'b101: MemtoReg <= {ir[15:0],16'h0000};
endcase
end
my_alu alu(
.aluA(aluA),
.aluB(aluB),
.aluOp(alu_op),
.aluResult(alu_result),
.aluZero(alu_z));
reg_file registers(
.clk(clk),
.write(rf_wrt),
.WR(Regno),
.WD(MemtoReg),
.RR1(ir[25:21]),
.RR2(ir[20:16]),
.RD1(rf_rd_1),
.RD2(rf_rd_2));
async_mem mem(
.clk(clk),
.write(mem_wrt),
.address(mem_addr),
.write_data(mem_write_data),
.read_data(mem_read_data));
multiplier u1(
.clk(clk),
.start(mult_s),
.is_signed(is_s),
.a(A),
.b(B),
.s1(s1),
.s2(s2));
// DATA PATH Ends Here
endmodule
module my_alu(
input [31:0] aluA,
input [31:0] aluB,
input [ 3:0] aluOp,
output reg[31:0] aluResult,
output aluZero
);
always #(*)
case(aluOp)
`alu_add : aluResult <= #2 aluA + aluB;//begin if( aluA[31] == aluB[31]) aluResult <= #2 aluA + aluB;
//else aluResult <= #2 aluA[31] ? ~aluA + aluB + 1'b1 : aluA + ~aluB +1'b1; end // add
`alu_addu : aluResult <= #2 aluA + aluB;
`alu_sub : aluResult <= #2 aluA + ~aluB + 1'b1; // sub
`alu_and : aluResult <= #2 aluA & aluB;
`alu_or : aluResult <= #2 aluA | aluB;
`alu_nor : aluResult <= #2 ~(aluA | aluB); // ?? ~ ( aluA | aluB )
`alu_xor : aluResult <= #2 aluA ^ aluB;
`alu_sltu : aluResult <= #2 aluA < aluB ? 1 : 32'h00000000;
`alu_slt: begin
if( aluA[31]!=aluB[31])begin
if( aluA[31]== 1)
aluResult <= #2 1;
else if( aluA[31]== 0)
aluResult <= #2 32'h00000000;
end
else if( aluA[31]==aluB[31] ) begin
if (aluA[31]== 0)
aluResult <= #2 aluA < aluB ? 1 : 32'h00000000;
else if( aluA[31]== 1)
aluResult <= #2 (~aluA+1'b1) < (~aluB+1'b1) ? 1 : 32'h00000000;
end
end
endcase
assign aluZero = ~ (|aluResult);
endmodule
module async_mem(
input clk,
input write,
input [31:0] address,
input [31:0] write_data,
output [31:0] read_data
);
reg [31:0] mem_data [0:1023];
assign #7 read_data = mem_data[ address[31:2] ];
always #(*)
if(write)
mem_data[ address[31:2] ] <= #2 write_data;
endmodule
module reg_file(
input clk,
input write,
input [4:0] WR,
input [31:0] WD,
input [4:0] RR1,
input [4:0] RR2,
output [31:0] RD1,
output [31:0] RD2
);
reg [31:0] rf_data [0:31];
assign #2 RD1 = rf_data[ RR1 ];
assign #2 RD2 = rf_data[ RR2 ];
always #(*) begin
if(write) begin
rf_data[ WR ] <= #0.1 WD;
`ifdef DEBUG
if(WR)
$display("$%0d = %x", WR, WD);
`endif
end
rf_data[0] <= #0.1 32'h00000000;
end
endmodule
and here is the hex of the test code:
[0x000000] 0x34080000 # ori $t0, $zero, 0 ($t0 = $zero | 0)
[0x000004] 0x24090060 # addiu $t1, $zero, 96 ($t1 = 96)
[0x000008] 0x3403DEAD # ori $v1, $zero, -8531 ($v1 = $zero | -8531)
[0x00000C] 0xAD030080 # sw $v1, 128($t0) (mem[$t0 + 128] = $v1)
[0x000010] 0x2129FFFF # addi $t1, $t1, -1 ($t1 = $t1 + -1)
[0x000014] 0x25080004 # addiu $t0, $t0, 4 ($t0 = $t0 + 4)
[0x000018] 0x00631020 # add $v0, $v1, $v1 ($v0 = $v1 + $v1)
[0x00001C] 0x00621026 # xor $v0, $v1, $v0 ($v0 = $v1 ^ $v0)
[0x000020] 0x3843BEEF # xori $v1, $v0, -16657 ($v1 = $v0 ^ -16657)
[0x000024] 0x1409FFF9 # bne $t1, $zero, -7 (if ($t1 != $zero) goto -7)
[0x000028] 0x20080004 # addi $t0, $zero, 4 ($t0 = 4)
[0x00002C] 0x20090060 # addi $t1, $zero, 96 ($t1 = 96)
[0x000030] 0x01294821 # addu $t1, $t1, $t1 ($t1 = $t1 + $t1)
[0x000034] 0x01294821 # addu $t1, $t1, $t1 ($t1 = $t1 + $t1)
[0x000038] 0x0109502A # slt $t2, $t0, $t1 (if ($t0 < $t1) $t2 = 1 else $t2 = 0)
[0x00003C] 0x1140000E # beq $t2, $zero, 14 (if ($t2 == $zero) goto 14)
[0x000040] 0x00085820 # add $t3, $zero, $t0 ($t3 = $t0)
[0x000044] 0x8D0C0080 # lw $t4, 128($t0) ($t4 = mem[$t0 + 128])
[0x000048] 0x000B502A # slt $t2, $zero, $t3 (if ($zero < $t3) $t2 = 1 else $t2 = 0)
[0x00004C] 0x11400007 # beq $t2, $zero, 7 (if ($t2 == $zero) goto 7)
[0x000050] 0x216DFFFC # addi $t5, $t3, -4 ($t5 = $t3 + -4)
[0x000054] 0x8DAE0080 # lw $t6, 128($t5) ($t6 = mem[$t5 + 128])
[0x000058] 0x01CC502B # sltu $t2, $t6, $t4 (if ($t6 < $t4) $t2 = 1 else $t2 = 0)
[0x00005C] 0x11400003 # beq $t2, $zero, 3 (if ($t2 == $zero) goto 3)
[0x000060] 0xAD6E0080 # sw $t6, 128($t3) (mem[$t3 + 128] = $t6)
[0x000064] 0x000D5820 # add $t3, $zero, $t5 ($t3 = $t5)
[0x000068] 0x1000FFF7 # beq $zero, $zero, -9 (if ($zero == $zero) goto -9)
[0x00006C] 0xAD6C0080 # sw $t4, 128($t3) (mem[$t3 + 128] = $t4)
[0x000070] 0x21080004 # addi $t0, $t0, 4 ($t0 = $t0 + 4)
[0x000074] 0x1000FFF0 # beq $zero, $zero, -16 (if ($zero == $zero) goto -16)
[0x000078] 0x1000FFFF # beq $zero, $zero, -1 (if ($zero == $zero) goto -1)
and here is the test bench:
`timescale 1ns/1ns
module multi_cycle_mips__tb;
reg clk = 1;
always #(clk)
clk <= #20 ~clk; //20
reg reset;
initial begin
reset = 1;
#(posedge clk);
#(posedge clk);
#(posedge clk);
#1;
reset = 0;
end
initial
$readmemh("isort32.hex", uut.mem.mem_data);
parameter end_pc = 32'h7C;
integer i;
always #(uut.pc)
if(uut.pc == end_pc) begin
for(i=0; i<96; i=i+1) begin
$write("%x ", uut.mem.mem_data[32+i]);
if(((i+1) % 16) == 0)
$write("\n");
end
$stop;
end
single_cycle_mips uut(
.clk(clk),
.reset(reset)
);
endmodule

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