Faulty outputs for JK flip flop state diagram implementation - verilog

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.

Related

Copying register value in Verilog behavioral modelling

I'm working to design encryption module in Verilog using behavioral modelling approach, but i'm stuck in passing register value to Data_out port. I'm making little mistake to copy register p value in Data_out port. Testbench is also attached. expected output of the module should be Data_out = (Data_in + Key) MOD 26. but we can't use % operator because of systhesis issue.
Your answer will be valuable for me.
module encription(Start,Clk,Reset,Data_In, Key,Data_out,Done);
parameter M='d26;
parameter S0=0, S1=1, S2= 2;
input Clk,Reset,Start;
input [4:0] Data_In,Key;
output reg [4:0] Data_out;
output reg Done;
reg [1:0] state;
reg [4:0] p,q,r,s;
always # (posedge Clk)
begin
r <= Data_In;
s <= Key;
end
always # (posedge Clk )
begin
if(Reset=='b0)
begin
Done <= 1'b0;
p <= M;
end
else if (Reset == 'b1)
case (state)
S0:
if (Start) begin
q <= r + s;
state <= S1;
end
S1:
if (p >= q) begin
p <= p - q;
state <= S2;
end
S2:
begin
Data_out <= p;
Done <= 1'b1;
Done <= 1'b0;
end
default:
state <= S0;
endcase
end
endmodule
module Encryption_tb();
reg Clk,Reset,Start;
reg [4:0] Data_In,Key;
wire [4:0] Data_out;
wire [4:0] q;
wire Done;
encription DUT(Start,Clk,Reset,Data_In, Key,Data_out,Done);
initial
begin
Clk = 0;
forever #5 Clk=~Clk;
end
initial
begin
#10 Start = 'b1; Data_In = 'b000111; Key = 'b01110;
#10 Start = 'b1; Data_In = 'b000101; Key = 'b01100;
#10 Start = 'b1; Data_In = 'b000001; Key = 'b00110;
#10 Reset = 'b1; Start = 'b1;
//#10 Reset = 'b0;
#10 Start = 'b1; Data_In = 'b000111; Key = 'b01110;
#10 Start = 'b1; Data_In = 'b000101; Key = 'b01100;
#10 Start = 'b1; Data_In = 'b000001; Key = 'b00110;
#10 $finish;
end
endmodule
This does not need a state machine just some flops.
RTL:
module encription(Start,Clk,Reset,Data_In, Key,Data_out,Done);
parameter M='d26;
parameter S0=0, S1=1, S2= 2;
input Clk,Reset,Start;
input [4:0] Data_In,Key;
output reg [4:0] Data_out;
output reg Done;
reg [6:0] sum;
assign sum = Data_In + Key;
always # (posedge Clk )
begin
if(Reset=='b1)
begin
Data_out <= 0;
Done <= 0;
end
else
begin
if(sum < M)
Data_out <= sum;
else
if(sum < 2*M)
Data_out <= sum - M;
else
Data_out <= sum - 2*M ;
Done <= Start;
end
end
endmodule
Testbench with meaningful vectors:
module Encryption_tb();
reg Clk,Reset,Start;
reg [4:0] Data_In,Key;
wire [4:0] Data_out;
wire [4:0] q;
wire Done;
encription DUT(Start,Clk,Reset,Data_In, Key,Data_out,Done);
initial
begin
Clk = 0;
forever #5 Clk=~Clk;
end
initial
begin :initial_block
$monitor("Data_In = %d,Key = %d, Data_out = %d",Data_In,Key,Data_out);
Reset = 1;
#20 Reset = 0;
#10;
#1;
Start = 1;
for(int i = 0; i < 30; i++)
begin
# (posedge Clk);
#1;
Key = i;
Data_In = i;
end
#10 $finish;
end :initial_block
initial
begin
$dumpfile("dump.vcd");
$dumpvars;
end
endmodule
Some of the outputs (note the answer is delayed by 1 clk because of the flops)
Data_In = 0,Key = 0, Data_out = 0
Data_In = 1,Key = 1, Data_out = 0
Data_In = 1,Key = 1, Data_out = 2
Data_In = 2,Key = 2, Data_out = 2
Data_In = 2,Key = 2, Data_out = 4
Data_In = 3,Key = 3, Data_out = 4
Data_In = 3,Key = 3, Data_out = 6
Data_In = 4,Key = 4, Data_out = 6
Data_In = 4,Key = 4, Data_out = 8
Data_In = 5,Key = 5, Data_out = 8
Data_In = 5,Key = 5, Data_out = 10
Data_In = 6,Key = 6, Data_out = 10
Data_In = 6,Key = 6, Data_out = 12
Data_In = 7,Key = 7, Data_out = 12
Data_In = 7,Key = 7, Data_out = 14
Data_In = 8,Key = 8, Data_out = 14
Data_In = 8,Key = 8, Data_out = 16
Data_In = 9,Key = 9, Data_out = 16
Data_In = 9,Key = 9, Data_out = 18
Data_In = 10,Key = 10, Data_out = 18
Data_In = 10,Key = 10, Data_out = 20
Data_In = 11,Key = 11, Data_out = 20
Data_In = 11,Key = 11, Data_out = 22
Data_In = 12,Key = 12, Data_out = 22
Data_In = 12,Key = 12, Data_out = 24
Data_In = 13,Key = 13, Data_out = 24
Data_In = 13,Key = 13, Data_out = 0
Data_In = 14,Key = 14, Data_out = 0
Data_In = 14,Key = 14, Data_out = 2
Data_In = 15,Key = 15, Data_out = 2
Data_In = 15,Key = 15, Data_out = 4
Data_In = 16,Key = 16, Data_out = 4
Data_In = 16,Key = 16, Data_out = 6
Data_In = 17,Key = 17, Data_out = 6
Data_In = 17,Key = 17, Data_out = 8
Data_In = 18,Key = 18, Data_out = 8
I see a couple issues.
The only way to get out of S1 in your state machine is if "if (p >= q)". If p is already less than Q, you are stuck in that state forever.
In your testbench, you are giving time between starts for your state
machine to run.
A few suggestions:
Better indentation make it easier to see what is inside a code block: Ex:
S1:
if (p >= q) begin
p <= p - q;
state <= S2;
end
In your testbench, instead of using #10 to define the sequence of stimulus, use #(posedge Clk), that way if your clock frequency changes or some other length delay is used in the TB, things will still line up with the clock.
Use #(Done) to wait for results.
I'm also curious, what synthesis tool you are using that doesn't support %?

the simulation output of my JK Flip-Flop just get nothing changed

the following is the jk flip-flop with preset and clear
there's nothing wrong after compiling. But after simulation, I just find out that my output (QA, QB, QC, QD) just keep to be 0 and unchanged.
is there any thing wrong with my case statement?
or I use the negedge in the wrong way?
module one(inputA, inputB, R01, R02, R91, R92, QA, QB, QC, QD);
input inputA, inputB, R01, R02, R91, R92;
output QA, QB, QC, QD;
reg qa = 1'b0, qb = 1'b0, qc = 1'b0, qd = 1'b0;
reg r0, r9, pre1, clr1, clr2, clr3, pre4, clr4, j2, j4, k4;
//your code~~
initial begin
r0 = ~(R01 & R02);
r9 = ~(R91 & R92);
end
always #(negedge inputA) begin
pre1 = r0;
clr1 = r9;
case({pre1, clr1})
2'b01 : qa = 1'b1;
2'b10 : qa = 1'b0;
2'b11 : qa = ~qa;//toggle is the original result of jk
endcase//jk1
end
always #(negedge inputB) begin
j2 = ~qd;
clr2 = ~(r0 | r9);
if (j2 == 0 && clr2 == 0) qb = 0;//clr=0 means must clear it
if (j2 == 1 && clr2 == 0) qb = 0;//clr=0 means must clear it
if (j2 == 1 && clr2 == 1) qb = ~qb;//toggle
//jk2
end
always #(negedge qb) begin
qc = ~qc;
clr3 = ~(r0 | r9);
if (clr3 == 0) qc = 0;//clr=0 means must clear it
else qc = ~qc;
//jk3
end
always #(negedge inputB) begin
j4 = qb & qc;
case({j4, k4, pre4, clr4})
4'b0011 : qd = qd; //HOLD
4'b0001 : qd = 1'b1; //PRESET
4'b0010 : qd = 1'b0; //CLEAR
4'b1011 : qd = 1'b1; //SET
4'b1001 : qd = 1'b1; //PRESET
4'b1010 : qd = 1'b0; //CLEAR
4'b0111 : qd = 1'b0; //RESET
4'b0101 : qd = 1'b1; //PRESET
4'b0110 : qd = 1'b0; //CLEAR
4'b1111 : qd = ~qd; //TOGGLE
4'b1101 : qd = 1'b1; //PRESET
4'b1110 : qd = 1'b0; //CLEAR
endcase
//jk4
end
begin
assign QA = qa;
assign QB = qb;
assign QC = qc;
assign QD = qd;
end
endmodule
and below is the testbench
module one_tb;
reg clk, r0, r9;
wire [3:0] Q;
one test (.inputA(clk), .inputB(Q[0]), .R01(r0), .R02(r0), .R91(r9), .R92(r9), .QA(Q[0]), .QB(Q[1]), .QC(Q[2]), .QD(Q[3]));
always
#5 clk=~clk;
initial
begin
clk=1'b0;
//0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,0,1,2,3,9,0,1,2,3,4,5,6,7,8
r0 = 1'b1; r9 = 1'b0; #3 ;r0 = 1'b0; r9 = 1'b0; #157;
r0 = 1'b1; r9 = 1'b0; #3 ;r0 = 1'b0; r9 = 1'b0; #37;
r0 = 1'b0; r9 = 1'b1; #3; r0 = 1'b0; r9 = 1'b0; #97;
$stop;
end
endmodule
I changed the JK-FF as modules instantiations, and now it works as intended:
module jk_ff_example (/*AUTOARG*/
// Outputs
QA, QB, QC, QD,
// Inputs
inputA, inputB, R01, R02, R91, R92
);
//..ports
input inputA, inputB, R01, R02, R91, R92;
output QA, QB, QC, QD;
//..regs and wires declaration
wire qa, qna, qb, qnb, qc, qnc, qd, qnd;
wire r0, r9;
//..r0 and r9 inputs comb logic
assign r0 = ~(R01 & R02);
assign r9 = ~(R91 & R92);
//..qa jk-ff logic
jk_ff qa_ff (
.preset_i (r9),
.clear_i (r0),
.clk_i (inputA),
.j_i (1'b1),
.k_i (1'b1),
.q_o (qa),
.qn_o (qna)
);
//..qb jk-ff logic
jk_ff qb_ff (
.preset_i (1'b1),
.clear_i (r0 | r9),
.clk_i (inputB),
.j_i (qnd),
.k_i (1'b1),
.q_o (qb),
.qn_o (qnb)
);
//..qc jk-ff logic
jk_ff qc_ff (
.preset_i (1'b1),
.clear_i (r0 | r9),
.clk_i (qb),
.j_i (1'b1),
.k_i (1'b1),
.q_o (qc),
.qn_o (qnc)
);
//..qd jk-ff logic
jk_ff qd_ff (
.preset_i (r9),
.clear_i (r0),
.clk_i (inputB),
.j_i (qb & qc),
.k_i (qd),
.q_o (qd),
.qn_o (qnd)
);
assign QA = qa;
assign QB = qb;
assign QC = qc;
assign QD = qd;
endmodule // jk_ff_example
Here is the code of a JK-FF with Preset and Clear active-low inputs:
/*
* JK-Flip Flop with Preset and Clear inputs Truth Table
* Preset, Clear and CLK with active-low logic
*
* -------------------------------------------------------------
* | Preset | Clear | CLK | J | K | Output | Qo | ~Qo |
* -------------------------------------------------------------
* | 0 | 0 | x | x | x | Invalid | 1* | 0* |
* | 0 | 1 | x | x | x | Preset | 1 | 0 |
* | 1 | 0 | x | x | x | Clear | 0 | 1 |
* | 1 | 1 | x | x | x | No change | Qo | ~Qo |
* | 1 | 1 | NEG | 0 | 0 | No change | Qo | ~Qo |
* | 1 | 1 | NEG | 0 | 1 | Reset | 0 | 1 |
* | 1 | 1 | NEG | 1 | 0 | Set | 1 | 0 |
* | 1 | 1 | NEG | 1 | 1 | Toggle | ~Qo | Qo |
* -------------------------------------------------------------
*/
module jk_ff (/*AUTOARG*/
// Outputs
q_o, qn_o,
// Inputs
preset_i, clear_i, clk_i, j_i, k_i
);
//..ports
input preset_i, clear_i, clk_i, j_i, k_i;
output q_o, qn_o;
//..regs and wires
reg q = 0;
//..jk ff w/ preset and clear logic
always # (negedge preset_i, negedge clear_i, negedge clk_i) begin
case({preset_i, clear_i})
2'b00: q <= 0; //..invalid
2'b01: q <= 1; //..preset
2'b10: q <= 0; //..clear
2'b11: begin
if(clk_i) //..no change
q <= q;
else begin
case({j_i, k_i})
2'b00: q <= q; //..no change
2'b01: q <= 0; //..reset
2'b10: q <= 1; //..set
2'b11: q <= ~q; //..toggle
endcase
end
end
endcase
end
//..output assignment
assign q_o = q;
assign qn_o = ~q;
endmodule // jk_ff
The output of the simulation is this:
[Cycle: 0] [Q value: 0]
[Cycle: 10] [Q value: 1]
[Cycle: 20] [Q value: 2]
[Cycle: 30] [Q value: 3]
[Cycle: 40] [Q value: 4]
[Cycle: 50] [Q value: 5]
[Cycle: 60] [Q value: 6]
[Cycle: 70] [Q value: 7]
[Cycle: 80] [Q value: 8]
[Cycle: 90] [Q value: 9]
[Cycle: 100] [Q value: 0]
[Cycle: 110] [Q value: 1]
[Cycle: 120] [Q value: 2]
[Cycle: 130] [Q value: 3]
[Cycle: 140] [Q value: 4]
[Cycle: 150] [Q value: 5]
[Cycle: 160] [Q value: 6]
[Cycle: 170] [Q value: 7]
[Cycle: 180] [Q value: 8]
[Cycle: 190] [Q value: 9]
[Cycle: 200] [Q value: 9]
[Cycle: 210] [Q value: 0]
[Cycle: 220] [Q value: 1]
[Cycle: 230] [Q value: 2]
[Cycle: 240] [Q value: 3]
[Cycle: 250] [Q value: 4]
[Cycle: 260] [Q value: 5]
[Cycle: 270] [Q value: 6]
[Cycle: 280] [Q value: 7]
[Cycle: 290] [Q value: 8]
End simulation
[Cycle: 300] [Q value: 9]
I have uploaded this as an example in this repository, I've included a Makefile in order to ease the simulation and FPGA synthesis, feel free to use it.
now I find out why my QB, QC, QD remain 0.
the function of preset and clear is depend on the r0, r9 rather than the inputA, inputB I typed.
after i changed my code to the following, the result looks well:
module one(inputA, inputB, R01, R02, R91, R92, QA, QB, QC, QD);
input inputA, inputB, R01, R02, R91, R92;
output QA, QB, QC, QD;
reg qa = 1'b0, qb = 1'b0, qc = 1'b0, qd = 1'b0;
reg r0, r9, pre1, clr1, clr2, clr3, j2, j4, k4;
always#(*) begin
r0 = ~(R01 & R02);
r9 = ~(R91 & R92);
clr2 = r0 | r9;
clr3 = r0 | r9;
end
always #(negedge inputA) begin
qa = ~qa;
//jk1
end
always #(negedge inputB) begin
j2 = ~qd;
if (j2 == 0 ) qb = 0;
if (j2 == 1 ) qb = ~qb;
//jk2
end
always #(negedge qb) begin
qc = ~qc;
//jk3
end
always #(negedge inputB) begin
j4 = qb & qc;
k4 = qd;
case({j4, k4})
2'b01 : qd = 1'b0;//reset
2'b10 : qd = 1'b1;//set
2'b00 : qd = qd;//hold
2'b11 : qd = ~qd;//toggle
endcase
//jk4
end
always #(negedge r9)begin
qa = 1'b1;
//preset of jk1
end
always #(negedge r0)begin
qa = 1'b0;
//clear of jk1
end
always #(negedge clr2)begin
qa = 1'b0;
//clear of jk2
end
always #(negedge clr3)begin
qa = 1'b0;
//clear of jk3
end
always #(negedge r9)begin
qa = 1'b1;
//preset of jk4
end
always #(negedge r0)begin
qa = 1'b0;
//clear of jk4
end
begin
assign QA = qa;
assign QB = qb;
assign QC = qc;
assign QD = qd;
end
endmodule
r0 and r9 are always unknown in simulation (X) because you only assigned them to values once at time 0.
You probably meant to change them every time the "R" signals change.
Change:
initial begin
r0 = ~(R01 & R02);
r9 = ~(R91 & R92);
end
to:
always #* begin
r0 = ~(R01 & R02);
r9 = ~(R91 & R92);
end
Doing so resolves the X's and allows the QA output to toggle.

Verilog Full Adder Unexpected Behavior

I am trying to do a very basic hardware module/test bench to get the hang of Verilog. I have tried to implement a full adder.
If I am not mistaken, you have three input, immediate addends a and b and a carry in from the 2^n-1 place.
The outputs are sum and carry out (which might serve as a carry in to another module in a basic adder or whatever the not carry-lookahead is called.)
If I am not mistaken the output logic is
sum = (a&b) | (a&cin) | (b&cin) //or all three, which is covered by any of these
cout = a ^ b ^ cin
Here is the full adder module
module FullAdder(
a,
b,
cin,
sum,
co
);
input a;
input b;
input cin;
output sum;
output co;
//wire a;
//wire b;
//wire ci;
wire sum;
wire co;
//At least two
assign co = (a & b) | (a & cin) | (b & cin);
//one or three
assign sum = a ^ b ^ cin; //(a & ~b & ~cin) | (~a & b & ~cin) | (~a & ~b & cin) | (a & b & cin);
endmodule
And here is the test bench
module HalfAdderTB();
reg a_in;
reg b_in;
reg cin_in;
wire s_out;
wire cout_out;
FullAdder DUT(
a_in,
b_in,
cin_in,
s_out,
cout_out
);
initial begin
a_in = 1'b0;
b_in = 1'b0;
cin_in = 1'b0;
#20
a_in = 1'b0;
b_in = 1'b0;
cin_in = 1'b0;
$display("a: %d, b: %d, cin: %d", a_in, b_in, cin_in);
$display("s: %b, cout: %b", s_out, cout_out);
#20
a_in = 1'b0;
b_in = 1'b0;
cin_in = 1'b1;
$display("a: %d, b: %d, cin: %d", a_in, b_in, cin_in);
$display("s: %b, cout: %b", s_out, cout_out);
#20
a_in = 1'b0;
b_in = 1'b1;
cin_in = 1'b0;
$display("a: %d, b: %d, cin: %d", a_in, b_in, cin_in);
$display("s: %b, cout: %b", s_out, cout_out);
#20
a_in = 1'b0;
b_in = 1'b1;
cin_in = 1'b1;
$display("a: %d, b: %d, cin: %d", a_in, b_in, cin_in);
$display("s: %b, cout: %b", s_out, cout_out);
#20
a_in = 1'b1;
b_in = 1'b0;
cin_in = 1'b0;
$display("a: %d, b: %d, cin: %d", a_in, b_in, cin_in);
$display("s: %b, cout: %b", s_out, cout_out);
#20
a_in = 1'b1;
b_in = 1'b0;
cin_in = 1'b1;
$display("a: %d, b: %d, cin: %d", a_in, b_in, cin_in);
2,1 4%
a_in = 1'b1;
b_in = 1'b1;
cin_in = 1'b0;
$display("a: %d, b: %d, cin: %d", a_in, b_in, cin_in);
$display("s: %b, cout: %b", s_out, cout_out);
#20
assign a_in = 1'b1;
assign b_in = 1'b1;
assign cin_in = 1'b1;
$display("a: %d, b: %d, cin: %d", a_in, b_in, cin_in);
$display("s: %b, cout: %b", s_out, cout_out);
#20
$finish;
end
endmodule
My output looks like this
a: 0, b: 0, cin: 0
s: 0, cout: 0
a: 0, b: 0, cin: 1
s: 0, cout: 0
a: 0, b: 1, cin: 0
s: 1, cout: 0
a: 0, b: 1, cin: 1
s: 1, cout: 0
a: 1, b: 0, cin: 0
s: 0, cout: 1
a: 1, b: 0, cin: 1
s: 1, cout: 0
a: 1, b: 1, cin: 0
s: 0, cout: 1
a: 1, b: 1, cin: 1
s: 0, cout: 1
I believe the logic statements in my code match those of the boolean equations I wrote up top. I am confident in my logic. I cannot seem to figure out what is wrong with the Verilog. Have I missed something with the timing and input of the test bench to the Full Adder?
Your code is fine, but you are getting this strange result due to $display statement. Your code will work fine, if you use $strobe instead of $display. You could also use $monitor to display the results. The reson is that display statement executes immediately so that your outputs will not yet be updated with the new values, whereas strobe will execute only at the end of a time instant, so that your outputs would have been updated by then. monitor is used to automatically display values, whenever the values see a change.
Since you are just starting on verilog, I would suggest you to go through this link to understand how various display statements work in verilog and also to go through this link to understand the order of execution of statements in a particular time instant, so that you can plan your code better

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