Reputation: 781
I am trying to Design hardware that will produce the following sequence, F = sum of the first N whole number, that is, 1+2...+N. (e.g. If N=3, F=1+2+3=6). I am implementing a module that whenever its input N changes, it produces F, at latest N clock cycles later. N will be any 4-bit number (meaning that F has to be 7 bits long). N will not change while new a new F is being calculated. Here is my attempt:
module Fib (clock, reset, N, Fib);
input clock, reset; input [3:0] N;
output [6:0] Fib;
reg [6:0] Fib;
// local vars
reg [2:0] Nprev;
reg [2:0] count;
reg state, next_state;
// control lines
reg [1:0] Fmux, Cmux;
//status line
wire zero, equal;
parameter wait4newN=1'b0,
wait4Zero=1'b1;
// Datapath
always@(posedge clock)
case(Fmux)
2'h0 : Fib <= N;
2'h1 : Fib <= Fib + count;
endcase
always@(posedge clock)
case (Cmux)
2'h0 : count <= N-1;
2'h1 : count <= count - 1;
endcase
assign zero = (count == 0);
assign equal = (Nprev==N);
// Controller
always@(posedge clock)
Nprev <= N;
always@(posedge clock)
if (reset) state <= wait4newN;
else
state <= next_state;
always@(*)
begin
Fmux = 0; Cmux = 0;
case (state) // synopsys full_case parallel_case
wait4newN :
if (!equal)
begin
Fmux = 0; Cmux = 0;
next_state=wait4newN;
end
else
begin
Fmux = 1; Cmux = 1;
next_state=wait4Zero;
end
wait4Zero :
if(!zero)
begin
Fmux = 1; Cmux = 1;
next_state = wait4Zero;
end
else
begin
Fmux = 0; Cmux =0;
next_state =wait4newN;
end
default:
$display("why am I here?");
endcase
end
endmodule
My test fixture is
// Testbench
module test;
reg clk, reset;
reg [3:0] N;
reg [6:0] Fib;
// Instantiate device under test
Fib fibInstance(.clock(clk),.reset(reset), .N(N), .Fib(Fib));
initial begin
// Dump waves
$dumpfile("dump.vcd");
$dumpvars(1, test);
clk = 0;
reset = 1;
N = 5;
$display("wait4newN N: %0h, Fib: %0h",
N, Fib);
toggle_clk;
$display("wait4Zero N: %0h, Fib: %0h",
N, Fib);
toggle_clk;
$display("wait4Zero N: %0h, Fib: %0h",
N, Fib);
toggle_clk;
$display("wait4Zero N: %0h, Fib: %0h",
N, Fib);
toggle_clk;
$display("wait4Zero N: %0h, Fib: %0h",
N, Fib);
toggle_clk;
$display("wait4Zero N: %0h, Fib: %0h",
N, Fib);
toggle_clk;
$display("wait4newN N: %0h, Fib: %0h",
N, Fib);
end
task toggle_clk;
begin
#5 clk = ~clk;
#5 clk = ~clk;
end
endtask
endmodule
The result of simulation is XX for F.
[2017-10-21 20:17:23 EDT] iverilog '-Wall' '-g2012' design.sv testbench.sv && unbuffer vvp a.out
VCD info: dumpfile dump.vcd opened for output.
wait4newN N: 5, Fib: xx
wait4Zero N: 5, Fib: xx
wait4Zero N: 5, Fib: xx
wait4Zero N: 5, Fib: xx
wait4Zero N: 5, Fib: xx
wait4Zero N: 5, Fib: xx
wait4newN N: 5, Fib: xx
Done
What am I doing wrong please?
Thank you very much for you time in advance.
Upvotes: 1
Views: 2347
Reputation: 4381
The problem seems due to reset. Here is a plain explanation for what is happening:
In your Fib module, you are not initializing variables on reset. When reset is applied, the state goes from 'X' to 'wait4newN'. Now the combinational block gets triggered on same clock and the case statement is executed. Thereby FMux goes from X->1 directly. As a result the equation "Fib <= Fib + count" always yields 'X' since Fib was never initialized to zero.
Apart from this, you are never deasserting reset to zero from your testbench. So the FSM state never changes.
In the Fib module, use the reset in sequential blocks.
always @(posedge clk) begin // Assuming synchronous reset
if(reset) begin
// Reset variables
end else begin
// other logic
end
end
More information about handling resets is available at this site and Cummings Reset related Paper.
Upvotes: 2