UPGRADE YOUR BROWSER

We have detected your current browser version is not the latest one. Xilinx.com uses the latest web technologies to bring you the best online experience possible. Please upgrade to a Xilinx.com supported browser:Chrome, Firefox, Internet Explorer 11, Safari. Thank you!

cancel
Showing results for 
Search instead for 
Did you mean: 
Visitor quesman1
Visitor
152 Views
Registered: ‎10-09-2018

Vivado register has strange timing and value reads in simulation

PROJECT DESCRIPTION (for context -- skip to the problem description for the TLDR):
A KeyFSM takes an input from a keypad, and in this example, the input of concern is C; when C is asserted in the CHECK_G state, it outputs a 4 on keyOut. Otherwise, it outputs 0xd. The FSM also sets the "press" output, to tell the synchronous register KeyPressReg to load the new value. The ports dIn show the incoming data to the register, and dOut shows the register's output. The "ld" signal is a "load" which enables writing to the register on a positive clock edge. Please note that both modules use a clock divider, which outputs s_clk; the s_clk is the actual clock signal that reaches these modules!
 
PROBLEM DESCRIPTION:
The keyPressReg (DReg.sv) is a basic register, using an always_ff @(posedge) to update its value dOut. I made a DReg_tb.sv simulation to test that it works properly, and it functions exactly as you would expect a register ought to. However, it doesn't work properly when part of the larger test bench for the project. 
 
Look at dIn and dOut on the register (keyPressReg), and you will see this strangeness: just before 25ns, dIn == 4, but on the posedge of the next sclk cycle, dOut is 1. And yet, dIn has *never* been 1 in all time of the simulation! Further, dOut updates on the posedge of the LD signal, which can't be right, given that the dOut should update on the *next* clock cycle. I really can't explain this.
 
err.png
 
MY CODE:
I put all of the project's code onto Github, and it can be viewed there without downloading (https://github.com/algoldst/CPE233Labs/tree/periph3) or downloaded from this link as a zip file: https://github.com/algoldst/CPE233Labs/archive/periph3.zip. It is also pasted below, for just the simulation test bench, the FSM, and the Register. (The whole project is larger and contains more modules, but they don't interact with these ones.
 
If you want to run my project, just unzip the file and add the entire directory to a Vivado project, setting KeyPadDriver and KeyPadDriver_tb as top; then run the sim for ~60ns. Finally, the board I am using is xc7a35tcpg236-1. 
 
Thanks for any help!
 
SIMULATION FILE:
 
`timescale 1ns / 1ps
module KeyPadDriver_tb(
    );
    logic clk;
    logic C = 0, A = 0, E = 0;  // columns 0,1,2 << PMOD
    logic [7:0] seg;   // sseg segments
    logic [3:0] an;    // sseg digit on/off
    logic B, G, F, D;  // rows B,G,F,D >> PMOD
    logic interrupt;
   
    KeyPadDriver #1 keyPadDriver_tb( .* );     // Low number for sim, 22727270 for actual use.
   
    always begin
        clk = 0; #5;
        clk = 1; #5;
    end
    
    initial begin
        #5;     // Wait 5 ns, then put C high while the FSM is in State CHECK_G --> 4  pressed
        C = 1;
        #20;
        C = 0;  // Finished with State CHECK_G, so this would go low again.     --> 13  "pressed"
        #80;
        C = 1;  // Put C high for CHECK_F                                       --> 7  pressed
        #20;
        C = 0;
        
    end    
endmodule
Key FSM:
`timescale 1ns / 1ps
module KeyFsm( input clk, input C, A, E, output logic B, G, F, D, output logic press, output logic [3:0] keyOut ); // States: Provides power to each row to check which (if any) column has power. <-- Multiplexor typedef enum {CHECK_B, CHECK_G, CHECK_F, CHECK_D} State; State NS, PS = CHECK_B; // PS/NS Logic always_ff @(posedge clk) begin PS <= NS; end always_comb begin // Set all outputs low initially B = 0; G = 0; F = 0; D = 0; if(C | A | E) press = 1; // If any column has power, press = 1 else press = 0; case(PS) CHECK_B: begin // 1, 2, 3 B = 1; if(C) keyOut = 1; else if(A) keyOut = 2; else if(E) keyOut = 3; else keyOut = 13; NS = CHECK_G; end CHECK_G: begin // 4, 5, 6 G = 1; if(C) keyOut = 4; else if(A) keyOut = 5; else if(E) keyOut = 6; else keyOut = 13; NS = CHECK_F; end CHECK_F: begin // 7, 8, 9 F = 1; if(C) keyOut = 7; else if(A) keyOut = 8; else if(E) keyOut = 9; else keyOut = 13; NS = CHECK_D; end CHECK_D: begin // *, 0, # (keypad "digits" represented as values xA, 0, xB) D = 1; if(C) keyOut = 10; else if(A) keyOut = 0; else if(E) keyOut = 11; else keyOut = 13; NS = CHECK_B; end default: begin // Should never get to this state. keyOut = 13; NS = CHECK_B; end endcase end endmodule
KeyPressed Register:
`timescale 1ns / 1ps
module DReg #(parameter WIDTH=1)(
    input clk, ld, set, clr,
    input [WIDTH-1:0] dIn,
    output logic [WIDTH-1:0] dOut = 0
    );
    always_ff @(posedge clk) begin
        if (clr) dOut <= 0;
        else if (set) dOut <= 1;
        else if (ld) dOut <= dIn;
        else dOut <= dOut;
    end
endmodule
0 Kudos