[verilog]Activating LED with Pmod_KYPD combination - verilog

I'm using a Pmod_KYPD connected to a Digilent FPGA.
My purpose is to activate the first LED on the board after the combination '123' is entered in to the keypad.
I've downloaded the demo code of the keypad from Digilent which works fine and it basically displays whatever pressed on from the keypad on to the 7-segment display.
The demo code is composed of two parts, which are decode and display. I've modified the display code(only the second 'always' statement is my addition) like the following with a statement machine:
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////////////////////////////
// Company: Digilent Inc 2011
// Engineer: Michelle Yu
// Josh Sackos
// Create Date: 07/23/2012
//
// Module Name: DisplayController
// Project Name: PmodKYPD_Demo
// Target Devices: Nexys3
// Tool versions: Xilinx ISE 14.1
// Description: This file defines a DisplayController that controls the seven segment display that works with
// the output of the Decoder.
//
// Revision History:
// Revision 0.01 - File Created (Michelle Yu)
// Revision 0.02 - Converted from VHDL to Verilog (Josh Sackos)
//////////////////////////////////////////////////////////////////////////////////////////////////////////
// ==============================================================================================
// Define Module
// ==============================================================================================
module DisplayController(
DispVal,
anode,
segOut,
led,
clk,
reset
);
input clk;
input reset;
// ==============================================================================================
// Additional Declarations
// ==============================================================================================
output reg [7:0] led;
reg [1:0] state;
// ==============================================================================================
// Port Declarations
// ==============================================================================================
input [3:0] DispVal; // Output from the Decoder
output [3:0] anode; // Controls the display digits
output [6:0] segOut; // Controls which digit to display
// ==============================================================================================
// Parameters, Regsiters, and Wires
// ==============================================================================================
// Output wires and registers
wire [3:0] anode;
reg [6:0] segOut;
// ==============================================================================================
// Implementation
// ==============================================================================================
// only display the rightmost digit
assign anode = 4'b1110;
//------------------------------
// Segment Decoder
// Determines cathode pattern
// to display digit on SSD
//------------------------------
always #(DispVal) begin
case (DispVal)
4'h0 : segOut <= 7'b1000000; // 0
4'h1 : segOut <= 7'b1111001; // 1
4'h2 : segOut <= 7'b0100100; // 2
4'h3 : segOut <= 7'b0110000; // 3
4'h4 : segOut <= 7'b0011001; // 4
4'h5 : segOut <= 7'b0010010; // 5
4'h6 : segOut <= 7'b0000010; // 6
4'h7 : segOut <= 7'b1111000; // 7
4'h8 : segOut <= 7'b0000000; // 8
4'h9 : segOut <= 7'b0010000; // 9
4'hA : segOut <= 7'b0001000; // A
4'hB : segOut <= 7'b0000011; // B
4'hC : segOut <= 7'b1000110; // C
4'hD : segOut <= 7'b0100001; // D
4'hE : segOut <= 7'b0000110; // E
4'hF : segOut <= 7'b0001110; // F
default : segOut <= 7'b0111111;
endcase
end
always #(posedge clk) begin
if(reset) begin
led <= 8'b11111111;
state <= 0;
end
else begin
case (state)
2'b00: begin
if(DispVal == 1) begin
state <= state + 1;
end
//led <= 8'b10000000;
end
2'b01: begin
if(DispVal == 2) begin
state <= state + 1;
end
else
state <= 0;
//led <= 8'b00000010;
end
2'b10: begin
if(DispVal == 3) begin
state <= state + 1;
end
else
state <= 0;
//led <= 8'b00000100;
end
2'b11: begin
led <= 8'b11111111;
end
default: led <= 0;
endcase
end
end
endmodule
But my modification is not working unfortunately. If I enter '123' from the keypad, the LED simply doesn't get activated.
What should I change in my modification?
Thanks. :)

You need a condition that keeps the current state. Example:
2'b01: begin
if(DispVal == 2) begin
state <= state + 1;
end
else if(DispVal == 1)
state <= state; // keep current state
else
state <= 0;
//led <= 8'b00000010;
end
Note: this is assuming DispVal is sticky (i.e., it holds it value until a different key is pressed). If not, then add logic or states to handle the no key press condition.
Debug suggestion: if you do not a a simulator, then un-comment the commented-out led <= in the state machine. This will allow monitoring of the state order

Related

How to fix infinite run time when VVP start simulation?

this verilog code for Multiplier 4x4 have a serious problem when simulation starts using vvp.i am totally confused and can not understand where should i put an end statement that finish the simulation?
`timescale 1ns / 1ps
module mult_4x4(
input reset,start,
input[3:0] A,B,
output [7:0] O, output Finish
);
reg [7:0] O;
wire Finish;
wire Phi0,Phi1;// 2 phase clocking
wire m1,m2,m3,m4;
// state machine
reg[3:0] State;
// Accumulator
reg [8:0] ACC; // Accumulator
// logic to create 2 phase clocking when starting
nand u0(m1,start,m2);
buf #20 u1(m2,m1);
buf #10 u2(Phi0,m1);// First phase clocking
not #2 u5(m4,Phi0);
assign m3=~m1;
and #2 u4(Phi1,m3,m4);// Second phase clocking
assign Finish = (State==9)? 1'b1:1'b0; // Finish Flag
// FSM
always #(posedge Phi0 or posedge Phi1 or posedge reset)
begin
if(reset) begin
State <= 0;
ACC <= 0;
O <= 0;
end
else if((Phi0==1'b1) || (Phi1==1'b1)) begin // 2 phase clocking
if(State==0)
begin
ACC[8:4] <= 5'b00000; // begin cycle
ACC[3:0] <= A; // Load A
State <= 1;
end
else if(State==1 || State == 3 || State ==5 || State ==7)
// add/shift State
begin
if(ACC[0] == 1'b1) begin // add multiplicand
ACC[8:4] <= {1'b0,ACC[7:4]} + B;
State <= State + 1;
end
else
begin
ACC <= {1'b0,ACC[8:1]};// shift right
State <= State + 2;
end
end
else if(State==2 || State == 4 || State ==6 || State ==8)
// shift State
begin
ACC <= {1'b0,ACC[8:1]}; // shift right
State <= State + 1;
end
else if(State == 9) begin
State <= 0;
O <= ACC[7:0];
end
end
end
endmodule
// TestBench
module test();
// signals
reg start,reset;
reg[3:0] A,B;
// Outputs
wire [7:0] O;
wire Finish;
// device under test
mult_4x4 dut(reset,start, A,B,O,Finish);
initial begin
reset=1; // reset
#40 start = 0;A =14; B= 11;
#400 reset = 0;
#40 start = 1; // start
end
endmodule
after running this code,simulating never stop and when you press control+c (in cmd) it shows this message:
** VVP Stop(0) **
** Flushing output streams.
** Current simulation time is 56484472000 ticks.
i forgot to add :
#(posedge finish);
$finish;
in the end of my code...

how to properly connect receiver, sender and top and make them dependent from each other - RS232

I've got a simple project which requires me to write a code for RS232 receiver and sender, then put them together and, finally, test if it works properly. I've prepared code for both sender and receiver (and also connecting block - top). My problem is that I don't know how to connect them, so they could work with each other properly.
The main issue is that I can't "transfer" data from data_o to data_i because of the fact that one is reg and second - wire. I wouldn't like to use inout for these purposes. I can't figure out any possible modifications to make it work.
Another issue is putting some flags that could kind of follow idea like this: if receiving -> not sending, if sending -> not receiving.
Here's my code:
top.v
`timescale 1ns / 1ps
module top (
clk_i,
rst_i,
RXD_i,
data_i,
TXD_o,
data_o
);
input clk_i;
input rst_i;
input RXD_i;
output TXD_o;
//the problem is here, can't data_i <= data_o because output is reg
input [7:0] data_i;
output [7:0] data_o;
receiver r1(clk_i, RXD_i, data_o);
sender s1(clk_i, data_i, TXD_o);
endmodule
receiver.v
`timescale 1ns / 1ps
module receiver (
clk_i,
RXD_i,
data_o
);
//inputs and outputs
input clk_i;
input RXD_i;
output reg [7:0] data_o;
//counter values
parameter received_bit_period = 5208;
parameter half_received_bit_period = 2604;
//state definitions
parameter ready = 2'b00;
parameter start_bit = 2'b01;
parameter data_bits = 2'b10;
parameter stop_bit = 2'b11;
//operational regs
reg [12:0] counter = 0; //9765.625Hz
reg [7:0] received_data = 8'b00000000;
reg [3:0] data_bit_count = 0;
reg [1:0] state = ready;
//latching part
reg internal_RXD;
always #(posedge clk_i) //latch RXD_i value to internal_RXD
begin
internal_RXD = RXD_i;
end
always #(clk_i) //receiving process
begin
case (state)
ready :
begin
if (internal_RXD == 0)
begin
state <= start_bit;
counter <= counter + 1;
end
else
begin
state <= ready;
counter <= 0;
data_bit_count <= 0;
end
end
start_bit :
begin
if (counter == half_received_bit_period)
begin
if (internal_RXD == 0)
begin
state <= data_bits;
counter <= 0;
end
end
else
begin
state <= start_bit;
counter <= counter + 1;
end
end
data_bits :
begin
if (counter == received_bit_period)
begin
received_data[data_bit_count] <= internal_RXD;
data_bit_count <= data_bit_count + 1;
counter <= 0;
if (data_bit_count == 8)
state <= stop_bit;
end
else
counter <= counter + 1;
end
stop_bit:
begin
counter <= counter + 1;
if (counter == received_bit_period)
begin
state <= ready;
data_o <= received_data;
end
end
endcase
end
endmodule
sender.v
`timescale 1ns / 1ps
module sender (
clk_i,
data_i,
TXD_o
);
//inputs and outputs
input clk_i;
input [7:0] data_i;
output reg TXD_o;
//counter values
parameter received_bit_period = 5208;
parameter half_received_bit_period = 2604;
//state definitions
parameter ready = 1'b0;
parameter data_bits = 1'b1;
//operational regs
reg [12:0] counter = 0; //9765.625Hz
reg [9:0] framed_data = 0;
reg [3:0] data_bit_count = 0;
reg state = ready;
always #(posedge clk_i) //sending process
begin
case (state)
ready :
begin // flag needed?
state <= data_bits;
TXD_o <= 1;
framed_data[0] <= 1'b0;
framed_data[8:1] <= data_i;
framed_data[9] <= 1'b1;
counter <= 0;
end
data_bits :
begin
counter <= counter + 1;
if (data_bit_count == 10)
begin // flag needed?
state <= ready;
data_bit_count <= 0;
TXD_o <= 1;
end
else
begin
if (counter == received_bit_period)
begin
data_bit_count <= data_bit_count + 1;
end
TXD_o <= framed_data[data_bit_count];
end
end
endcase
end
endmodule
You don't!
In all CPU's and FPGA nowadays the read and write data path are separate buses. You will find that also with all CPU cores. Have a look at AXI or AHB bus protocols from ARM.
What is more worrying is the way you have implemented your functions. You would at least need some 'data valid' signal for the transmitter to know when there is valid data to transmit and for the receive when valid data has arrived.
Even that is not enough because for the TX the connecting logic would need to know when the data has been send and the next byte can go out.
You need to make a (preferably standard) CPU interface which talks to your UART. (For beginner I would not use AXI.)
As to your flags: they would come from within the CPU interface.
Last: a UART should be capable of transmitting and receiving at the same time.

Verilog : uart on FPGA and simulation behavioural differences

EDIT: removed some redundancies, moved all assignments to non-blocking, inserted a reset mapped as one of the input buttons of my FPGA... but when I implement the code, it starts transmitting the same wrong character and gets stuck in a single state of my machine.
Post Synthesis and Post-Implementation simulations are identical,$time-wise
module UART (reset_button, sysclk_p, sysclk_n,TxD, Tx_busy, Tx_state_scope_external);
input reset_button, sysclk_p, sysclk_n;
output wire TxD, Tx_busy;
output wire [1:0]Tx_state_scope_external;
//internal communications signals
wire clk_internal;
//buffer unit control signals
wire [7:0]TxD_data_internal;
wire Tx_start_internal;
wire Tx_busy_internal;
wire reset_flag;
reset_buf RESET_BUFF (.reset_internal (reset_flag), .reset (reset_button));
differential_CK CK_GENERATION (.sysclk_p (sysclk_p), .sysclk_n(sysclk_n), .clk(clk_internal));
output_Dbuffer OB1 (.reset (reset_flag), .RTS_n (Tx_busy_internal), .clk(clk_internal), .TX_trigger (Tx_start_internal), .TX_data(TxD_data_internal));
async_transmitter TX1 (.reset (reset_flag), .clk (clk_internal), .TxD_data(TxD_data_internal), .Tx_start (Tx_start_internal), .TxD(TxD), .Tx_busy_flag(Tx_busy_internal), .Tx_state_scope(Tx_state_scope_external));
obuf_TX O_TX1( .Tx_busy(Tx_busy), .Tx_busy_flag(Tx_busy_internal));
endmodule
module reset_buf (
output reset_internal,
input reset
);
// IBUF: Single-ended Input Buffer
// 7 Series
// Xilinx HDL Libraries Guide, version 14.7
IBUF #(
.IBUF_LOW_PWR("TRUE"), // Low power (TRUE) vs. performance (FALSE) setting for referenced I/O standards
.IOSTANDARD("DEFAULT") // Specify the input I/O standard
) IBUF_inst (
.O(reset_internal), // Buffer output
.I(reset) // Buffer input (connect directly to top-level port)
);
// End of IBUF_inst instantiation
endmodule
module differential_CK(
input sysclk_p,
input sysclk_n,
output clk
);
// IBUFGDS: Differential Global Clock Input Buffer
// 7 Series
// Xilinx HDL Libraries Guide, version 14.7
IBUFGDS #(
.DIFF_TERM("FALSE"), // Differential Termination
.IBUF_LOW_PWR("TRUE"), // Low power="TRUE", Highest performance="FALSE"
.IOSTANDARD("DEFAULT") // Specify the input I/O standard
) IBUFGDS_inst (
.O(clk), // Clock buffer output
.I(sysclk_p), // Diff_p clock buffer input (connect directly to top-level port)
.IB(sysclk_n) // Diff_n clock buffer input (connect directly to top-level port)
);
// End of IBUFGDS_inst instantiation
endmodule
module output_Dbuffer (
input reset,
input RTS_n, //TX_BUSY flag of the transmitter is my ready to send flag
input clk, //ck needed for the FSM
output wire TX_trigger, //TX_START flag of the transmitter now comes from THIS unit instead of Receiver
output wire [7:0]TX_data //byte for transmission
);
//internal variables
reg [7:0] mem [0:9]; //memory init, 10 * 8 bit locations
integer m, n, i, j, k ; //M = row [a.k.a. bytes], N = column [a.k.a. single bits]
reg TX_trigger_int;
reg [7:0] TX_data_int, TX_complete;
//reg sum256_ok;
reg [7:0]checksum_buff ;
//buffer FSM required variables
localparam //state enumeration declaration
BUF_IDLE = 3'b000,
BUF_START = 3'b001,
BUF_BYTES = 3'b010,
BUF_BUSY = 3'b011,
BUF_TX_CHECKSUM = 3'b100;
reg [2:0] buf_state; //2 bits for 4 states
//static assignments of OUTPUTS : Transmission Flag and Transmission Data (content)
assign TX_trigger = TX_trigger_int;
assign TX_data = TX_data_int;
//Block for transmitting [here I manage the TX_Data and TX_Trigger functionality]
always #(posedge clk)
begin
if (reset)
begin
buf_state <= BUF_IDLE;
TX_trigger_int <= 0;
TX_data_int <= 8'b00000000;
end
else case (buf_state)
BUF_IDLE:
begin
TX_trigger_int <= 0;
TX_data_int <= 8'b00000000;
m <=0;
n <=0;
i <=0;
j <=0;
mem[9] <= 8'b01010001; //81
mem[8] <= 8'b01000000; //64
mem[7] <= 8'b00110001; //49
mem[6] <= 8'b00100100; //36
mem[5] <= 8'b00011001; //25
mem[4] <= 8'b00010000; //16
mem[3] <= 8'b00001001; //9
mem[2] <= 8'b00000100; //4
mem[1] <= 8'b00000001; //1
mem[0] <= 8'b00000010;//2
checksum_buff <= 8'd31;
//check if the TX is not busy
if (RTS_n == 0) buf_state <= BUF_START;
end
BUF_START:
begin
TX_trigger_int <= 0;
if ((i == 0) || ( (j - i) > 1 )) buf_state <= BUF_BYTES;
else begin
$display ("BUFFER BUSY #time:", $time);
buf_state <= BUF_BUSY;
end
end
BUF_BYTES:
begin
//check if the TX is busy
if (RTS_n==0)
begin
// TX_trigger_int = 1; 21.09 MOVED THE TRIGGER INSIDE THE ELSE N LINE 498
if (j > 9)
begin
TX_trigger_int <= 0;
buf_state <= BUF_TX_CHECKSUM;
end
else begin
TX_data_int <= mem[j];
TX_trigger_int <= 1;
j <= j+1;
//TX_trigger_int =0;
buf_state <= BUF_START;
end
end
else buf_state <= BUF_BYTES;
end
BUF_BUSY:
begin
if (RTS_n == 0)
begin
$display ("BUFFER AVAILABLE AGAIN #time:", $time);
buf_state <= BUF_START;
end
end
BUF_TX_CHECKSUM:
begin
if (RTS_n==0) begin
TX_data_int <= checksum_buff;
// sum256_ok = 0;
TX_trigger_int <= 1;
buf_state <= BUF_IDLE;
end
end
//default: buf_state <= BUF_IDLE;
endcase
end
endmodule
module async_transmitter(
input clk,
input reset,
//differential clock pair
input [7:0] TxD_data,
input Tx_start, // it is ==TX_TRIGGER
output wire TxD, //bit being sent to the USB
output reg Tx_busy_flag,
output wire [1:0]Tx_state_scope
);
localparam //state enumeration declaration
TX_IDLE = 2'b00,
TX_START_BIT = 2'b01,
TX_BITS = 2'b10,
TX_STOP_BIT = 2'b11;
parameter ClkFrequencyTx = 200000000; // 200MHz
parameter BaudTx = 9600;
reg [1:0] Tx_state; //2 bits for 4 states
integer bit_counter; //bit counter variable
reg [7:0]TxD_data_int, TxD_int;
integer i; //vector index for output data
wire TXSTART_Trigger;
StartDetectionUnitTX SDU_TX (.clk(clk), .state (Tx_state), .signal_in (Tx_start), . trigger (TXSTART_Trigger));
wire BitTick;
BaudTickGen #(ClkFrequencyTx, BaudTx) as (.clk(clk), .trigger (TXSTART_Trigger), .tick(BitTick));
//BitTick is 16times the frequency generated during the RX portion
assign TxD = TxD_int;
always #(posedge clk) begin
if (reset)
begin
Tx_state <= TX_IDLE;
TxD_int <= 1;
Tx_busy_flag <=0;
end
else case (Tx_state)
TX_IDLE:
begin //reinitialization and check on the trigger condition
bit_counter <= 0;
TxD_data_int <= 8'b00000000;
i <= 0;
TxD_int <= 1; //idle state
Tx_busy_flag <= 0;
if (TXSTART_Trigger) begin
Tx_state <= TX_START_BIT;
TxD_data_int <= TxD_data;
Tx_busy_flag <= 1;
bit_counter <= 8;
end
end
TX_START_BIT:
begin
if (BitTick)
begin
TxD_int <= 0 ; //start bit is a ZERO logical value
Tx_state <= TX_BITS;
end
end
TX_BITS:
begin
if (BitTick)
begin
bit_counter <= bit_counter -1;
TxD_int <= TxD_data_int[i];
// $display ("ho trasmesso dalla UART un bit di valore %b al tempo: ", TxD, $time);
i <= i+1;
if (bit_counter < 1) Tx_state <= TX_STOP_BIT;
end
end
TX_STOP_BIT:
begin
if (BitTick) begin
TxD_int <= 1; //STOP BIT is a logical '1'
Tx_busy_flag <= 0;
Tx_state <= TX_IDLE;
end
end
// default: Tx_state <= TX_IDLE;
endcase
end
assign Tx_state_scope = Tx_state;
endmodule
module obuf_TX (
output Tx_busy,
input Tx_busy_flag
);
// OBUF: Single-ended Output Buffer
// 7 Series
// Xilinx HDL Libraries Guide, version 14.7
OBUF #(
.DRIVE(12), // Specify the output drive strength
.IOSTANDARD("DEFAULT"), // Specify the output I/O standard
.SLEW("SLOW") // Specify the output slew rate
) OBUF_inst (
.O(Tx_busy), // Buffer output (connect directly to top-level port)
.I(Tx_busy_flag) // Buffer input
);
// End of OBUF_inst instantiation
endmodule
module StartDetectionUnitTX ( //detects a rising edge of the start bit == TRANSMISSION START, during the IDLE state = 0000
input clk, [1:0]state,
input signal_in,
output trigger
);
reg signal_d;
always #(posedge clk)
begin
signal_d <= signal_in;
end
assign trigger = signal_in & (!signal_d) & (!state);
endmodule
module BaudTickGen (
input clk, trigger,
output tick //generates a tick at a specified baud rate *oversampling
);
parameter ClkFrequency = 200000000; //sysclk at 200Mhz
parameter Baud = 9600;
parameter Oversampling = 1;
//20832 almost= ClkFrequency / Baud, to make it an integer number
integer counter = (20833/Oversampling)-1; //-1 so counter can get to 0
reg out;
always #(posedge clk)
begin
if (trigger)
begin
counter <= (20833/Oversampling)-1; //-1 so counter can get to 0
out <= 1;
end
if (counter == 0)
begin
counter <= (20833/Oversampling)-1; //-1 so counter can get to 0
out <= 1;
end
else begin
counter <= counter-1;
out <= 0;
end
end
assign tick = out;
endmodule
My FPGA is a Virtex-7 VC707 and I'm using Vivado for my design flow.
Here I am attaching an image of my looping error.
error image
What have you done? Have you just simulated the code? Are you saying that it fails on the board, but the post-implementation sim is Ok?
A difference between pre- and post-implementation sim could point to a race condition. Get rid of all your blocking assignments, replace with NBAs (why did you use blocking assignments?)
Don't go to Chipscope - it's just a red flag that you don't know what you're doing
The code is a mess - simplify it. The Xilinx-specific stuff is irrelevant - get rid of it if you want anyone to look at it, fix comments (2-bit state?!), fix your statement about getting stuck in '10', etc
Have you run this through Vivado? Seriously? You have multiple drivers on various signals. Get rid of the initial block, use a reset. Initialise the RAM in a way which is understood by the tools. Even if Vivado is capable of initialising stuff using a separate initial block, don't do it
Get rid of statements like 'else Tx_state = TX_IDLE' in the TX_IDLE branch - they're redundant, and just add verbosity
Write something which fails stand-alone, and post it again.

Verilog wires being set to X instead 1

I am currently programming a blackjack game in verilog with several modules including game logic and scoring. The goal of my project is to display onto a screen through VGA and a nexys3 FPGA board the blackjack game. Before I mess with setting up VGA, I need to make sure that my game logic is correctly working and setting the player hand and player score correctly. Unfortunately the player's hand is not being set correctly and is displaying X values where 1s should be. Below are all of my modules and code and at the bottom is the simulation I am running:
This is the main module that calls my other modules.
module blackJack(
input clk,
input btnhit, //deal card to player
input btnpass, //stay for player/pass to dealer
input btnreset, //reset game to 0 and redeal
output Hsync,
output Vsync,
output reg [2:0] vgaRed,
output reg [2:0] vgaGreen,
output reg [1:0] vgaBlue
);
wire [7:0] plscore;
wire [7:0] dlscore;
wire [7:0] plhand;
wire [7:0] dlhand;
wire [2:0] state;
wire [7:0] plcard;
wire [7:0] dlcard;
wire plbust;
wire dlbust;
wire plbj;
wire dlbj;
wire plhit;
wire dlhit;
wire plwin;
wire pllose;
reg vgaclk;
wire trigger;
clock vclk(
.clk(clk),
.vgaclk(vgaclk)
);
wire hit;
debouncer hitD(
.clk(clk),
.button_in(btnhit),
.button_out(hit)
);
wire pass;
debouncer passD(
.clk(clk),
.button_in(btnpass),
.button_out(pass)
);
wire reset;
debouncer resetD(
.clk(clk),
.button_in(btnreset),
.button_out(reset)
);
controller cntrl(
.clk(clk),
.trigger(trigger),
.state(state),
.curPlHand(plhand),
.curDlHand(dlhand),
.dlhit(dlhit),
.plhit(plhit),
.plwin(plwin),
.pllose(pllose),
.plscore(plscore),
.dlscore(dlscore)
);
randomGen gen(
.clk(clk),
.card1(plcard),
.card2(dlcard)
);
player pl(
.clk(clk),
.addCard(plhit),
.card(plcard),
.hand(plhand)
);
player dl(
.clk(clk),
.addCard(dlhit),
.card(dlcard),
.hand(dlhand)
);
checkBust chkpl(
.clk(clk),
.handTotal(plhand),
.bust(plbust),
.blackJack(plbj)
);
checkBust chkdl(
.clk(clk),
.handTotal(dlhand),
.bust(dlbust),
.blackJack(dlbj)
);
stateMonitor sm(
.clk(clk),
.reset(reset),
.hit(hit),
.pass(pass),
.plwin(plwin),
.pllose(pllose),
.state(state),
.trigger(trigger)
);
endmodule
Here are each individual module.
module clock(
input clk,
output vgaclk
);
reg vgaclk;
reg [31:0] out = 0;
always # (posedge clk) begin
if (out >= 3) begin
out <= 0;
end
if (out == 3) begin
vgaclk <= 1;
end
else begin
vgaclk <= 0;
end
out <= out + 1;
end
endmodule
player module:
module player(
input clk,
input addCard,
input [7:0] card,
output [7:0] hand
);
reg [7:0] hand = 0;
always #(posedge clk) begin
if (addCard == 1)
hand <= hand + card;
end
endmodule
statemonitor module:
module stateMonitor(
input clk,
input reset,
input hit,
input pass,
input plwin,
input pllose,
output [2:0] state,
output trigger
);
reg [2:0] currentState = 3'b000;
reg action = 1;
//modes
//000 = start of game. score = 0 and no hand dealt
//001 = player dealt first card
//010 = player dealt second card
//011 = dealer dealt first card - wait for player to hit or pass
//100 = player hits
//101 = player passes -> dealer hits
//110 = payer wins
//111 = player loses
always # (posedge clk) begin
if (currentState == 3'b000 && action == 0) begin
currentState <= 3'b001;
action <= 1;
end
else if (currentState == 2'b001 && action == 0) begin
currentState <= 3'b010;
action <= 1;
end
else if (currentState == 3'b010 && action == 0) begin
currentState <= 3'b011;
action <= 1;
end
else if (currentState == 3'b011 && action == 0) begin
if (plwin == 1) begin
currentState <= 3'b110;
action <= 1;
end
else if (hit == 1) begin
currentState <= 3'b100;
action <= 1;
end
else if (pass == 1) begin
currentState <= 3'b101;
action <= 1;
end
else if (reset == 1) begin
currentState <= 3'b000;
action <= 1;
end
end
else if (currentState == 3'b100 && action == 0) begin
if (plwin == 1) begin
currentState <= 3'b110;
action <= 1;
end
else if (pllose == 1) begin
currentState <= 3'b111;
action <= 1;
end
else if (hit == 1) begin
currentState <= 3'b100;
action <= 1;
end
else if (pass == 1) begin
currentState <= 3'b101;
action <= 1;
end
else if (reset == 1) begin
currentState <= 3'b000;
action <= 1;
end
end
else if (currentState == 3'b101 && action == 0) begin
if (plwin == 1) begin
currentState <= 3'b110;
action <= 1;
end
else if (pllose == 1) begin
currentState <= 3'b111;
action <= 1;
end
else if (reset == 1) begin
currentState <= 3'b000;
action <= 1;
end
else
action <= 1;
end
else if (currentState == 3'b110 && action == 0) begin
if (hit == 1)
currentState <= 3'b000;
end
else if (currentState == 3'b111 && action == 0) begin
if (hit == 1)
currentState <= 3'b000;
end
else
action <= 0;
end
assign state = currentState;
assign trigger = action;
endmodule
controller module:
module controller(
input clk,
input trigger,
input reset,
input plbust,
input dlbust,
input plbj,
input [2:0] state,
output [7:0] curPlHand,
output [7:0] curDlHand,
output dlhit,
output plhit,
output plwin,
output pllose,
output [7:0] plscore,
output [7:0] dlscore
);
reg [7:0] curPlHand;
reg [7:0] curDlHand;
reg [7:0] plscore;
reg [7:0] dlscore;
//reg plbust;
//reg dlbust;
//reg plscore;
//reg dlscore;
reg plhit = 0;
reg dlhit = 0;
reg plwin = 0;
reg pllose = 0;
//modes
//000 = start of game. score = 0 and no hand dealt
//001 = player dealt first card
//010 = player dealt second card
//011 = dealer dealt first card - wait for player to hit or pass
//100 = player hits
//101 = player passes -> dealer hits
//110 = payer wins
//111 = player loses
always #(*) begin
if (plbust == 1)
pllose <= 1;
else if (plbj == 1)
plwin <= 1;
else if (dlbust == 1)
plwin <= 1;
end
always #(posedge clk) begin
plhit <= 0;
dlhit <= 0;
if (state == 3'b000 && trigger) begin
curPlHand <= 8'b00000000;
curDlHand <= 8'b00000000;
if (reset == 1) begin
plscore <= 8'b00000000;
dlscore <= 8'b00000000;
end
end
else if (state == 3'b001 && trigger) begin
plhit <= 1;
end
else if (state == 3'b010 && trigger) begin
plhit <= 1;
end
else if (state == 3'b011 && trigger) begin
if (plbj == 1)
plwin <= 1;
else
dlhit <= 1;
end
else if (state == 3'b100 && trigger) begin
if (plbust == 1)
pllose <= 1;
else if (plbj == 1)
plwin <= 1;
else
plhit <= 1;
end
else if (state == 3'b101 && trigger) begin
if (dlbust == 1)
plwin <= 1;
else if (plbust == 1)
pllose <= 1;
else if (plbj == 1)
plwin <= 1;
else
dlhit <= 1;
end
/*else if (state == 3'b110) begin
end
else if (state == 3'b111) begin
end
*/
end
endmodule
random card generator module:
module randomGen (
input clk,
output card1,
output card2
);
reg [7:0] card1;
reg [7:0] card2;
always # (posedge clk) begin
card1 <= ({$random} % 51 >> 2) + 1;
card2 <= ({$random} % 51 >> 2) + 1;
end
endmodule
check for blackjack and bust module:
module checkBust (
input clk,
input handTotal,
output bust,
output blackJack
);
wire [7:0] handTotal;
reg blackJack;
reg bust;
always #(posedge clk) begin
if(handTotal == 8'd21) begin
bust <= 0;
blackJack <= 1;
end
else if(handTotal > 8'd21) begin
bust <= 1;
blackJack <= 0;
end
else begin
bust <= 0;
blackJack <= 0;
end
end
endmodule
debouncer for FPGA button presses:
module debouncer(
input clk,
input button_in,
output button_out
);
reg [1:0] button_buffer;
assign button_out = button_buffer[0];
always #(posedge clk or posedge button_in) begin
if (button_in)
button_buffer <= 2'b11;
else
button_buffer <= {1'b0, button_buffer[1]};
end
endmodule
Here is the testbench I am currently running:
module testBlackjack;
// Inputs
reg clk;
reg btnhit;
reg btnpass;
reg btnreset;
// Instantiate the Unit Under Test (UUT)
blackJack uut (
.clk(clk),
.btnhit(btnhit),
.btnpass(btnpass),
.btnreset(btnreset)
);
initial begin
// Initialize Inputs
clk = 0;
btnhit = 0;
btnpass = 0;
btnreset = 0;
// Wait 100 ns for global reset to finish
#1000;
$finish;
end
always #20 clk = ~clk;
endmodule
Here is a image of my simulation which is only testing the initial setup of the game by distributing 2 cards to the player and 1 card to the dealer:
As you can see from the simulation, the card 6 is being added to the players hand when plhit = 1 (this is addcard inside the player module). The correct value that should be displayed in plhand should be 00000110 but instead the 1's are X's.
The issue I am having is that when I am attempting to add a card to a player's total hand score (in 8 bits) the bits that should be a 1 are being set as X. I have tried restating plscore as a reg and tried multiple assigning operations however I have no luck. Any help would be greatly appreciated and if there is any information need I will be happy to respond quickly.
A couple if issue:
Fist off the header. You are mixing ANSI and non-ANSI header styles. This is illegal syntax. Some simulator/synthesizer is allowing it, but it is bad practice. I've already answered header related question in more depth here "object <name> is not declared in verlog" and "Issue with parameters in Modelsim" so I'll just summarize; follow ANSI or non-ANSI, don't blend header styles in the same module. You may use different header styles with different modules, but it is recommended to be consistent. I prefer ANSI style.
For example:
module clock(
input clk,
output vgaclk
);
reg vgaclk; // <-- this is mixing styles
...
module checkBust (
input clk,
input handTotal,
output bust,
output blackJack
);
wire [7:0] handTotal; // <-- these are mixing styles too
reg blackJack;
reg bust;
...
should be:
module clock(
input clk, reset,
output reg vgaclk
);
...
module checkBust (
input clk,
input [7:0] handTotal,
output reg bust,
output reg blackJack
);
...
Some signals (for example vgaclk) are not initialized. You could initialize them inline or an initial block, however it is recommended to reset them in an always block. This way you can restore the initial values without powering down the design. FPGAs have limited number of asynchronous reset flops, so use synchronous reset only. ASIC prefer using asynchronous reset flops to initialize all values and use synchronous reset for dynamic resets. Example:
always #(posedge clk) begin
if (reset) begin
hand <= 8'h0;
end
if (addCard == 1) begin
hand <= hand + card;
end
end
plhand and dlhand are begin driven by controller by player. Based on the code, it should only be assigned within player. controller should send a reset signal to player to set the value back to 0.
The last issue I can quickly spot is that following code is infers level-sensitive latches and assigned in two separate always blocks. Latches are not necessarily bad, but they have a higher change of glitching and should only be used when specifically requited. The fact the variables are assigned in two different always blocks will be a synthesis error. I believe you can safely delete the latching code.
always #(*) begin
if (plbust == 1)
pllose <= 1;
else if (plbj == 1)
plwin <= 1;
else if (dlbust == 1)
plwin <= 1;
end
You have to remember that signals in verilog represent physical circuitry. We refer to something that sets a value to a wire signal as a driver. Signals aren't allowed to have multiple drivers, as this can cause shorts (one driver want to put Vdd on a wire, while another connects it to ground).
In your case, both the controller and the player specify that they output to plhand, which makes both of them drivers. So when player want to write a 1 to a bit of plhand, the controller is still writing a 0, which causes a conflict. You should've gotten an error or warning that a signal had multiple drivers, which would let you know that you were getting this behavior.
In short, you can pass a wire between as many modules as you want, but only one of those modules can output to it. So, consider changing curPlHand from an output to an input.
NOTE: This is not the problem. See other answers/comments for more information.
In the player module, you don't set hand properly for all conditions. Specifically:
always #(posedge clk) begin
if (addCard == 1)
hand <= hand + card;
end
needs to handle addCard != 1. So try:
always #(posedge clk) begin
if (addCard == 1)
hand <= hand + card;
else
hand <= hand;
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