verilog asynchronous FIFO Wizard - verilog

How do you use the read enable to properly output a signal on a pin? I am using a ZyBo board and used a the FIFO Generator Wizard. I need an asynchronous, continuous writing to a FIFO and reading from the FIFO. This is why I need a write_enable signal and read_enable signal. However, I cannot read from the FIFO. I check to make sure the FIFO isn't empty and that read_enable is asserted. I read from the FIFO by serializing a 32bit word onto a data pin. (It alternates from serializing onto pin I and pin Q). How can I make sure I am reading from the FIFO and outputting the serialized data onto a pin? The following is my code:
// Wires and registers related to data capturing
wire capture_clk;
reg [31:0] capture_data;
wire capture_en;
reg [4:0] slowdown;
wire capture_full;
reg capture_open;
reg capture_open_cross;
reg capture_has_been_full;
reg capture_has_been_nonfull;
reg has_been_full_cross;
reg has_been_full;
// Data capture section
// ====================
always #(posedge capture_clk)
begin
if (capture_en)
capture_data <= user_w_write_32_data; // Data source being read from a file
// The slowdown register limits the data pace to 1/32 the bus_clk
// when capture_clk = bus_clk. This is necessary, because the
// core in the evaluation kit is configured for simplicity, and
// not for performance. Sustained data rates of 200 MB/sec are
// easily reached with performance-oriented setting.
// The slowdown register has no function in a real-life application.
slowdown <= slowdown + 1;
// capture_has_been_full remembers that the FIFO has been full
// until the file is closed. capture_has_been_nonfull prevents
// capture_has_been_full to respond to the initial full condition
// every FIFO displays on reset.
if (!capture_full)
capture_has_been_nonfull <= 1;
else if (!capture_open)
capture_has_been_nonfull <= 0;
if (capture_full && capture_has_been_nonfull)
capture_has_been_full <= 1;
else if (!capture_open)
capture_has_been_full <= 0;
end
// The dependency on slowdown is only for bogus data
assign capture_en = capture_open && !capture_full &&
!capture_has_been_full &&
(slowdown == 0);
// Clock crossing logic: bus_clk -> capture_clk
always #(posedge capture_clk)
begin
capture_open_cross <= user_r_read_32_open;
capture_open <= capture_open_cross;
end
// Clock crossing logic: capture_clk -> bus_clk
always #(posedge bus_clk)
begin
has_been_full_cross <= capture_has_been_full;
has_been_full <= has_been_full_cross;
end
// The user_r_read_32_eof signal is required to go from '0' to '1' only on
// a clock cycle following an asserted read enable, according to Xillybus'
// core API. This is assured, since it's a logical AND between
// user_r_read_32_empty and has_been_full. has_been_full goes high when the
// FIFO is full, so it's guaranteed that user_r_read_32_empty is low when
// that happens. On the other hand, user_r_read_32_empty is a FIFO's empty
// signal, which naturally meets the requirement.
assign user_r_read_32_eof = user_r_read_32_empty && has_been_full;
assign user_w_write_32_full = 0;
// The data capture clock here is bus_clk for simplicity, but clock domain
// crossing is done properly, so capture_clk can be an independent clock
// without any other changes.
assign capture_clk = bus_clk;
async_fifo_32x512 fifo_32 //FIFO created using Xilinx FIFO Generator Wizard
(
.rst(!user_r_read_32_open),
.wr_clk(capture_clk),
.rd_clk(bus_clk),
.din(capture_data),
.wr_en(capture_en),
.rd_en(user_r_read_32_rden),
.dout(user_r_read_32_data),
.full(capture_full),
.empty(user_r_read_32_empty)
);
reg Q_en = 1'b0; //starting value is 0 because first 32bit is I
reg [31:0] data_outI = 32'd0;
reg [31:0] data_outQ = 32'd0;
reg I = 1'b0;
reg Q = 1'b0;
reg counter_32_shift = 6'b000000;
reg temp = 1'b0;
always #(posedge bus_clk) begin
if(user_r_read_32_empty == 1'b0 && user_r_read_32_rden == 1'b1)begin //if something in FIFO
if(Q_en == 1'b0) begin //output onto pin I
if(counter_32_shift == 6'b000000) begin
data_outI <= user_r_read_32_data;
end else if(counter_32_shift != 5'd32) begin
I <= data_outI[0];
data_outI <= (data_outI >> 1);
Q <= data_outQ[0];
data_outQ <= (data_outQ >> 1);
counter_32_shift <= counter_32_shift + 1'b1;
end else begin //counter_32_shift == 32
I <= data_outI[0];
data_outI <= (data_outI >> 1);
Q <= data_outQ[0];
data_outQ <= (data_outQ >> 1);
counter_32_shift <= 6'd0;
Q_en <= ~Q_en;
end
end else if(Q_en == 1'b1) begin //Output onto pin Q
if(counter_32_shift == 6'd0) begin
data_outQ <= user_r_read_32_data;
end else if(counter_32_shift != 6'd32) begin
I <= data_outI[0];
data_outI <= (data_outI >> 1);
Q <= data_outQ[0];
data_outQ <= (data_outQ >> 1);
counter_32_shift <= counter_32_shift + 1'b1;
end else begin //counter_32_shift == 32
I = data_outI[0];
data_outI <= (data_outI >> 1);
Q = data_outQ[0];
data_outQ <= (data_outQ >> 1);
counter_32_shift <= 6'd0;
Q_en <= ~Q_en;
end
end// end Q_en compare
end //end check if FIFO empty
end //end always
Thanks in advance for all the help

You need to design a bit better the way you write your clocked logic.
For example, in your code, you only write to I and Q if the fifo is not empty, which is not correct.
You need a module which:
Takes in a 32-bit value from the fifo, stores it, and then serializes it out to a pin over 32 cycles.
Once a value has been read in from the fifo, it needs to keep serializing regardless of whether or not the fifo is empty (you only care about the state of the fifo when you're pulling in a new 32-bit value).
Only accepts a new value when it is not currently doing serialization.
The design looks to be making progress since your last question, but you haven't got the logic right yet. Try using a waveform debugger to understand better why it's not working the way you expect.

Related

Verilog FSM being optimised away

New to Verilog, Basys3 board and Vivid 2021.2.
Trying to implement a typical stopwatch with Stop/Start and Lap/Reset buttons.
A divider produces 1kHz and 100Hz clock from the board clock, 100Hz is for button debounce (and seven segment display multiplexing, next todo), the 1kHz drives a 20 bit 5 x 4 bit BCD counter, the low 16 bits of which drive a latch to freeze the display, the latch drives the 16 on board LEDs.
I've test 'wired' this up and the modules perform as expected. It's only when I add the FSM I run into trouble.
The FSM is simple, the two buttons determine the state changes and the state sets three outputs to control the counter.
The state module as been through many versions, tried using buttons in the sensitivity list, tried with button edges and levels, tried *, tried blocking and non-blocking assignments, can't get it right. The current error is:
[Synth 8-3332] Sequential element (state/transfer_reg) is unused and will be removed from module stopwatch.
The error changes but it's always Synth 8-3332 removing something, even curr_state or next_state.
The RTL synthesis schematic shows exactly what I expect, later schematics show the two buttons, 16 LEDs and nothing in between.
I'm lost at this stage, have I missed something fundamental?
`timescale 1ns / 1ps
////////////////////////////////////////////////////////////////////////////////
//
// Create Date: 02/02/2022 0800
//
// Module Name: state
// Project Name: Stop Watch
// Target Devices: BASYS 3
//
// state machine
//
// inputs:
// start-stop button via debounce (both edg and level are available)
// lap-reset buttonvia debounce (both edg and level are available)
//
// outputs:
// control 4 x 4 bit BCD counters and output latch
// clear state
// enabvble couter to count
//. transfer counter value to latch
//
////////////////////////////////////////////////////////////////////////////////
module state (
input clk,
input lap_reset,
input start_stop,
output reg clear,
output reg enable,
output reg transfer
);
// state encodings
localparam
RESET_0 = 3'd0,
STOPPED_1 = 3'd1,
RUNNING_2 = 3'd2,
PRELAP_3 = 3'd3,
LAP_4 = 3'd4;
// state reg
reg[2:0] curr_state;
reg[2:0] next_state;
// setup
initial
begin
curr_state <= RESET_0;
next_state <= RESET_0;
enable <= 0;
clear <= 0;
transfer <= 0;
end
// sync state transitons to clk
// always # (posedge clk)
// begin
// curr_state <= next_state;
// end
// state machine
always # (posedge clk)
begin
curr_state <= next_state;
case (curr_state)
RESET_0:
begin
// init, stop counter, clear counter
// transfer count to latch
enable <= 0;
clear <= 1;
transfer <= 1;
next_state <= STOPPED_1;
end
STOPPED_1:
begin
// stop counter, clear counter
enable <= 0;
clear <= 0;
transfer <= 0;
if (start_stop)
next_state <= STOPPED_1;
else if (lap_reset)
next_state <= RESET_0;
else
next_state <= curr_state;
end
RUNNING_2:
begin
// start or continue counting
// transfer count to latch
enable <= 1;
clear <= 0;
transfer <= 1;
if (start_stop)
next_state <= STOPPED_1;
else if (lap_reset)
next_state <= PRELAP_3;
else
next_state <= curr_state;
end
PRELAP_3:
begin
// start or continue counting
// don't update latch
enable <= 1;
clear <= 0;
transfer <= 0;
next_state <= LAP_4;
end
LAP_4:
begin
// continue counting
// transfer counter to latch
enable <= 1;
clear <= 0;
transfer <= 1;
if (start_stop)
next_state <= RUNNING_2;
else if (lap_reset)
next_state <= PRELAP_3;
else
next_state <= curr_state;
end
default:
begin
enable <= 0;
clear <= 0;
transfer <= 0;
next_state <= RESET_0;
end
endcase
end
endmodule
Getting somewhere at last, thankyou all.
After correcting a logical error and a couple of constants 0'b0 which make little sense (the compiler didn't complain about them) and doing suggested fixes my stopwatch works.
The SM structure is the 3 blocks, sync transitions, next state 'gotos' and state actions. I started with the suggested always # (*) but had to change to a posedge clk for it to work, not sure why.
Got rid of the inferred latches and now understand why they come about.
About generating a reset signal, I assume the Artix chip has one but it doesn't get a mention in the supplied xdc file, I was trying to simulate a reset held low (active) then going high a short time later, determined by a clock divider - which should have a reset... Also read Xilinx WP272 which tells a different story.
Thanks again.
Just from www.javatpoint.com/verilog-initial-block:
"An initial block is not synthesizable and cannot be converted into a
hardware schematic with digital elements. The initial blocks do not
have more purpose than to be used in simulations. These blocks are
primarily used to initialize variables and drive design ports with
specific values."
I am not sure now about the code for that FPGA, but in common ASICs I would remove the "initial" code section, which you use to implement the reset behaviour and add an actual reset section in the always#.
always#(posedge clk)
begin
if (rst) begin
// do the reset
curr_state <= RESET_0;
next_state <= RESET_0;
enable <= 0;
clear <= 0;
transfer <= 0;
end else begin
// the rest
end
end
EDITED:
Never leave a signal without a default value, as it will infer latches instead of flip-flops, which create problems when inferring sequential logic (of course latches are useful in some scenarios).
When one wants to build a finite state machine (FSM) there are two common approaches: Mealy and Moore. I will explain how the sequential logic should be implemented with a Moore FSM:
A synchronous always# block to write the state: cur_state <= next state.
A combinational block to generate next_state value based on cur_state and inputs.
A combinational block to generate outputs based on the state.
always#(posedge clk, rst)
begin
if (rst = '1') begin
cur_state <= State_0;
end else begin
cur_state <= next_state;
end
end
always_comb(cur_state, my_inputA)
begin
if (cur_state = State_0) begin
if(my_inputA)
next_state = State_1;
else
next_state = Stage_0;
end else if (cur_state = State_1) begin
next_state = State_2;
end
end
always_comb(cur_state)
begin
if (cur_state = State_0) begin
my_outputA = '1';
end else if (cur_state = State_1) begin
my_outputA = '0';
end else if (cur_state = State_2) begin
my_outputA = '1';
end
end

SIPO (Serial Input Parallel Output) FSM synthesis problem

I want to write a Serial to Parallel conversion in Verilog, and I can't realize what is wrong with my code. It doesn't synthesize, and not even the ISE shows what the problem is. Can anyone help me?
I guess the problem is around the second always block. The part:
if (STATE == TRANSMIT)
PAR_OUT[COUNTER] = SER_IN;
seems wrong to me, but I can't understand what to change or test.
module SIPO(
input SER_IN,
input RST,
input CLK,
input LOAD,
output reg READY,
output reg [7:0] PAR_OUT
);
parameter IDLE = 2'b00, START = 2'b01, TRANSMIT = 2'b10, STOP = 2'b11;
reg [1:0] STATE;
reg [2:0] COUNTER;
always # ( posedge CLK or negedge RST)
if (~RST)
begin
STATE <= IDLE;
READY <= 1;
COUNTER <= 0;
end
else
begin
if (STATE == IDLE)
begin
READY <= 1;
COUNTER <= 0;
if (LOAD)
begin
STATE <= START;
end
else
STATE <= IDLE;
end
else
if (STATE == START)
STATE <= TRANSMIT;
else
if (STATE == TRANSMIT)
begin
COUNTER <= COUNTER + 1;
if (COUNTER == 7)
STATE <= STOP;
end
else
begin
STATE <= IDLE;
READY <= 1;
end
end
always #( * )
begin
if (STATE == IDLE)
PAR_OUT = 1;
else
if (STATE == START)
PAR_OUT = 0;
else
if (STATE == TRANSMIT)
PAR_OUT[COUNTER] = SER_IN;
else
PAR_OUT = 1;
end
endmodule
I think your suspicion might be correct regarding PAR_OUT[COUNTER]. When I synthesize your code on edaplayground with Yosys, it infers latches for PAR_OUT, which you likely do not want.
PAR_OUT is 8 bits wide, but you only assign 1 of the 8 bits at a time in the TRANSMIT state, which means the other 7 bits retain their state. For example, if COUNTER=3, then only PAR_OUT[3] is assigned.
I recoded your combo logic, simplifying it with a case statement to make the issue more evident (it should be functionally equivalent to your if/else code):
always #* begin
case (STATE)
TRANSMIT: PAR_OUT[COUNTER] = SER_IN; // Assign to only 1 bit <---
START : PAR_OUT = 8'h00; // Assign to all 8 bits
default : PAR_OUT = 8'h01; // Assign to all 8 bits
endcase
end
If you can afford one cycle of latency, you could use sequential logic for PAR_OUT, such as a shift register.

I2C slave module in Verilog does not acknowledge

I wrote this I2C slave module in Verilog:
module I2CSlave(
input iSCL,
input iI2C_CLK,
inout bSDA,
output reg [7:0] odata,
output reg oread,
output wire oactive
);
reg incycle = 1'b0;
reg pSDA;
reg pSCL;
always #(posedge iI2C_CLK) begin
if ((pSCL) && (iSCL) && (pSDA) && (~bSDA)) begin
incycle <= 1;
end
if ((pSCL) && (iSCL) && (~pSDA) && (bSDA)) begin
incycle <= 0;
end
pSDA <= bSDA;
pSCL <= iSCL;
end
assign oactive = incycle;
localparam STATE_IDLE = 0;
localparam STATE_ADDR = 1;
localparam STATE_RW = 2;
localparam STATE_ACK = 3;
localparam STATE_DATA = 4;
localparam STATE_ACK2 = 5;
reg [7:0] i = 0;
reg [7:0] state = STATE_IDLE;
reg [6:0] addr = 7'h03;
reg addr_match = 1;
reg rw;
reg lSDA;
always #(posedge iSCL) lSDA <= bSDA;
assign bSDA = ((state == STATE_ACK) || (state == STATE_ACK2)) ? 0 : 1'bz;
assign oread = (state == STATE_ACK2);
assign ostate = i;
always #(negedge iSCL or negedge incycle) begin
if (~incycle) begin
state <= STATE_IDLE;
addr_match <= 1;
end
else if (addr_match) begin
case (state)
STATE_IDLE: begin
state <= STATE_ADDR;
i <= 7;
end
STATE_ADDR: begin
if (addr[i-1] != lSDA) addr_match <= 0;
if (i == 1) begin
state <= STATE_RW;
i <= i - 1;
end
else i <= i - 1;
end
STATE_RW: begin
rw <= lSDA;
state <= STATE_ACK;
end
STATE_ACK: begin
state <= STATE_DATA;
i = 7;
end
STATE_DATA : begin
odata[i] <= lSDA;
if (i == 0) state <= STATE_ACK2;
else i <= i - 1;
end
STATE_ACK2: begin
state <= STATE_DATA;
i = 7;
end
endcase
end
end
endmodule
As of now it should just read the data sent by master. It seems to work well in simulation, but when I upload it into the FPGA, sometimes everything is OK, however sometimes it does not acknowledge the data sent by master and it just seems to ignore them. I am newbie in Verilog, so I hope, this is not a silly question.
One possible cause for random fails while running on real hardware is that you didn't synchronize inputs.
You are sampling slowly changing signals (i2c bus will have a long slopes) that are truly asynchronous to your design's clock. Depending on your luck, you will have random violations for setup/hold times of your fpga's d-flops, which results in metastability issues. The same value in the register might be treated differently in multiple parts of the chip. That will wreak havoc in your i2c slave's logic.
You must synchronize asynchronous inputs, in the simplest case passing it through a couple of registers before feeding it to the module's fsm.
You have several issues with your code which could cause mismatch in behavior in simulation and synthesis. For example, the following is not synthesizable and is ignored by synthesis tools. So, your initial state would be different. Check your logs for warnings. Do not use declaration assignments for regs. (ok for wires).
reg [7:0] i = 0;
reg [7:0] state = STATE_IDLE;
reg [6:0] addr = 7'h03;
reg addr_match = 1;
The above means that you initialization does not work.
You messed up blocking and non-blocking assignments in the state machine. Make sure that you use nbas in all places where 'i = 7'. it should be
i <= 7;
And make sure that you test enough initialization and different conditions in simulation.

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.

Keybord interface design in Verilog

I am new to Verilog and I am trying to create one of my first programs which should display something when key on keybord is pressed. I'd like to use example code from Verilog coursebook, but I have some problems with pin assingment (I use DE2-70 from Altera).
Why I have input ReadKB; while there is nothing like this in module definition?
I know which pins should be assign to KBclk and KBdata. (PS2_KBCLK PIN_F24 PS/2 Clock and (PS2_KBDAT PIN_E24 PS/2 Data) What about ResetKB?
In the coursebook there is no explanation and I am really courious about it.
Code:
module KeyboardInterface(KBclk, KBdata, ResetKB, SYNclk, ScanRdy, ScanCode, KeyReleased);
input KBclk;
input KBdata;
input ResetKB;
input ReadKB;
input SYNclk;
output ScanRdy;
output ScanCode;
output KeyReleased;
//Generate an internal synchronized clock
reg Clock;
always #(posedge SYNclk) Clock = KBclk;
reg[3:0] BitCount;
reg StartBitDetected, ScanRdy;
reg[7:0] ScanCode;
//Count the number of serial bits and collect data into ScanCode
always #(posedge Clock) begin
if(ResetKB) begin
BitCount=0; StartBitDetected =0;
end else begin
if(KBdata == 0 && StartBitDetected == 0) begin
StartBitDetected=1;
ScanRdy = 0;
end else if (StartBitDetected) begin
if(BitCount < 8) begin
BitCount = BitCount + 1;
ScanCode = {KBdata, ScanCode[7:1]};
end else begin
StartBitDetected = 0;
BitCount = 0;
ScanRdy = 1;
end
end
end
end
reg [1:0] CompletionState;
wire KeyReleased;
//keep track of the state of Scan Codes outputted
always #(posedge SYNclk) begin
if(ResetKB) CompletionState = 0;
else case(CompletionState)
0: if(ScanCode == 8'h70 && ScanRdy == 1) CompletionState =1;
else CompletionState =0;
1: if(ScanRdy == 1) CompletionState =1;
else CompletionState =2;
2: if(ScanRdy == 0) CompletionState = 2;
else CompletionState = 0;
3: CompletionState = 0;
endcase
end
assign KeyReleased = CompletionState == 3 ? 1 : 0;
endmodule
Thank you!
That looks like a typo, just go ahead and add the missing wire to the module definition.
There's probably not actually a 'reset' coming from your keyboard if that's what you're asking. I'd just tie it to some pushbutton on the Altera if it is available.
It is just a high-level reset signal. You can just connect it with a push button, then you can use the push button to reset the reg signals, bitcount and startbitdetect.
But one crucial thing you should note is that reg signals can not use "=" inside the always section, it should be "<=". This is the difference between blocking and non-blocking assignment that you should pay more attentions on. Good luck.:-)

Resources