I am new to Verilog. I am trying to detect peak to peak voltage of an input signal to ADC on FPGA. Before that I wanted to test a simple but similar code which finds the minimum and maximum of set of 4 bit parallel inputs.
Initially I assigned pk_low
and pk_high
as first input, depending on the upcoming inputs pk_low
and pk_high
should change or stay the same. But in the simulations I see that pk_low
value is always 0. pk_high
and pp_voltage
(peak to peak voltage) are unknown(X).
What is the problem?
module peak_voltage (clk, parallel_in, pk_high, pk_low, pp_voltage);
input clk;
input wire [3:0] parallel_in;
output reg [3:0] pk_high;
output reg [3:0] pk_low;
output wire [3:0] pp_voltage;
reg state;
parameter st0 = 'd0;
parameter st1 = 'd1;
parameter st2 = 'd2;
initial begin
state = st0;
pk_high <= parallel_in;
pk_low <= parallel_in;
end
always @ (posedge clk) begin
if (parallel_in > pk_high)begin
state = st1;
end else if (parallel_in < pk_low) begin
state = st2;
end else begin
state = st0;
end
end
always @(*) begin
case (state)
st0: begin
pk_low <= pk_low;
pk_high <= pk_high;
end
st1: begin
pk_low <= pk_low;
pk_high <= parallel_in;
end
st2: begin
pk_low <= parallel_in;
pk_high <= pk_high;
end
endcase
end
assign pp_voltage = pk_high - pk_low;
endmodule
You have coded this like a state machine, where you should instead have a continuous assignment for your case selector. Assign 3 bits to make a one-hot vector maybe.
You have non-blocking assignments in this logic - you need to use blocking for the combinatorial logic.
You are missing any explicit storage for the peak high/low values. Maybe you could infer some latches in this style, but it would not be clear quite what you meant.
Define some flops, clocked by clk, with non-blocking assignments. Capture the updated results in these every cycle.
Remember that verilog executes all the statements in parallel, you shouldn't be thinking about execution order. Think instead about explicitly capturing your results, and calculating the 'next' values for these results.
You could view your code as:
You have done (1) wrong, and missed (3) altogether. It might make sense to code (1) and (2) together, but that is down to how you want to express the functions.
assign new_level = (in > level) ? in : level;