Verilog: conditional branching - verilog

I want iState (the 2nd bar from the bottom) to be 0 on the rising edge of the clock (the bar at the very top) and when its current value is 1110 (provided that iSkip and iRev are both 0) or when 1010 (provided that iSkip is 1 and iRev are both 0). However, its going to 1111 instead. Does anyone know why this is happening and what I should do about it? Thanks.
Does anyone know what I should do about this? Thanks.
module CounterSkipReverse(iClk, iRst, iSkip, iRev, oState);
input iClk, iRst, iSkip, iRev;
//declare oState:
output integer oState;
//declare internal wires and reg types here:
always # (posedge iClk) begin
if (iRst == 1)
oState <= 0;
else
if (iSkip == 0 & iRev == 0) oState <= oState + 4'd1;
else if (iSkip == 1 & iRev == 0) oState <= oState + 4'd5;
else if (iSkip == 0 & iRev == 1) oState <= oState - 4'd1;
else if (iSkip == 1 & iRev == 1) oState <= oState + 4'd9;
if (oState < 0) oState <= oState + 4'd14;
if (oState > 14) oState <= oState - 4'd14;
end
endmodule
module StateToCountSequence(iState, oV);
//declare the input and output
input iState;
output reg [3:0]oV;
//declare any internal wire and reg types here.
always # (iState) begin
case(iState)
4'd0: oV = 4'd3;
4'd1: oV = 4'd2;
4'd2: oV = 4'd4;
4'd3: oV = 4'd9;
4'd4: oV = 4'd9;
4'd5: oV = 4'd0;
4'd6: oV = 4'd7;
4'd7: oV = 4'd1;
4'd8: oV = 4'd1;
4'd9: oV = 4'd5;
4'd10: oV = 4'd1;
4'd11: oV = 4'd7;
4'd12: oV = 4'd0;
4'd13: oV = 4'd8;
4'd14: oV = 4'd9;
endcase
end
//Have you checked for inferred latches in this module?
endmodule
module CompleteCounter(iClk, iRst, iSkip, iRev, oV, oState);
input iClk, iRst, iSkip, iRev;
output [3:0] oV;
//declare oState next line
output [3:0]oState;
CounterSkipReverse cntr(.iClk(iClk), .iRst(iRst), .iSkip(iSkip), .iRev(iRev), .oState(oState));
StateToCountSequence statemap(.iState(oState), .oV(oV));
endmodule
`timescale 1ns / 1ps
module AssignmentTestBench;
//declare internal signals and instantiate module CompleteCounter.
reg iClk, iRst, iSkip, iRev;
wire [3:0]oState;
wire [3:0]oV;
initial begin
iClk = 1'b1;
iRst = 0;
iSkip = 0;
iRev = 0;
end
CompleteCounter counter(iClk, iRst, iSkip, iRev, oV, oState);
//generate test sequences for all state transitions
always begin
#5 iClk = ~iClk; //period 10 ns for clock
end
always begin // control w input and reset
#1;
// iSkip = 0, iRev = 0
#10 iRst = 1'b1;
#10 iRst = 1'b0;
#300; // 30 clock cycles
// iSkip = 1, iRev = 0
#10 iRst = 1'b1;
#10 iRst = 1'b0;
iSkip = 1'b1;
#80;
// iSkip = 1, iRev = 1
#10 iRst = 1'b1;
#10 iRst = 1'b0;
iRev = 1'b1;
#40;
// iSkip = 0, iRev = 1
#10 iRst = 1'b1;
#10 iRst = 1'b0;
iSkip = 1'b0;
#150;
$display("Finished test");
$finish; // remove for modelsim
$stop;
end
endmodule

The way the <= work is to assign the value to the oState later, after the block is done. So, in the following while oState is scheduled to be 15, the if statement still sees it as 14.
oState <= oState + 1;
...
if (oState > 14) ...
As minimum, you need if(oState >= 14);
also, in the following statement
if (oState > 14) oState <= oState - 4'd14;
if oState is really bigger than 14, i.e. 15, then 15 - 14 = 1;
you probably need
if (oState > 14) oState <= 0;
You need to figure out the other side of the expression as well. The problem is that if (oState <= 0) will give you a trouble in combination with ostate <= 0. You probably need something like the following there: if (iSkip == 0 && iRev == 1 && oState <= 0)
A few more issues:
BToState is integer in CounterSkipReverse which is 32 bit wide signed. istate on the other hand is a one-bit wide input in StateToCountSequence. You need to make all of them of the same width. Your case statement will not work with 1-bit iState.
In addition, do not use singel & in conditional statements. use `&&. Though it does not matter in your case, it really matters in my suggestion which i provided above.
Do not use always #(iState), use always #*.

Related

FPGA Basys 3 State Machine Logic with PMOD ALS Sensor

For a lab I must create the logic to use on a Digilent PMOD ALS. In the lab requirenment I cannot use the sclk signal on the sensitivity list and therefore use a state machine to create the 2.5 MHz clk signal to send to the PMOD ALS. See the code below:
module sens_interface(
input clk, //clk 10Mhz
input reset_n,
input [15:0] delay,
input datain,
output reg sclk,
output reg cs_n,
output reg [3:0] Cout,
output reg [3:0] Dout,
output reg [5:0] cnt
);
//params
//state machine 1
parameter SA0 = 3'b000;
parameter SA1 = 3'b001;
parameter SA2 = 3'b010;
parameter SA3 = 3'b011;
parameter SD0 = 3'b100;
parameter SD1 = 3'b101;
//state machine 2
parameter SR0 = 2'b00;
parameter SR1 = 2'b01;
parameter SR2 = 2'b10;
parameter SR3 = 2'b11;
//pmod als registers
//reg sclk; //2.5Mhz clk
//reg cs_n; //
reg [14:0] data_reg;
//count registers
//reg [5:0] cnt;
reg [15:0] cnt_d;
reg [5:0] cnt_r;
//state registers
reg [2:0] state_sclk;
reg [1:0] state_data;
//State Machine 1
always # (posedge clk)begin
if(reset_n == 1'b0)begin
cs_n <= 1'b1;
sclk <= 0;
cnt <= 6'd0;
cnt_d <= 16'd0;
end
else
case(state_sclk)
SA0:begin
sclk <= 1'b1;
state_sclk <= SA1;
if (cnt <= 6'd17)
cs_n <= 1'b0;
else
cs_n <= 1'b1;
end
SA1:begin
state_sclk <= SA2;
end
SA2:begin
sclk <= 1'b0;
cnt <= cnt + 1;
state_sclk <= SA3;
end
SA3:begin
if(cnt == 6'd21)begin
cnt <= 0;
state_sclk <= SD0;
end
else
state_sclk <= SA0;
end
SD0:begin
cnt_d <= delay;
state_sclk <= SD1;
end
SD1:begin
if (cnt_d == 0)
state_sclk <= SA0;
else
cnt_d <= cnt_d - 1;
end
default:begin
state_sclk <= SA0;
end
endcase
end
always # (posedge clk)begin
if (reset_n == 1'b0)begin
cnt_r <= 0;
data_reg <= 0;
end
else begin
case (state_data)
SR0:begin
if (cs_n == 1'b1 && sclk == 1'b1)
state_data <= SR1;
end
SR1: begin
if (cs_n == 1'b1)begin
state_data <= SR0;
cnt_r <= 0;
end
else if (sclk == 1'b0)
state_data <= SR2;
end
SR2:begin
if (cs_n == 1'b1)begin
state_data <= SR0;
cnt_r <= 0;
end
else if (cnt_r == 15)
state_data <= SR3;
else if (sclk == 1'b1)begin
data_reg [14-cnt_r] <= datain;
cnt_r <= cnt_r + 1;
state_data <= SR1;
end
end
SR3:begin
if (cs_n == 1) begin
Cout <= data_reg [11:8];
Dout <= data_reg [7:4];
state_data <= SR0;
end
end
default:begin
state_data <= SR0;
end
endcase
end
end
endmodule
I tried to make a simulation of it and the simulation indicates that after my cnt register reaches 15 it just cuts out and goes to 0.
simulation
That behavior is caused by your SA3 state.
SA3:begin
if(cnt == 6'd21)begin
cnt <= 0;
state_sclk <= SD0;
end
else
state_sclk <= SA0;
end
end
When your cnt == 6'd21 (which is 6'h15) the cnt is set to zero.
The generic variable names and lack of comments makes it difficult to see why this is not the expected behavior.

Case statement doesn't seem to be working

The value of oV should be the value on the right side in the StateToCountSequence that corresponds to the respective iState value on the left. However, oV only seems to be able to have the values 2 or 3, as shown the in capture below.
Does anyone know what I should do about this?
module CounterSkipReverse(iClk, iRst, iSkip, iRev, oState);
input iClk, iRst, iSkip, iRev;
//declare oState:
output integer oState;
//declare internal wires and reg types here:
always # (posedge iClk) begin
if (iRst == 1)
oState <= 0;
else
if (iSkip == 0 & iRev == 0) oState <= oState + 4'd1;
else if (iSkip == 1 & iRev == 0) oState <= oState + 4'd5;
else if (iSkip == 0 & iRev == 1) oState <= oState - 4'd1;
else if (iSkip == 1 & iRev == 1) oState <= oState + 4'd9;
if (oState < 0) oState <= oState + 4'd14;
if (oState > 14) oState <= oState - 4'd14;
end
endmodule
module StateToCountSequence(iState, oV);
//declare the input and output
input iState;
output reg [3:0]oV;
//declare any internal wire and reg types here.
always # (iState) begin
case(iState)
4'd0: oV = 4'd3;
4'd1: oV = 4'd2;
4'd2: oV = 4'd4;
4'd3: oV = 4'd9;
4'd4: oV = 4'd9;
4'd5: oV = 4'd0;
4'd6: oV = 4'd7;
4'd7: oV = 4'd1;
4'd8: oV = 4'd1;
4'd9: oV = 4'd5;
4'd10: oV = 4'd1;
4'd11: oV = 4'd7;
4'd12: oV = 4'd0;
4'd13: oV = 4'd8;
4'd14: oV = 4'd9;
endcase
end
//Have you checked for inferred latches in this module?
endmodule
module CompleteCounter(iClk, iRst, iSkip, iRev, oV, oState);
input iClk, iRst, iSkip, iRev;
output [3:0] oV;
//declare oState next line
output [3:0]oState;
CounterSkipReverse cntr(.iClk(iClk), .iRst(iRst), .iSkip(iSkip), .iRev(iRev), .oState(oState));
StateToCountSequence statemap(.iState(oState), .oV(oV));
endmodule
`timescale 1ns / 1ps
module AssignmentTestBench;
//declare internal signals and instantiate module CompleteCounter.
reg iClk, iRst, iSkip, iRev;
wire [3:0]oState;
wire [3:0]oV;
initial begin
iClk = 1'b1;
iRst = 0;
iSkip = 0;
iRev = 0;
end
CompleteCounter counter(iClk, iRst, iSkip, iRev, oV, oState);
//generate test sequences for all state transitions
always begin
#5 iClk = ~iClk; //period 10 ns for clock
end
always begin // control w input and reset
#1;
// iSkip = 0, iRev = 0
#10 iRst = 1'b1;
#10 iRst = 1'b0;
#300; // 30 clock cycles
// iSkip = 1, iRev = 0
#10 iRst = 1'b1;
#10 iRst = 1'b0;
iSkip = 1'b1;
#80;
// iSkip = 1, iRev = 1
#10 iRst = 1'b1;
#10 iRst = 1'b0;
iRev = 1'b1;
#40;
// iSkip = 0, iRev = 1
#10 iRst = 1'b1;
#10 iRst = 1'b0;
iSkip = 1'b0;
#150;
$display("Finished test");
$finish; // remove for modelsim
$stop;
end
endmodule
The signal iState is a 1-bit signal in the StateToCountSequence, which means it can only take on the known values 0 and 1. Thus, you can only set oV to 3 and 2.
Change:
input iState;
to:
input [3:0] iState;

Verilog not fully reading the file

I am trying to read the input from the file, and it is not reading the file fully. If there are 100 entries, it will only read 99. Here is the file and code. Any help would be appreciated. How do I know it? It is basically the sum of hit_count and miss_count should be the total number of input in the file and that is what is missing by 1.
module cache_memory_direct_mapped(input clk,
input reset,
input [3:0]read_addr,
output reg hit,
output reg miss,
output reg [7:0]hit_count,
output reg [7:0]miss_count);
reg [1:0]c1[3:0];
initial
begin
hit_count =8'h00;
miss_count = 8'h00;
end
always #(posedge clk, posedge reset)
begin
if(reset)
begin
c1[0] <= 2'hx;
c1[1] <= 2'hx;
c1[2] <= 2'hx;
c1[3] <= 2'hx;
end
else
begin
if(read_addr[3:2] == c1[0] || read_addr[3:2] == c1[1] || read_addr[3:2] == c1[2] || read_addr[3:2]
== c1[3])
begin
hit <= 1;
hit_count <= hit_count + 1;
miss <= 0;
end
else
begin
hit <= 0;
miss <= 1;
miss_count <= miss_count + 1;
if(read_addr[1:0] == 2'b0 )
c1[0] <= read_addr[3:2];
else if(read_addr[1:0] == 2'b1 )
c1[1] <= read_addr[3:2];
else if(read_addr[1:0] == 2'b10 )
c1[2] <= read_addr[3:2];
else if(read_addr[1:0] == 2'b11 )
c1[3] <= read_addr[3:2];
end
end
end
endmodule
module Tb_direct_mapped;
// Inputs
reg clk;
reg reset;
reg [3:0] read_addr;
// Outputs
wire hit;
wire miss;
wire [7:0]hit_count;
wire [7:0]miss_count;
integer data_file ; // file handler
integer scan_file ; // file handler
reg [4:0]captured_data;
// Instantiate the Unit Under Test (UUT)
cache_memory_direct_mapped uut (
.clk(clk),
.reset(reset),
.read_addr(read_addr),
.hit(hit),
.miss(miss),
.hit_count(hit_count),
.miss_count(miss_count)
);
initial begin
// Initialize Inputs
clk = 0;
reset = 0;
data_file = $fopen("data_file.txt", "r");
end
always
#10 clk= ~clk;
always #(posedge clk) begin
scan_file = $fscanf(data_file, "%h\n", captured_data);
if (!$feof(data_file)) begin
read_addr <= captured_data;
//$strobe(hit_count);
end
else begin
//$display("The total hit counts are:");
$display(hit_count);
$display(miss_count);
$finish;
end
end
endmodule
And here is the file:
6
9
4
A
8
2
9
5
7
9
7
4
9
7
6
8
Check for EOF before you read each line of the file:
always #(posedge clk) begin
if (!$feof(data_file)) begin
scan_file = $fscanf(data_file, "%h\n", captured_data);
read_addr <= captured_data;
//$strobe(hit_count);
end
else begin
//$display("The total hit counts are:");
$display(hit_count);
$display(miss_count);
$finish;
end
end

Rising Edge Counter

I'm new to fpgas in general. I want to make counter that iterates each time SCK sees a rising edge. The issue i'm having with my code is that it seems to count twice. Two leds are lit each time there is a rising edge transition - as opposed to just one led. Any idea where this may be coming from?
module spi_slave(pcEn, LED, clk, SCK);
input clk, SCK;
output reg pcEn;
output reg [7:0] LED = 8'h00;
reg r1 = 0;
reg r2 = 0;
reg r3 = 0;
reg [3:0] cnt = 4'b0000;
always #(posedge clk)
begin
r1 <= SCK;
r2 <= r1;
pcEn <= r1 && !r3;
if (pcEn == 1) begin
cnt = cnt + 4'b0001;
if (cnt == 4'b0001) begin
LED[0] = 1'b1;
end
else if (cnt == 4'b0010) begin
LED[1] = 1'b1;
end
else if (cnt == 4'b0011) begin
LED[2] = 1'b1;
end
else if (cnt == 4'b0100) begin
LED[3] = 1'b1;
end
else if (cnt == 4'b0101) begin
LED[4] = 1'b1;
end
else if (cnt == 4'b0110) begin
LED[5] = 1'b1;
end
else if (cnt == 4'b0111) begin
LED[6] = 1'b1;
end
else if (cnt == 4'b1000) begin
LED[7] = 1'b1;
end
else
LED = 8'h00;
end
else
#100;
r3 <= r2;
end
endmodule
The counter is counting twice because you are comparing r1 & !r3.
r1->r2->r3 .it takes 2 clocks for r3 to be set after r1 equal 1. This implies that r1&!r3 condition will remain valid for 2 clocks. The pcEn will be generated for 2 clocks , Hence the counter will count twice.
r1 && !r2 or if you want a delay r2 && !r3 should work fine.
you should be able to see this behavior in a waveform to debug.Use $dumpvars; in your simulation to view the waveform.
Also there are couple of change to improve the code.
use of reset.
consistently use non-blocking assignment .
there is no need for #100 delay.
module spi_slave(pcEn, LED, clk, SCK,rst_n);
input clk, SCK,rst_n;
output reg pcEn;
output reg [7:0] LED ;
reg r1 ;
reg r2 ;
reg r3 ;
reg [3:0] cnt ;
always #(posedge clk or negedge rst_n)
begin
if ( rst_n == 0 )
begin
r1 <=0 ;
r2 <= 0 ;
r3 <= 0 ;
cnt <= 0 ;
LED <=0 ;
pcEn <=0 ;
end
else
begin
r1 <= SCK;
r2 <= r1;
r3 <= r2;
pcEn <= r2 && !r3;
if (pcEn == 1) begin
cnt <= cnt + 4'b0001;
if (cnt == 4'b0001) begin
LED[0] <= 1'b1;
end
else if (cnt == 4'b0010) begin
LED[1] <= 1'b1;
end
else if (cnt == 4'b0011) begin
LED[2] <= 1'b1;
end
else if (cnt == 4'b0100) begin
LED[3] <= 1'b1;
end
else if (cnt == 4'b0101) begin
LED[4] <= 1'b1;
end
else if (cnt == 4'b0110) begin
LED[5] <= 1'b1;
end
else if (cnt == 4'b0111) begin
LED[6] <= 1'b1;
end
else if (cnt == 4'b1000) begin
LED[7] <= 1'b1;
end
else
LED <= 8'h00;
end
end
end
endmodule
First of # delays are not synthesizable, they are delays for simulation only.
Generally is considered best practice to separate block and non-blocking logic into different always blocks. always #* for combinational (blocking assignments), and always #(posedge clk) for sequential (non-blocking assignments). FYI : Verilog supports case-statements which make coding value compare easier then nesting else-if.
I thing you may want to use r2 && !r3 instead of r1 && !r3 as Rahul also pointed out
always #* begin
if (pcEn == 1'b0) begin
next_cnt = cnt;
next_LED = LED;
else begin
next_cnt = cnt + 4'b0001;
next_LED = 8'h00; // Rest all to 0s
if(cnt >= 8'h8) next_cnt = 4'b0000; // optional : assuming you want to roll back before waiting another 8 SCK toggles
case(cnt)
4'b0000 : next_LED[0] = 1'b1;
4'b0001 : next_LED[1] = 1'b1;
// ...
4'b0111 : next_LED[7] = 1'b1;
endcase
end
end
always #(posedge clk) begin
r1 <= SCK;
r2 <= r1;
r3 <= r2;
pcEn <= r2 && !r3;
cnt <= next_cnt;
LED <= next_LED;
end

hdl verilog Compiler Errors

When I first tried to compile my code, I only had syntax errors and was able to fix them. Now I have errors that I cannot figure out at all. I don't know how to fix.
Here is my current code:
module p_5 (output y_out, input x_in, clk, reset_b);
parameter s_a = 2'd0;
parameter s_b = 2'd1;
parameter s_c = 2'd2;
reg Set_flag;
reg Clr_flag;
reg [1:0] state, next_state;
assign y_out = (state == s_b) || (state == s_c) ;
always # (posedge clk)
if (reset_b == 1'b0) state <= s_a;
else state <= next_state;
always # (state, x_in, flag) begin
next_state = s_a;
Set_flag = 0;
Clr_flag = 0;
case (state)
s_a: if ((x_in == 1'b1) && (flag == 1'b0))
begin next_state = s_a; Set_flag = 1; end
else if ((x_in == 1'b1) && (flag == 1'b1))
begin next_state = s_b; Set_flag = 0; end
else if (x_in == 1'b0) next_state = s_a;
s_b: if (x_in == 1'b0) next_state = s_b;
else begin next_state = s_c; Clr_flag = 1; end
s_c: if (x_in == 1'b0) next_state = s_c;
else next_state = s_a;
default: begin next_state = s_a; Clr_flag = 1'b0; Set_flag = 1'b0; end
endcase
end
always # (posedge clk)
if (reset_b == 1'b0) flag <= 0;
else if (Set_flag) flag <= 1'b1;
else if (Clr_flag) flag <= 1'b0;
endmodule
This is the test bench:
module test_5 ();
wire y_out;
reg x_in, clk, flag, reset_b;
p_5 M0 (y_out, x_in, clk, reset_b);
initial #500 $finish;
initial begin clk = 0; forever #5 clk = !clk; end
initial fork
reset_b = 1'b0;
#20 reset_b = 1;
#20 x_in = 1'b0;
#40 x_in = 1'b1;
#50 x_in = 1'b0;
#80 x_in = 1'b1;
#100 x_in = 0;
#150 x_in = 1'b1;
#160 x_in = 1'b0;
#200 x_in = 1'b1;
#230 reset_b = 1'b0;
#250 reset_b = 1'b1;
#300 x_in = 1'b0;
#300 flag = 1'b0;
join
endmodule
Errors:
p5.v:22: error: Unable to bind wire/reg/memory `flag' in `t_ques_5_50.M0'
p5.v:22: error: Unable to elaborate condition expression.
p5.v:17: error: Unable to bind wire/reg/memory `flag' in `t_ques_5_50.M0'
flag
p5.v:36: error: Could not find variable ``flag'' in ``t_ques_5_50.M0''
p5.v:37: error: Could not find variable ``flag'' in ``t_ques_5_50.M0''
p5.v:38: error: Could not find variable ``flag'' in ``t_ques_5_50.M0''
7 error(s) during elaboration.
You refer to the value flag repeatedly inside p5.v, yet it is not declared anywhere as an input, reg, or wire.
Add the appropriate declaration and it should be resolved.

Resources