How to change clock in Verilog? - verilog

module task_A(input [15:0]sw, input clk,output reg [3:0] an= 4'b1111,output reg[7:0] seg);
reg [2:0] num = 3'd0;
wire Z,Z1,Z2;
clk_1_47hz(clk,Z1);
clk_762hz(clk,Z2);
reg count=0;
assign Z= (count<5)?(Z1):(Z2);
always # (posedge Z)
begin
num <= (sw[15:0]==16'b1111111111111111)?((num==5 | num==0)?(3'd1):(num+1)):(0);
count <=count+1;
case(num)
3'd0 : begin seg <= 8'b11111111 ; an <= 4'b1111; end
3'd1 : begin seg <= 8'b10000111 ; an <= 4'b0111; end //t
3'd2 : begin seg <= 8'b10001000 ; an <= 4'b1011; end //a
3'd3 : begin seg <= 8'b11001111 ; an <= 4'b1101; end //l
3'd4 : begin seg <= 8'b11111001 ; an <= 4'b1101; end //l
3'd5 : begin seg <= 8'b10010001 ; an <= 4'b1110; end //y
endcase
end
endmodule
I wish to change the clock after the 7 segment display has displayed 'tally' once. So I use count to check. But the clock does not change at all. May I know how to correct it?

count is declared as a 1-bit signal, which is always smaller than 5.
reg count=0;
To accomplish your goal, declare it as a 3-bit signal or more.
And you may also need to set a limit for count, and stop it, if you want to switch to Z2 clock forever after 'tally' is displayed once.

Related

No output data in sinc3 filter simulation

I have the following code for sinc3 digital filter in verilog:-
`timescale 1ns / 1ps
module dec256sinc24b
(input mclk1, /* used to clk filter */
input reset, /* used to reset filter */
input mdata1, /* input data to be filtered */
output reg [15:0] DATA, /* filtered output*/
output reg data_en,
input [15:0] dec_rate
);
/* Data is read on negative clk edge */
reg [36:0] ip_data1;
reg [36:0] acc1;
reg [36:0] acc2;
reg [36:0] acc3;
reg [36:0] acc3_d2;
reg [36:0] diff1;
reg [36:0] diff2;
reg [36:0] diff3;
reg [36:0] diff1_d;
reg [36:0] diff2_d;
reg [15:0] word_count;
reg word_clk;
reg enable;
/*Perform the Sinc action*/
always # (mdata1)
if(mdata1==0)
ip_data1 <= 37'd0;
/* change 0 to a -1 for twos complement */
else
ip_data1 <= 37'd1;
/*Accumulator (Integrator)
Perform the accumulation (IIR) at the speed of the modulator.
Z = one sample delay MCLKOUT = modulators conversion bit rate */
always # (negedge mclk1, posedge reset)
begin
if (reset)
begin
/* initialize acc registers on reset*/
acc1 <= 37'd0;
acc2 <= 37'd0;
acc3 <= 37'd0;
end
else
begin
/*perform accumulation process */
acc1 <= acc1 + ip_data1;
acc2 <= acc2 + acc1;
acc3 <= acc3 + acc2;
end
end
/*decimation stage (MCLKOUT/WORD_CLK) */
always # (negedge mclk1, posedge reset)
begin
if (reset)
word_count <= 16'd0;
else
begin
if ( word_count == dec_rate - 1 )
word_count <= 16'd0;
else
word_count <= word_count + 16'b1;
end
end
always # ( negedge mclk1, posedge reset )
begin
if ( reset )
word_clk <= 1'b0;
else
begin
if ( word_count == dec_rate/2 - 1 )
word_clk <= 1'b1;
else if ( word_count == dec_rate - 1 )
word_clk <= 1'b0;
end
end
/*Differentiator (including decimation stage)
Perform the differentiation stage (FIR) at a lower speed.
Z = one sample delay WORD_CLK = output word rate */
always # (negedge word_clk, posedge reset)
begin
if(reset)
begin
acc3_d2 <= 37'd0;
diff1_d <= 37'd0;
diff2_d <= 37'd0;
diff1 <= 37'd0;
diff2 <= 37'd0;
diff3 <= 37'd0;
end
else
begin
diff1 <= acc3 - acc3_d2;
diff2 <= diff1 - diff1_d;
diff3 <= diff2 - diff2_d;
acc3_d2 <= acc3;
diff1_d <= diff1;
diff2_d <= diff2;
end
end
/* Clock the Sinc output into an output register
WORD_CLK = output word rate */
always # (negedge word_clk )
begin
case ( dec_rate )
16'd32:begin
DATA <= (diff3[15:0] == 16'h8000) ? 16'hFFFF : {diff3[14:0], 1'b0};
end
16'd64:begin
DATA <= (diff3[18:2] == 17'h10000) ? 16'hFFFF : diff3[17:2];
end
16'd128:begin
DATA <= (diff3[21:5] == 17'h10000) ? 16'hFFFF : diff3[20:5];
end
16'd256:begin
DATA <= (diff3[24:8] == 17'h10000) ? 16'hFFFF : diff3[23:8];
end
16'd512:begin
DATA <= (diff3[27:11] == 17'h10000) ? 16'hFFFF : diff3[26:11];
end
16'd1024:begin
DATA <= (diff3[30:14] == 17'h10000) ? 16'hFFFF : diff3[29:14];
end
16'd2048:begin
DATA <= (diff3[33:17] == 17'h10000) ? 16'hFFFF : diff3[32:17];
end
16'd4096:begin
DATA <= (diff3[36:20] == 17'h10000) ? 16'hFFFF : diff3[35:20];
end
default:begin
DATA <= (diff3[24:8] == 17'h10000) ? 16'hFFFF : diff3[23:8];
end
endcase
end
/* Synchronize Data Output*/
always# (negedge mclk1, posedge reset )
begin
if ( reset )
begin
data_en <= 1'b0;
enable <= 1'b1;
end
else
begin
if ( (word_count == dec_rate/2 - 1) && enable )
begin
data_en <= 1'b1;
enable <= 1'b0;
end
else if ( (word_count == dec_rate - 1) && ~enable )
begin
data_en <= 1'b0;
enable <= 1'b1;
end
else
data_en <= 1'b0;
end
end
endmodule
I have written a testbench for the same, with the following inputs: mclk1 = 10MHz, mdata1 = 5MHz and dec_rate = 64
`timescale 1ns / 1ps
`define SIM_CYCLE 8192
module sinc3_tb;
//Inputs
reg mclk1;
reg reset;
reg mdata1;
reg [15:0] dec_rate;
//outputs
wire [15:0] DATA;
wire data_en;
//debug
wire [36:0] diff3 = dec256sinc24b_inst.diff3;
// Instantiate the Unit Under Test (UUT)
dec256sinc24b dec256sinc24b_inst(
.mclk1(mclk1),
.reset(reset),
.dec_rate(dec_rate),
/*************************************/
.mdata1(mdata1),
.DATA(DATA),
.data_en(data_en)
);
/*************************************/
// mclk1 = 10MHz
always#(50)
begin
mclk1 <= ~mclk1;
end
// mdata1 = 5MHz
always#(posedge mclk1)
begin
mdata1 <= ~mdata1;
end
initial begin
// Initialize Inputs
mclk1 = 1'b0;
reset = 1'b0;
mdata1 = 1'b0;
dec_rate = 16'd64;
// Add stimulus here
#5 reset = 1'b1;
#(`SIM_CYCLE) $finish;
end
endmodule
When I run the simulation, I don't get any output for the DATA and diff3 as seen in the simulation below. Any suggestions how should I fix this issue?
Also why is the dec_rate = 40? Since, I have set it to 64?
The problem is how you are driving the reset from your testbench. Your design uses an active-high reset, but your testbench sets the reset to 1 for most of the simulation, keeping the design always in reset.
You need to invert the polarity of the reset signal inside the testbench. Assert the reset at time 0, then release the reset at time 5:
initial begin
// Initialize Inputs
mclk1 = 1'b0;
reset = 1'b1;
mdata1 = 1'b0;
dec_rate = 16'd64;
// Add stimulus here
#5 reset = 1'b0;
#(`SIM_CYCLE) $finish;
end
Also, run your simulation for more time to see DATA change from 0. For example:
`define SIM_CYCLE 8192*10
If you want to run for 1ms:
`define SIM_CYCLE 1_000_000
Your waveform display is set to hexadecimal format. 40 is 0x40, which is the same as 64 decimal.
DATA is stuck at 0 because its re-timed by word_clk, and word_clk is stuck at 0.
The signal word_clk is stuck at 0 because reset is high and it holds word_clk at 0.
You are also not running it for enough time to see any data come out.
Try runing for 8192*8 rather than 8192 cycles.
The entire design is held in reset forever.
By the way its bad practice to generate clocks using always blocks in your RTL. It might work in simulation and not in a synthesis/build flow.
A best practice is to use an PLL or MMCM or other vendor apparatus to generate your clocks.
Express time in ms like this:
localparam NUM_MS = 2;
// other code
#(NUM_MS*1ms);

How to start with zero counter verilog

I'm implementing a repeating bit shifter for a 16 bit number. To do this, I have a bit counter that counts how many times I've shifted and resets when I reach 4'b1111. Then I have an assign statement that feeds the MSB to an output. However, the logic makes it so that the output skips the first MSB every time. What is the most succinct way to include the first MSB, before any shifting has occurred?
CODE
module DAC_Control(
input [15:0]data_in,
input clk,
input rst,
output data_out,
output reg cs,
output reg enable
);
//bit counter
reg [3:0] bit_counter;
//to help with shifting
reg [15:0] shifter;
always #(data_in)
shifter <= data_in;
//shifter
always #(posedge (clk)) begin
if (rst) begin
bit_counter <= 4'b0;
enable <= 1'b0;
cs <= 1'b1;
end
else if (bit_counter == 4'b1111) begin
bit_counter <= 4'b0;
enable <= 1'b1;
cs <= 1'b1;
end
else begin //this is the problem area
bit_counter <= bit_counter + 1'b1;
enable <= 1'b0;
cs <= 1'b0;
shifter <= shifter << 1;
end
end
assign data_out = shifter[15];
endmodule
Firstly it would be better to have a trigger to capture the data_in. If not then in simulation ,if the data_in changes in between the shifting it will update the shifter and cause the expected output to change. It would be preferable to capture the data_in based on a qualifying event ( e.g. counter_enable in the example below) . Synthesis will produce an error as shifter has two drivers . One the continuous assignment shifter <= data_in; and other the shifting logic shifter <= shifter << 1;
Updated sample code should serialize the data.
module DAC_Control(
input [15:0]data_in,
input counter_enable,
input clk,
input rst,
output data_out,
output reg cs,
output reg enable
);
//bit counter
reg [3:0] bit_counter;
//to help with shifting
reg [15:0] shifter;
//shifter
always #(posedge (clk)) begin
if (rst) begin
bit_counter <= 4'b0;
shifter <= 0;
end
else if (counter_enable == 1) begin
shifter <= data_in;
bit_counter <= 4'b0;
end
else begin
shifter <= shifter << 1; // shifting
bit_counter <= bit_counter + 1'b1; // counter
end
end
always #(posedge (clk)) begin
if (rst) begin
enable <= 1'b0;
cs <= 1'b1;
end
else if (bit_counter == 4'b1111) begin
enable <= 1'b1;
cs <= 1'b1;
end
else begin
enable <= 1'b0; // generate enable signals
cs <= 1'b0;
end
end
assign data_out = shifter[15];
endmodule

Creating pulses of different width

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

Seven Segment Display

I'm having some problems coding a seven seg display in verilog. I want to increment 1 digit by 1 and have it roll over to 0 after 9. I have done lots of debugging and looked at examples but I can't seem to find the problem. My code:
module counter(output sega, segb, segc, segd, sege, segf, segg);
OSCH #("2.08") osc_int ( //"2.03" specifies the operating frequency, 2.03 MHz. Other clock frequencies can be found in the MachX02's documentation
.STDBY(1'b0), //Specifies active state
.OSC(clk), //Outputs clock signal to 'clk' net
.SEDSTDBY());
reg [21:0] cnt;
wire clk_slow = cnt[21]; //clock at 1 Hz
reg [3:0] BCD; //represents the states of the counter
always #(posedge clk)
begin
begin
cnt <= cnt+1;
end
begin
if(clk_slow) BCD <= (BCD ==4'h9 ? 4'h0 : BCD+4'b0001); //increments state by 1
end
end
reg [6:0] seg;
always #(*)
begin
case(BCD)
//gfedcba
4'b0000: seg = 7'b1000000; //0
4'b0001: seg = 7'b1111001; //1
4'b0010: seg = 7'b0100100; //2
4'b0011: seg = 7'b0110000; //3
4'b0100: seg = 7'b0011001; //4
4'b0101: seg = 7'b0010010; //5
4'b0110: seg = 7'b0000010; //6
4'b0111: seg = 7'b1111000; //7
4'b1000: seg = 7'b0000000; //8
4'b1001: seg = 7'b0011000; //9
default seg = 7'b0111111;
endcase
end
assign {segg, segf, sege, segd, segc, segb, sega} = seg;
endmodule
So when its running, my LEDs light up the correct digit every other time. In this case, it lights up on 0, 2, 4, 6, 8 and repeats. In between each number, the LEDs are lit, but not as brightly ( a dim '8'). When I switched the order of the cases but kept the numbers in the same spot (i.e. case b0000 is now for number 9), the LEDs light up 9, 7, 5, 3, 1.... For some reason, my LEDs arnt responding for any of the "odd" cases (i.e. 0001, 0011...). Any help sorting this out is greatly appreciated, as I have spent lots of hours trying to debug already.
I am using a Diamond Lattice FPGA. It has an onboard clock (the first module in my code). I slow it down to 1 hz at clock_slow.
Your problem is related to those lines:
always #(posedge clk)
begin
cnt <= cnt+1;
if(clk_slow) BCD <= (BCD ==4'h9 ? 4'h0 : BCD+4'b0001); //increments state by 1
end
Because clk is faster than clk_slow, the if condition will be true for more than one clock cycle ('cause clk_slow is high for couple clk cycles). That's why BCD will be incremented more than once. I'd recommend you to divide this two instructions into two separate always blocks:
always #(posedge clk) begin
cnt <= cnt + 1;
end
always #(posedge clk_slow) begin
BCD <= (BCD ==4'h9 ? 4'h0 : BCD+4'b0001); //increments state by 1
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