Jump to content
  • 1

Cannot read data with microblaze mcs (simple verilog program on nexys video)


ChaC73

Question

Hi there, 

I am quite new to FPGA and would like first to apologize if my question is *stupid* :-)

I have read already quite a lot and I am kind of stuck. Any help appreciated ?

Hardware 

Card: Nexys Video

Vivado 2016.4

What I would like to do

I have an external TTL signal (3.3 V, 1 kHz) connected to the Pmod A, ja[0] pin (and the ground to GNB) . 

As a test, I would like to read this signal, fill a FIFO and then read the FIFO buffer when the buffer is full. I do not mind to lose data; I just want to see (on the computer) some raw data once in a while. 

ISSUES

From the SDK terminal, I receive weird data like "²’ÒŠRj$ª²šÒŠRj$ª²¢". 

 

My top module 

`timescale 1ns / 1ps

module oscillo(clk, uart_rx_out, TTL_in,sw);

input clk;
input sw;
input  [0:0] TTL_in;  // These are input data

output uart_rx_out;

reg [0:0] TTL_in_reg; always @(posedge clk) TTL_in_reg <= TTL_in;


wire [0:0] q_fifo; // These are output data
    
  fifo_generator_0 myFifo (
  .clk(clk),      // input wire clk
  .din(TTL_in_reg),      // input wire [0 : 0] din
  .wr_en(wrreq),  // input wire wr_en
  .rd_en(rdempty),  // input wire rd_en
  .dout(q_fifo),    // output wire [0 : 0] dout
  .full(wrfull),    // output wire full
  .empty(wrempty)  // output wire empty
);

// The flash ADC side starts filling the fifo only when it is completely empty,
// and stops when it is full, and then waits until it is completely empty again
reg fillfifo;
always @(posedge clk)
if(~fillfifo)
  fillfifo <= wrempty; // start when empty
else
  fillfifo <= ~wrfull; // stop when full

assign wrreq = fillfifo;
assign rdempty = ~ fillfifo;

microblaze_mcs_0 myMCS (
  .Clk(clk),                        // input wire Clk
  .Reset(sw),                    // input wire Reset
  .GPI1_Interrupt(GPI1_Interrupt),  // output wire GPI1_Interrupt
  .INTC_IRQ(INTC_IRQ),              // output wire INTC_IRQ
  .UART_txd(uart_rx_out),              // output wire UART_txd
  .GPIO1_tri_i(fillfifo),        // input wire [0 : 0] GPIO1_tri_i
  .GPIO2_tri_i(q_fifo)        // input wire [0 : 0] GPIO2_tri_i
);


endmodule

My xdc file

## FPGA Configuration I/O Options
set_property CONFIG_VOLTAGE 3.3 [current_design]
set_property CFGBVS VCCO [current_design]

set_property -dict { PACKAGE_PIN AB22  IOSTANDARD LVCMOS33 } [get_ports { TTL_in }]

## Board Clock: 100 MHz

set_property -dict { PACKAGE_PIN R4    IOSTANDARD LVCMOS33 } [get_ports { clk }]; 
create_clock -add -name clk_100m -period 10.00 [get_ports clk]

## Reset Switch

set_property -dict {PACKAGE_PIN E22 IOSTANDARD LVCMOS12} [get_ports {sw}];


set_property -dict { PACKAGE_PIN AA19  IOSTANDARD LVCMOS33 } [get_ports { uart_rx_out }]

My helloword.c for the sdk

#include <stdio.h>
#include "platform.h"
#include "xil_printf.h"
#include "xparameters.h" // add
#include "xiomodule.h" // add

volatile char int_flag = 0;    // millisecond counter variable
//function which is called by the GPI interrupt when one of its bits goes hi
void MyInterruptFlagSet( void* ref) {
  int_flag = 1; // when it receives interrupt, set c
}
int main()
{
    init_platform();
    u32 data;
    u16 my_secs = 0;
    XIOModule gpi;

    //print("Setting up GPI\n\r");
    data = XIOModule_Initialize(&gpi, XPAR_IOMODULE_0_DEVICE_ID);
    data = XIOModule_Start(&gpi);

    //setting up interrupt handlers and enables them
    microblaze_register_handler(XIOModule_DeviceInterruptHandler,
                                  XPAR_IOMODULE_0_DEVICE_ID); // register the interrupt handler
    // Makes the connection between the Id of the interrupt source and the associated handler that is to run when the interrupt is recognized.
    XIOModule_Connect(&gpi, XIN_IOMODULE_GPI_1_INTERRUPT_INTR, MyInterruptFlagSet,
                            NULL); // register timerTick() as our interrupt handler
    XIOModule_Enable(&gpi, XIN_IOMODULE_GPI_1_INTERRUPT_INTR); // enable the interrupt
    microblaze_enable_interrupts(); // enable global interrupts
    while (1)
    {
      while(int_flag == 0 )  //wait till interrupt flag goes high
            ;
      data = XIOModule_DiscreteRead(&gpi, 2); // read counts (channel 2)
        xil_printf("%d: %d\n\r",my_secs, data);
        my_secs++;
        int_flag = 0;  //clear flag
    }
    cleanup_platform();
    return 0;
}

 

schem.jpg

Link to comment
Share on other sites

8 answers to this question

Recommended Posts

  • 0

Hi @ChaC73,

I haven't worked with Microblaze MCS specifically, though you may need to check the C_FREQ and C_UART_BAUDRATE settings based on some courtesy searching. Another recommendation I got from another engineer would be to probably add a gpio output on the mcs block that is tied to the fifo rd_en pin in such a way that the sofware toggling it triggers the fifo to present a new piece of data on the q_fifo bus. Right now the fifo is filled up and then dumped into a mostly unread gpio pin.

Otherwise I would probably recommend taking a look at the Nexys Video GPIO demo, https://digilent.com/reference/programmable-logic/nexys-video/start#example_projects, which is an HDL based demo that reads in inputs on the Nexys Video (in this case on-board buttons, but that's effectively the same as a Pmod port pin, just on a different FPGA pin) and prints out data over UART once a button is pressed.

Thanks,
JColvin

Link to comment
Share on other sites

  • 0

Before trying to debug your hardware perhaps you might post a brief description of the theory of operation for your design.

You start with: "I have an external TTL signal (3.3 V, 1 kHz)"; and from this your intend to receive ascii characters? more informatin needed.

Link to comment
Share on other sites

  • 0

@ zygot : yes I understand ....
I have been working and have something that is now working (albeit not doing what I want :-) ).
 

Here is my new top module

Spoiler




`timescale 1ns / 1ps

module oscillo(clk, uart, TTL_in,sw, btnc);

input clk;
input sw;
input btnc;
input  [0:0] TTL_in;  // These are input data

output uart;

reg [0:0] TTL_in_reg; always @(posedge clk) TTL_in_reg <= TTL_in;


//wire [0:0] q_fifo; // These are output data
    
wire [0:9] data_count; // These are output data
//----------- Begin Cut here for INSTANTIATION Template ---// INST_TAG
fifo_generator_0 my_Fifo (
  .clk(clk),                // input wire clk
  .srst(sw),              // input wire srst
  .din(TTL_in_reg),                // input wire [0 : 0] din
  .wr_en(wrreq),            // input wire wr_en
  .rd_en(rdempty),            // input wire rd_en
  .dout(q_fifo),              // output wire [0 : 0] dout
  .full(wrfull),              // output wire full
  .empty(wrempty),            // output wire empty
  .data_count(data_count)  // output wire [9 : 0] data_count
);

// The flash ADC side starts filling the fifo only when it is completely empty,
// and stops when it is full, and then waits until it is completely empty again
reg fillfifo;
always @(posedge clk)
if(~fillfifo)
  fillfifo <= wrempty; // start when empty
else
  fillfifo <= ~wrfull; // stop when full

assign wrreq = fillfifo;
assign rdempty = ~ fillfifo;



microblaze_mcs_0 my_msc (
  .Clk(clk),                        // input wire Clk
  .Reset(sw),                    // input wire Reset
  .GPI1_Interrupt(GPI1_Interrupt),  // output wire GPI1_Interrupt
  .INTC_IRQ(INTC_IRQ),              // output wire INTC_IRQ
  .UART_txd(uart),              // output wire UART_txd
  .GPIO1_tri_i(btnc),        // input wire [0 : 0] GPIO1_tri_i
  .GPIO2_tri_i(data_count)        // input wire [9 : 0] GPIO2_tri_i
);

endmodule

 

My new xdc file

Spoiler


## FPGA Configuration I/O Options
set_property CONFIG_VOLTAGE 3.3 [current_design]
set_property CFGBVS VCCO [current_design]

## Signal IN
set_property -dict { PACKAGE_PIN AB22  IOSTANDARD LVCMOS33 } [get_ports { TTL_in }]

## Board Clock: 100 MHz
set_property -dict { PACKAGE_PIN R4    IOSTANDARD LVCMOS33 } [get_ports { clk }]; 
create_clock -add -name clk_100m -period 10.00 [get_ports clk]

## Reset Switch
set_property -dict {PACKAGE_PIN E22 IOSTANDARD LVCMOS12} [get_ports {sw}];

## Buttons
set_property -dict { PACKAGE_PIN B22 IOSTANDARD LVCMOS12 } [get_ports { btnc }];

## Uart
set_property -dict { PACKAGE_PIN AA19  IOSTANDARD LVCMOS33 } [get_ports { uart }]

 

And my new .c file

#include <stdio.h>
#include "platform.h"
#include "xil_printf.h"
#include "xparameters.h" // add
#include "xiomodule.h" // add

volatile char int_flag = 0;    // millisecond counter variable
//function which is called by the GPI interrupt when one of its bits goes hi
void MyInterruptFlagSet( void* ref) {
  int_flag = 1; // when it receives interrupt, set c
}
int main()
{
    init_platform();
    u32 data;
    u16 my_secs = 0;
    XIOModule gpi;

    //print("Setting up GPI\n\r");
    data = XIOModule_Initialize(&gpi, XPAR_IOMODULE_0_DEVICE_ID);
    data = XIOModule_Start(&gpi);

    //setting up interrupt handlers and enables them
    microblaze_register_handler(XIOModule_DeviceInterruptHandler,
                                  XPAR_IOMODULE_0_DEVICE_ID); // register the interrupt handler
    // Makes the connection between the Id of the interrupt source and the associated handler that is to run when the interrupt is recognized.
    XIOModule_Connect(&gpi, XIN_IOMODULE_GPI_1_INTERRUPT_INTR, MyInterruptFlagSet,
                            NULL); // register timerTick() as our interrupt handler
    XIOModule_Enable(&gpi, XIN_IOMODULE_GPI_1_INTERRUPT_INTR); // enable the interrupt
    microblaze_enable_interrupts(); // enable global interrupts
    while (1)
    {
      while(int_flag == 0 )  //wait till interrupt flag goes high
            ;
      data = XIOModule_DiscreteRead(&gpi, 2); // read counts (channel 2)
        xil_printf("%d: %d\n\r",my_secs, data);
        my_secs++;
        int_flag = 0;  //clear flag
    }
    cleanup_platform();
    return 0;
}

 

This allows me to read the number of words :

data_count

in the FIFO when I push a button on the card and this works.

Now, I am wondering how to the read the actual counts: that is reading all the 1024 words (1 bit) at once. I guess I have to play with the .c file and make some changes in the FIFO and microblaze but I am *again* stuck.

 

 

schem.jpg

Edited by ChaC73
Link to comment
Share on other sites

  • 0

The only thing that you've posted is your solutions to whatever it is that your design is supposed to accomplish.

I'm a big fan of creating projects just for the purpose of learning or experimentation. I do it all the time. Even for "hobby" projects that are mostly for experimentation it's best to start off with figuring our a description of the problem, what you want to do, and the theory of how you intend to go about solving the problem. The act of writing this down usually helps raise important questions. For experimentation, knowing the right questions is more important than knowing answers to unimportant questions.

I can see your solution. I can't see a anything that tells me what you are trying to do consistent with the stated objectives: "I have a signal. I'd like to read the signal".

Trying to solve a problem that is undefined is rarely a productive educational experience, though might be a good way to pass the time.

Edited by zygot
Link to comment
Share on other sites

  • 0

Thanks .

I want to acquire a signal and mesure the autocorrelation using an ´efficient computation ‘ as shown here https://en.m.wikipedia.org/wiki/Autocorrelation

So I need to acquire some samples, store them in memory and calculate the autocorrelation. I want to repeat this multiple time , knowing that I do not mind losing some data.  
 

As said, I am very new to fpga 

Hope it clarifies.

Link to comment
Share on other sites

  • 0

Well, I guess that this is more information than before...

"So I need to acquire some samples, store them in memory and calculate the autocorrelation" doesn't really tell me how your design is supposed to "measure autocorrelation". At least try and put into words what it is that you believe that your logic circuit does.

What is the source of your digital input?

Mechanical buttons and switches are notorious for a phenomenon known as contact bounce. Using them without conditioning is dangerous, especially for circuit like yours.

It seems to me that your HW/SW approach, ignoring the actual code involved, is complicating your design solution. All hardware or all software approaches might be easier to conceptualize. I'd go for all HDL but that doesn't mean that you should. Anyway, you seem to be reluctant to provide enough insight into your theory of operation for me to be helpful. Perhaps that because you don't think that you need do this step and haven't tried?

Normally when someone says that "xil_printf("%d: %d\n\r",my_secs, data);" produces unexpected characters I'd suggest that there's a baud rate issue, but in your case I suspect that it's due to a much more serious problem, a divergence between what you hope that your design is doing and what it's actual;ly doing.

I strongly urge you to create a Veriog testbench and get a visual picture of what your hardware is doing. The first iteration will likely not be very good as you will fail to get the button and switch input behavior correct; but you have to start somewhere.

Link to comment
Share on other sites

  • 0
On 2/3/2022 at 2:59 PM, ChaC73 said:

I want to acquire a signal and mesure the autocorrelation using an ´efficient computation ‘

Ignoring all previous commentary regarding this post I do have one more suggestion.

For such a project I'd start with a high level simulation using OCTAVE or MATLAB. Sometimes, it appropriate to use any functionality as a first pass just to verify that your concept makes sense. Before trying to implement anything in hardware ( whatever that might be )  I'd write an algorithmic OCTAVE implementation that exposes all of the details of the design. This means just using basic logic structures like if-then-else, while and for loops, etc. The idea is to make sure that your implementation doesn't rely on high level function. It also forces you to create and implementation that can be readily translated into programmable logic using the resources available to that hardware.

The purpose of this is that after you get to the end, where you have an implementation working in ( in the case of FPGA hardware) simulation and then hardware, you can compare the results to the OCTAVE simulations. More importantly, the effort will circumvent spending time trying to implement an algorithm in logic that can't possibly succeed.

Of course, if you're unable write down how you believe your daydream, er concept, is suppose to work and how the implementation is constructed, then you are probably just wasting your time.

PS. I use OCTAVE because I can afford it. I've recently discovered that MATLAB now has a 'personal use' license that make the commercial tool available to individuals who couldn't afford it. I haven't tried it yet, but now MATLAB might be a reasonable investment for hobbyists and people not privy to academic discounts.

Edited by zygot
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...