Creating pulses of different width - verilog

I have written following code which produces pulse of different width.I want the code to produce a single pulse according to select line.
If select line is
00 pulse width = 1 us ,
01 pulse width = 10 us
. .
11 pulse width = 1000 us
The input clock is of 10 Mhz.
But according to code I am getting continuous pulse if I don't provide any other value of selection line.How can I achieve only one pulse?
module pulse(input wire [1:0] sel , //selection lines s1 s0
input clk,
input rst_n,
output reg flag, //for checking conditions
output reg [13:0] Q, // output of 14 bit counter
output reg pulse, //output pulse
output reg count); //also for checking conditions
wire flag_d , count_d;
assign flag_d = ( (sel == 2'b00 | sel == 2'b01 | sel == 2'b10 | sel == 2'b11) && count == 1'b0)? 1'b1 : flag;
assign count_d = ( (sel == 2'b00 | sel == 2'b01 | sel == 2'b10 | sel == 2'b11) && count == 1'b0)? 1'b1 : count;
always #(posedge clk , negedge rst_n)
begin
if(!rst_n)
begin
Q <= 14'h0;
count <= 1'b0;
pulse <= 1'b0;
flag <= 1'b0;
end
else
begin
flag <= flag_d;
count <= count_d;
if(flag)
begin
case(sel)
2'b00: Q <= 14'd11;//count from 11 to 1
2'b01: Q <= 14'd101;//count from 101 to 1
2'b10: Q <= 14'd1001;//count from 1001 to 1
2'b11: Q <= 14'd10001;//count from 10001 to 1
default: Q <= 14'd0;
endcase
flag <= 1'b0;
end
else
begin
if(Q != 14'h1 && Q != 14'h0)
begin
Q <= Q - 14'h1;
pulse <= 1'b1;
end
else
begin
pulse <= 1'b0;
count <= 1'b0;
end
end
end
end
endmodule
Is this code in a good coding style considering the synthesis and hardware of the circuit? if not than what changes I should apply?..

I couldn't figure out the point of flag_d and count_d. Also ( (sel == 2'b00 | sel == 2'b01 | sel == 2'b10 | sel == 2'b11) && count == 1'b0) simplifies to (count == 1'b0). sel should not be Xs or Zs.
I think you want something more like the following:
reg [13:0] next_Q;
always #* begin
if (Q==0) begin
case(sel)
2'b00 : next_Q = 14'd10;
2'b01 : next_Q = 14'd100;
2'b10 : next_Q = 14'd1000;
2'b11 : next_Q = 14'd10000;
endcase
end
else begin
next_Q = Q - 1;
end
end
always #(posedge clk, negedge rst_n) begin
if (!rst_n) begin
pulse <= 1'b0;
Q <= 14'd0;
end
else begin
// if (Q==0) pulse <= !pulse; // high and low pulse will have equal if sel is constant
pulse <= (Q!=0); // or high pulse based on sel, low is one clk
Q <= next_Q;
end
end
working example: http://www.edaplayground.com/x/GRv

module pulse(input wire [1:0] sel, // No need for the sel to be wire
input clk,
input rst_n,
output reg [13:0] Q,
output reg pulse,
input input_stb, // Input is valid
input output_ack,
output output_stb,
output input_ack); // 2 Flag model
reg s_input_ack ;
reg s_output_stb;
parameter get_inputs = 4'd0,
counter = 4'd1;
always #(posedge clk , negedge rst_n)
begin
case (state)
get_inputs:
s_input_ack <= 1;
if (s_input_ack && input_a_stb)
begin
s_input_ack <= 0;
case(sel)
00: Q <= 14'd11;//00000000001010;
01: Q <= 14'd101;//00000001100100;
10: Q <= 14'd1001;//00001111101000;
11: Q <= 14'd10001;//10011100010000;
default: Q <= 14'd0;
endcase
state <= counter;
end
counter:
begin
s_output_stb <= 1;
if (s_output_stb && output_z_ack)
begin
s_output_stb <= 0;
if(Q != 14'h1 && Q != 14'h0)
begin
Q <= Q - 1'b1;
pulse <= 1'b1;
end
else
begin
pulse <= 1'b0;
end
end
state <= get_inputs;
end
endcase
if(!rst_n)
begin
Q <= 14'h0;
pulse <= 1'b0;
s_input_ack <= 0;
s_output_stb <= 0;
end
assign input_ack = s_input_ack;
assign output_stb = s_output_stb;
end
endmodule
*Still needs work , add registers and necessary signals accordingly. Will edit at a later point in time

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.

Verilog If statement -Appears to be triggering before Condition

Why does r_D <= 8'h40 execute before w_Rx_DV == 1'b1 according to below code and waveform? R_D should not be assigned any value until w_Rx_DV goes high.
Thank you for any comments
Joe
module main(
input i_Clock,
input i_Rx_Serial,
output o_PWM
);
reg r_Load ;
reg [7:0] r_D =0;
wire w_Rx_DV;
wire [7:0] w_RX_Byte;
reg [7:0] r_RX_Byte;
PWM PWM(
.i_Clock(i_Clock),
.i_Load(r_Load),
.i_D (r_D),
.o_PWM(o_PWM)
);
rx rx(
.i_Clock (i_Clock),
.i_Rx_Serial (i_Rx_Serial),
.o_Rx_DV (w_Rx_DV),
.o_Rx_Byte (w_RX_Byte)
);
always # (posedge i_Clock)
begin
r_Load <= 0;
if(w_Rx_DV == 1'b1) ;
begin
r_RX_Byte <= w_RX_Byte;
if(r_RX_Byte ==8'h0)
begin
r_D <= 0;
r_Load <= 1;
end
if(r_RX_Byte == 8'h3F)
begin
r_D <= 8'h40;
r_Load <= 1;
end
else
begin
r_Load <= 0;
end
end
end
endmodule
waveform
Why does r_D <= 8'h40 execute before w_Rx_DV == 1'b1
Because you have a semicolon after the if here:
if(w_Rx_DV == 1'b1) ;
// ^ End of if statement.

coffee vending machine simulation in verilog with test bench issue

I have written a verilog code for a simple coffee vending machine with inputs
25ps,50ps,75ps and 1
as
"00","01","10" and "11"
respectively. Coffee cost is 1 rs. If more than 1rs is inserted, the balance will be returned. That balance will be
01, 10, 11
as
25ps, 50ps, 1rs
respectively. I simulate this without test bench. simulation takes double clock pulse for output.(when i put 25 ps 8 times or 8 clock pulses is required for getting output. expected clock pulse is 4). Why this is happens? and also i didn't get output when using the test bench.
please help me to correct the test bench and my programme. Is clock frequency divider is necessary while doing the programme in fpga board to see output? It is working as expected when i programmed into fpga board.Im using Xilinx vivado 2015.2 tool and zynq board.Please help me to solve these issues
//programme
module main(
input clk,
input rst,
input [1:0] money,
output coffee,
output [1:0] balance
);
reg coff;
reg [1:0] bal;
reg [2:0] pr_st;
reg [2:0] nx_st;
parameter [2:0] A=3'b000;
parameter [2:0] B=3'b001;
parameter [2:0] C=3'b010;
parameter [2:0] D=3'b011;
parameter [2:0] E=3'b100;
parameter [2:0] F=3'b101;
parameter [2:0] G=3'b110;
parameter [2:0] H=3'b111;
always # (posedge clk or posedge rst)
begin
if(rst)
pr_st <= A;
else
pr_st <= nx_st;
end
always #(posedge clk)
begin
case(pr_st)
A : if(money == 2'b00) // input money is 25ps
begin
nx_st <= B;
end
else if(money == 2'b01) // input money is 50ps
begin
nx_st <= C;
end
else if(money == 2'b10) // input money is 75ps
begin
nx_st <= D;
end
else if(money == 2'b11)
begin
nx_st <= E;
end
B : if(money == 2'b00)
begin
nx_st <= C;
end
else if(money == 2'b01)
begin
nx_st <= D;
end
else if(money == 2'b10)
begin
nx_st <= E;
end
else if(money == 2'b11)
begin
nx_st <= F;
end
C : if(money == 2'b00)
begin
nx_st <= D;
end
else if(money == 2'b01)
begin
nx_st <= E;
end
else if(money == 2'b10)
begin
nx_st <= F;
end
else if(money == 2'b11)
begin
nx_st <= G;
end
D : if(money == 2'b00)
begin
nx_st <= E;
end
else if(money == 2'b01)
begin
nx_st <= F;
end
else if(money == 2'b10)
begin
nx_st <= G;
end
else if(money == 2'b11)
begin
nx_st <= H;
end
E : nx_st <= A;
F : nx_st <= A;
G : nx_st <= A;
H : nx_st <= A;
default : nx_st <= A;
endcase
end
//output logic
always #( posedge clk or pr_st)
begin
case(pr_st)
A: begin
coff <= 1'b0;
bal <= 2'b00;
end
B: begin
coff <= 1'b0;
bal <= 2'b00;
end
C: begin
coff <= 1'b0;
bal <= 2'b00;
end
D: begin
coff <= 1'b0;
bal <= 2'b00;
end
E: begin
coff <= 1'b1;
bal<= 2'b00;
end
F: begin
coff <= 1'b1;
bal <= 2'b01;
end
G: begin
coff <= 1'b1;
bal <= 2'b10;
end
H: begin
coff <= 1'b1;
bal <= 2'b11;
end
default : begin
off <=1'b0;
bal <= 2'b00;
end
endcase
end
assign coffee = coff;
assign balance = bal;
endmodule
//test bench
module tb_main(
);
reg clk;
reg rst;
reg [1:0] money;
wire coffee;
wire [1:0] balance;
main dut( clk, rst, money, coffee, balance);
always
begin
#200 clock = ~clk;
end
initial
begin
rst = 1'b1;
#100 rst = 1'b0;
money = 2'b00; // putting 25ps four times to get coffee
#400 money = 2'b01; //putting 50ps two times to get coffee
#200 money = 2'b10;// putting 75ps two times to get coffee
#200 money = 2'b11;// putting 1 rs single time to g
#100 money = 2'b01; // putting 1st 25ps and 50ps i n second clock cycle
#100 money = 2'b10;
#200
$finish
end
endmodule
You need to initialize your clock signal to a known value in the testbench. You should speed up the clock because your money input changes faster than the clock:
initial clk = 0;
always begin
#10 clk = ~clk;
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

verilog to FSM convert

I have a program written in Verilog and I want to convert it into a FSM automatically. Is this possible (just to visualize it)?
Here is the code :
module pci(reset,clk,frame,irdy,trdy,devsel,idsel,ad,cbe,par,stop,inta,led_out);
input reset;
input clk;
input frame;
input irdy;
output trdy;
output devsel;
input idsel;
inout [31:0] ad;
input [3:0] cbe;
inout par;
output stop;
output inta;
output [3:0] led_out;
parameter DEVICE_ID = 16'h9500;
parameter VENDOR_ID = 16'h106d; // Sequent!
parameter DEVICE_CLASS = 24'hFF0000; // Misc
parameter DEVICE_REV = 8'h01;
parameter SUBSYSTEM_ID = 16'h0001; // Card identifier
parameter SUBSYSTEM_VENDOR_ID = 16'hBEBE; // Card identifier
parameter DEVSEL_TIMING = 2'b00; // Fast!
reg [2:0] state;
reg [31:0] data;
reg [1:0] enable;
parameter EN_NONE = 0;
parameter EN_RD = 1;
parameter EN_WR = 2;
parameter EN_TR = 3;
reg memen; // respond to baseaddr?
reg [7:0] baseaddr;
reg [5:0] address;
parameter ST_IDLE = 3'b000;
parameter ST_BUSY = 3'b010;
parameter ST_MEMREAD = 3'b100;
parameter ST_MEMWRITE = 3'b101;
parameter ST_CFGREAD = 3'b110;
parameter ST_CFGWRITE = 3'b111;
parameter MEMREAD = 4'b0110;
parameter MEMWRITE = 4'b0111;
parameter CFGREAD = 4'b1010;
parameter CFGWRITE = 4'b1011;
`define LED
`ifdef LED
reg [3:0] led;
`endif
`undef STATE_DEBUG_LED
`ifdef STATE_DEBUG_LED
assign led_out = ~state;
`else
`ifdef LED
assign led_out = ~led; // board is wired for active low LEDs
`endif
`endif
assign ad = (enable == EN_RD) ? data : 32'bZ;
assign trdy = (enable == EN_NONE) ? 'bZ : (enable == EN_TR ? 1 : 0);
assign par = (enable == EN_RD) ? 0 : 'bZ;
reg devsel;
assign stop = 1'bZ;
assign inta = 1'bZ;
wire cfg_hit = ((cbe == CFGREAD || cbe == CFGWRITE) && idsel && ad[1:0] == 2'b00);
wire addr_hit = ((cbe == MEMREAD || cbe == MEMWRITE) && memen && ad[31:12] == {12'b0, baseaddr});
wire hit = cfg_hit | addr_hit;
always #(posedge clk)
begin
if (~reset) begin
state <= ST_IDLE;
enable <= EN_NONE;
baseaddr <= 0;
devsel <= 'bZ;
memen <= 0;
`ifdef LED
led <= 0;
`endif
end
else begin
case (state)
ST_IDLE: begin
enable <= EN_NONE;
devsel <= 'bZ;
if (~frame) begin
address <= ad[7:2];
if (hit) begin
state <= {1'b1, cbe[3], cbe[0]};
devsel <= 0;
// pipeline the write enable
if (cbe[0])
enable <= EN_WR;
end
else begin
state <= ST_BUSY;
enable <= EN_NONE;
end
end
end
ST_BUSY: begin
devsel <= 'bZ;
enable <= EN_NONE;
if (frame)
state <= ST_IDLE;
end
ST_CFGREAD: begin
enable <= EN_RD;
if (~irdy || trdy) begin
case (address)
0: data <= { DEVICE_ID, VENDOR_ID };
1: data <= { 5'b0, DEVSEL_TIMING, 9'b0, 14'b0, memen, 1'b0};
2: data <= { DEVICE_CLASS, DEVICE_REV };
4: data <= { 12'b0, baseaddr, 8'b0, 4'b0010 }; // baseaddr + request mem < 1Mbyte
11: data <= {SUBSYSTEM_ID, SUBSYSTEM_VENDOR_ID };
16: data <= { 24'b0, baseaddr };
default: data <= 'h00000000;
endcase
address <= address + 1;
end
if (frame && ~irdy && ~trdy) begin
devsel <= 1;
state <= ST_IDLE;
enable <= EN_TR;
end
end
ST_CFGWRITE: begin
enable <= EN_WR;
if (~irdy) begin
case (address)
4: baseaddr <= ad[19:12]; // XXX examine cbe
1: memen <= ad[1];
default: ;
endcase
address <= address + 1;
if (frame) begin
devsel <= 1;
state <= ST_IDLE;
enable <= EN_TR;
end
end
end
ST_MEMREAD: begin
enable <= EN_RD;
if (~irdy || trdy) begin
case (address)
`ifdef LED
0: data <= { 28'b0, led };
`endif
default: data <= 'h00000000;
endcase
address <= address + 1;
end
if (frame && ~irdy && ~trdy) begin
devsel <= 1;
state <= ST_IDLE;
enable <= EN_TR;
end
end
ST_MEMWRITE: begin
enable <= EN_WR;
if (~irdy) begin
case (address)
`ifdef LED
0: led <= ad[3:0];
`endif
default: ;
endcase
address <= address + 1;
if (frame) begin
devsel <= 1;
state <= ST_IDLE;
enable <= EN_TR;
end
end
end
endcase
end
end
endmodule
If there is no automatic way, could you explain a way of doing this?
Here is an FSM made with hand but can't test so ...
Does it seem ok?
It is sometimes easier to write the code and have the documentation generated from that. Sometimes you inherit legacy code without documentation, in these situations especially if new to a language tools to help visualise what is happening can be quite useful.
With cadence tools you can run your code with 'code coverage' then imc can load the coverage data and run FSM Analysis.
I have included a simple FSM below and show the generated state diagram.
module simple_fsm();
//Inputs to FSM
logic clk;
logic rst_n;
logic [1:0] state ;
logic [1:0] nextstate;
logic turn_on ;
logic turn_off ;
localparam S_OFF = 2'b00;
localparam S_GO_ON = 2'b01;
localparam S_ON = 2'b10;
localparam S_GO_OFF = 2'b11;
// State FlipFlop
always #(posedge clk or negedge rst_n) begin
if (~rst_n) begin
state <= 2'b0;
end
else begin
state <= nextstate;
end
end
//Nextstate Logic
always #* begin
case (state)
2'd0 : if (turn_on) begin
nextstate = S_GO_ON;
end
2'd1 : nextstate = S_ON;
2'd2 : if (turn_off) begin
nextstate = S_GO_OFF ;
end
2'd3 : nextstate = S_OFF;
endcase
end
//TB clk
initial begin
#1ns;
clk = 0;
forever begin
#20ns;
clk = ~clk;
end
end
//The Test
initial begin
rst_n = 1'b0;
turn_on = 1'b0;
turn_off = 1'b0;
#(posedge clk);
#(posedge clk);
rst_n = 1'b1 ;
#(posedge clk);
turn_on = 1'b1;
#(posedge clk);
turn_on = 1'b0;
#(posedge clk);
#(posedge clk);
#100ms;
$finish();
end
endmodule
Execute with :
$ irun simple_fsm.sv -coverage all -covdut simple_fsm
$ imc &
Load cov_work (folder created by above simulation) in imc, select simple_fsm and choose FSM Analysis.
imc also helps to visualise your test coverage as well. Arcs and states that have not been hit are shown in red.
We have seen that there are some tools which can visualise the FSM, another part of the question is; is the syntax of the purposed FSM suitable for these tools.
#vermaete has reported that Modelsim SE can not see the FSM. From imc I get :
Which does not seem to cover the complexity of the code, and is shown as only having 2 reachable states, IDLE and BUSY. I would recommend if OP is going down the route of using tools to visualise, adopt a simpler (syntax) FSM structure so that the tools can parse it better.
The better and expensive simulators can detect FSM's in the code and make a visualization of it. E.g. the Modelsim SE version. These can be nice to understand code and check the coveage.
But making you're own drawing of a 6-state FSM is not that hard.
The way to check if it's OK is to write a simulation and check that the behaviour is what you want. There is no point getting a bubble diagram out and seeing if it matches your hand-drawn one, as you have no way of knowing if your hand-drawn diagram is correct...
case(segmentRead)
//-------------------
SEGMENT0: begin
READ_Ready_EEPROM <= 1'b0;
READ_RDSR_Enable <= 1'b0;
Read_Enable <= 1'b0;
READ_RDSR_DATA_REG <= 8'b0;
// READ_DATA_REG <= 8'b0;
end
//-------------------
SEGMENT2: begin
READ_RDSR_Enable <= 1'b1;
READ_RDSR_DATA_REG <= 8'b0;
end
// //-------------------
SEGMENT3: begin
READ_RDSR_Enable <= 1'b0;
READ_RDSR_DATA_REG <= RDSR_Data;
end
//-------------------
SEGMENT4: begin
Read_Enable <= 1'b1;
end
//-------------------
SEGMENT5: begin
Read_Enable <= 1'b0;
READ_DATA_REG <= Read_Data;
end
//-------------------
SEGMENT6: begin
READ_Ready_EEPROM <= 1'b1;
end
//-------------------
endcase

Resources