How to filter keyboard events? - keyboard

I'm writing an pong game vhdl code for spartan 3E starter kit. I want to control the game pad with my PS2 keyboard. For this i need to generate up and down signals from the keyboard received scan code.
Here's sample code
-- Instantiate key_board controller
my_keyobard : entity work.ps2_key(Behavioral)
port map( ps2_clk => ps2_clk, ps2_data => ps2_data, clk => clk,
data_out => data);
process(data)
begin
case data is
when X"15" => up <= '1'; -- Q key for UP
when X"1C' => down <= '1'; -- A key for DOWN
when others => up <= '0'; down <= '0';
end case;
end process;
But if I use this code the up key will remain '1' HIGH always, even after relesing the Q key on the keyboard. I want up signal to remain to high only till i hold the Q button down if I release it then up signal must return to '0'. Basically i want my keyboard keys to function like normal button.
If i press and hold then it must give HIGH signal else if released it must give LOW signal.

others clauses are ignored by synthesis (usually, unless you tell them not to)
process(data)
begin
up <= '0'; down <= '0';
case data is
when X"15" => up <= '1'; -- Q key for UP
when X"1C" => down <= '1'; -- A key for DOWN
end case;
end process;
Have you simulated - it should work fine in simulation the way you had it.

I believe PS2 keyboard Protocol sends a command word, then the keyboard code when the button is pressed, then two command words and a keyboard code when released. Are you dealing with this elsewhere? We need to know more about your "Data out" from your keyboard controller. Does it latch the data signal from the keyboard? If you have data reset when the key is released then your code should work as desired.
Page 8 is what I am talking about
http://www.cse.nd.edu/courses/cse20221/www/handouts/L21_%20PS2%20Keyboard.pdf

The PS/2 keyboard protocol is more complicated than that. You'll need to implement a stateful decoder.
In brief:
When nothing happens, both ps2_data and ps2_clk are always '1'.
On an event, a keyboard sends a start bit (0), data bits one-by-one, then a stop bit (1). The bits are clocked with ps2_clk.
When a key is pressed and held, the scan code is sent repeatedly with a certain interval.
When a key is depressed, 'F0' code, then the scan code, is sent (it's a bit more complex for so-called "extended" keys that include the arrow keys).
See Xilinx Spartan-3E FPGA Starter Kit Board User Guide, "PS/2 Mouse/Keyboard Port" section, and/or generic PS/2 electric protocol description (the latter essentially repeats the former in more detail).

Related

Verilog module generates impossible data when running on FPGA

I’m developing a boolean data logger on a ZYNQ 7000 SoC. The logger takes a boolean input from GPIO and logs the input’s value and the time it takes to flip.
I use a 32-bit register as a log entry, the MSB bit is the boolean value. The 30:0 bits is an unsigned integer which records the time between last 2 flips. The logger should work like the following picture.
Here's my implementation of the logger in Verilog. To read the logged data from the processor, I use an AXI slave interface generated by vivado and inline my logger in the AXI module.
module BoolLogger_AXI #(
parameter BufferDepth = 512
)(
input wire data_in, // boolean input
input wire S_AXI_ACLK, // clock
input wire S_AXI_ARESETN, // reset_n
// other AXI signals
);
wire slv_reg_wren; // write enable of AXI interface
reg[31:0] buff[0:BufferDepth-1];
reg[15:0] idx;
reg[31:0] count;
reg last_data;
always #(posedge S_AXI_ACLK) begin
if((!S_AXI_ARESETN) || slv_reg_wren) begin
idx <= 0;
count <= 1;
last_data <= data_in;
end else begin
if(last_data!=data_in) begin // add an entry only when input flips
last_data <= data_in;
if(idx < BufferDepth) begin // stop logging if buffer is full
buff[idx] <= count | (data_in << 31);
idx <= idx + 1;
end
count <= 1;
end else begin
count <= count + 1;
end
end
end
//other AXI stuff
endmodule
In the AXI module, the 512*32bit logged data is mapped to addresses from 0x43c20000 to 0x43c20800.
In the Verilog code, the logger adds a new entry only when the boolean input flips. In simulation, the module works as expected. But in the FPGA, sometimes the logged data is not valid. There are successive 2 data and their MSB bit is the same, which means the entry is added even when the boolean input stays the same.
The invalid data appear from time to time. I've tried reading from the address programmatically (*(u32*)(0x43c20000+4*idx)), and there are still invalid data. I watch idx in a ILA module and idx is 512, which means the logging finishes when I read the data.
The FPGA clock is 10 MHz. The input signal is 10 Hz. So the typical period is 10e6/10/2=0x7A120, which most of the data is close to, except the invalid data.
I think if the Verilog code is implemented well, there should be no such invalid data. What may be the problem? Is this an issue about timing?
The code
First off, are you absolutely sure you are not issuing an accidental write on the AXI bus, resetting the registers?
If so, have you tried inserting a so-called double-flop on data_in (two flip-flops, delaying the signal two clock ticks)? I suppose that your data_in is not synchronous to the FPGA clock, which will lead to metastability and you having bad days if not accounted for. Have a look here for information by NANDLAND.
Citing the linked source:
If you have ever tried to sample some input to your FPGA, such as a button press, or if you have had to cross clock domains, you have had to deal with Metastability. A metastable state is one in which the output of a Flip-Flop inside of your FPGA is unknown, or non-deterministic. When a metastable condition occurs, there is no way to tell if the output of your Flip-Flop is going to be a 1 or a 0. A metastable condition occurs when setup or hold times are violated.
Metastability is bad. It can cause your FPGA to exhibit very strange behavior.
In that source there is also a link to a white paper from Altera about the topic of metastability, linked here for reference.
Citing from that paper:
When a metastable signal does not resolve in the allotted time, a logic failure can result if the destination logic observes inconsistent logic states, that is, different destination registers capture different values for the metastable signal.
and
To minimize the failures due to metastability in asynchronous signal transfers, circuit designers typically use a sequence of registers (a synchronization register chain or synchronizer) in the destination clock domain to resynchronize the signal to the new clock domain. These registers allow additional time for a potentially metastable signal to resolve to a known value before the signal is used in the rest of the design.
Basically having the asynchronous signal routed to two flip-flops might for example lead to one FF reading a 1 and one FF reading a 0. This in turn could lead to the data point being saved, but the counter not being reset to 0 (hence doubling the measured time) and the bit being saved as 0.
Finally, it seems to me, that you are using the Vivado-generated example AXI core. Dan Gisselquist simply calls it "broken". This might not be the problem here, but you might want to have a look at his posts and his AXI core design.

Verilog: Understanding multiple driver on bidirectional signal

I am debugging some Verilog code and I'm having some difficulty understanding a bidirectional signal with multiple drivers:
The verilog code looks like this:
inout a;
assign a = b ? c : 1'bz
a=Stx b=St1 c=St0
assign (weak0, weak1) a = d ? 1'bz : (e ? 1'b0 : (f ? 1'b1 : 1'bz));
a=Stx d=St0 e=St0 f=St0
Signal c is the actual data that needs be transmitted to a (output pad). When I run the simulation using a commercial simulator, I get the values annotated above. I don't understand why a ends up being X throughout the simulation. b is toggling and c is also toggling. d/e/f are always 0. The 2nd statement is using a weak pull-up/pull-down but by setting it d/e/f=0, it should drive Z. So the other statement should win out?
With your code above, you are in essence creating a bidirectional buffer which is one input buffer from IO pad to internal signal, and an output buffer from internal signal to IO pad that is controlled by an enable. The b signal is the enable on one side and the d signal is the enable on the other side.
Remember that a bidirectional signal or bus must still have some kind of arbitration on it, something that understands the bidirectional transactions that are occurring as both sides should not be enabling their output buffers at the same time.

How do I specify weak feedback inverter in Verilog

I have a normal inverter IV1(.in(a), .out(b)) driven by a controlled inverter IV0(.c(ctrl),.in(d),.out(a)). For IV0, When ctrl is 1, output is driven. Otherwise, it is left floating.
In the meantime, there is a weak feedback inverter IVW(.in(b), .out(a)).
The value of node a is driven by IV0 when ctrl is 1. When ctrl is 0, node a is driven by weak feedback inverter.
When IV0 drives node a, weak feedback inverter IVW is driving node a as well. If they drive node a to different values, verilog will produce X.
How can I write this in verilog?
original answer
module buf(input d,ctrl, output b);
reg a,b;
always # (d or ctrl) begin
if(ctrl==1) begin
a=~d;
b=~a;
end
else begin
a=~b;
b=~a;
end
end
endmodule
commented by Morgan
This will not work the same way after synthesis as your current RTL
simulation. You really need to use always #* to ensure RTL and gate
level will match.
To specify a weak inverter:
not (weak1,weak0) u0 (out0,in1);
For more info.
IV0(.c(ctrl), .in(d), .out(a)); //out is z when crtl==0
IV1( .in(a), .out(b));
IVW( .in(b), .out(a)); //out has weak drive
When ctrl is 1 we only really have this in play :
IV1( .in(a), .out(b));
IVW( .in(b), .out(a));
This is a timing loop likely resulting in an unstable oscilator.

Reconstructing variable sized packets in verilog

I am trying to reconstruct a packet that was sent via UART RS232 connections, but am not sure how to reconstruct the packet in its entirety such that the packet can be taken apart and stuff can be done using it.
The issue is that when I receive 1 byte at a time, I store that byte into a register 8 bits wide, and when I receive the next byte, I want to be able to shift the first byte by 8 bits, then add the new byte to the end. This becomes an issue as the register is now too small (8 bits vs 16 bits to hold the next byte). In addition, I cannot see a way to change the size of the register during runtime to grow and shrink depending on the size of the packet, as all registers must be static, and I also must know the exact size of the packet in order to process it.
There is the possibility of setting up an insanely large register to hold the packet, and counting how many valid bytes were copied into the register, but I am sure there is a better way to do this that I am not seeing.
All this is done using Xilinx ISE.
Verilog is static to mimic physical design. You will need to know the maximum number of bytes that can be supported. To know the size of the input, simply incompetent a counter as the data bytes shift. The only way to have a dynamic size is if this is for non-synthesizable behavior modeling then you can use C code to link into your design (PLI/VPI/DPI) or SystemVerilog Queues (IEEE Std 1800-2012 section 7.10). Read-up about SystemVerilog if you are interested.
The follow is a Verilog example of a large shift register:
parameter SIZE = 2**10;
reg [SIZE*8-1:0] store;
always #(posedge clk or negedge rst_n) begin
if ( !rst_n ) begin
counter <= 0;
store <= {(SIZE*8){1'b0}};
end
else if ( push_in ) begin
counter <= first_byte ? 0 : (counter+1);
store <= {store[SIZE*8-1-8:0], data_in[7:0]};
end
end
With an "insanely large register" you may need to break up the store into chunks so the simulator can handle it; some simulators cannot handle reg [2**32-1:0] store;. Sudo code example:
// ...
storeN <= {store3[SIZE*8-1-8:0], storeM[7:0]};
// ...
store1 <= {store1[SIZE*8-1-8:0], store0[7:0]};
store0 <= {store0[SIZE*8-1-8:0], data_in[7:0]};
// ...

Asynchronous FIFO Design

I found the following piece of code in the internet , while searching for good FIFO design. From the linkSVN Code FIFO -Author Clifford E. Cummings . I did some research , I was not able to figure out why there are three pointers in the design ?I can read the code but what am I missing ?
module sync_r2w #(parameter ADDRSIZE = 4)
(output reg [ADDRSIZE:0] wq2_rptr,
input [ADDRSIZE:0] rptr,
input wclk, wrst_n);
reg [ADDRSIZE:0] wq1_rptr;
always #(posedge wclk or negedge wrst_n)
if (!wrst_n) {wq2_rptr,wq1_rptr} <= 0;
else {wq2_rptr,wq1_rptr} <= {wq1_rptr,rptr};
endmodule
module sync_w2r #(parameter ADDRSIZE = 4)
(output reg [ADDRSIZE:0] rq2_wptr,
input [ADDRSIZE:0] wptr,
input rclk, rrst_n);
reg [ADDRSIZE:0] rq1_wptr;
always #(posedge rclk or negedge rrst_n)
if (!rrst_n) {rq2_wptr,rq1_wptr} <= 0;
else {rq2_wptr,rq1_wptr} <= {rq1_wptr,wptr};
endmodule
What you are looking at here is what's called a dual rank synchronizer. As you mentioned this is an asynchronous FIFO. This means that the read and write sides of the FIFO are not on the same clock domain.
As you know flip-flops need to have setup and hold timing requirements met in order to function properly. When you drive a signal from one clock domain to the other there is no way to guarantee this requirements in the general case.
When you violate these requirements FFs go into what is called a 'meta-stable' state where there are indeterminate for a small time and then (more or less) randomly go to 1 or 0. They do this though (and this is important) in much less than one clock cycle.
That's why the two layers of flops here. The first has a chance of going meta-stable but should resolve in time to be captured cleanly by the 2nd set of flops.
This on it's own is not enough to pass a multi-bit value (the address pointer) across clock domains. If more than one bit is changing at the same time then you can't be sure that the transition will be clean on the other side. So what you'll see often in these situations is that the FIFO pointers will by gray coded. This means that each increment of the counter changes at most one bit at a time.
e.g. Rather than 00 -> 01 -> 10 -> 11 -> 00 ... it will be 00 -> 01 -> 11 -> 10 -> 00 ...
Clock domain crossing is a deep and subtle subject. Even experienced designers very often mess them up without careful thought.
BTW ordinary Verilog simulations will not show anything about what I just described in a zero-delay sim. You need to do back annotated SDF simulations with real timing models.
In this example, the address is passed through the shift register in order for it to be delayed by one clock cycle. There could have been more “pointers” in order to delay the output even more.
Generally, it is easier to understand what is going on and why if you simulate the design and look at the waveform.
Also, here are some good FIFO implementations you can look at:
Xilinx FIFO Generator IP Core
Altera's single/double-clock FIFOs
OpenCores Generic FIFOs
Hope it helps. Good Luck!

Resources