silantyeved Posted December 3, 2022 Share Posted December 3, 2022 Originally posted under a different category: Link to comment Share on other sites More sharing options...
0 silantyeved Posted December 3, 2022 Author Share Posted December 3, 2022 I want to know if anyone on this forum has ever managed to implement a UART echo application and managed to use tools available in a Unix OS to send and receive serial data (e.g. `minicom`, `echo`). My specific board is Arty a7 100T, but from what I understand the interface is universal (it is in the name) so other board owners input is welcome. Link to comment Share on other sites More sharing options...
0 zygot Posted December 3, 2022 Share Posted December 3, 2022 (edited) 2 hours ago, silantyeved said: I want to know if anyone on this forum has ever managed to implement a UART echo application and managed to use tools available in a Unix OS to send and receive serial data Sure. Perhaps a UART echo project isn't where you want to start. You could look at this project: https://forum.digilent.com/topic/4348-a-uart-based-debugger-tool/ This is a transmit only example but might help you resolve any OS related issues that might be getting in the way. It has a testbench example to help you with simulation. It's not clear what the problems are that you've encountered from suggestions to the earlier post. Reducing the number of things that can cause a failure is always a good way to proceed when you aren't having success. You should be able to figure out a way to use the UART_DEBUGGER.vhd from the testbench, but I've posted other code that uses it if you are having a hard time doing so. A common problem that people have using UARTs is figuring out whether it's the FPGA or the USB UART that's driving TxD and RxD. Some USB UARTs require the CTSn be asserted correctly, but the ones on Digilent's boards do not. Edited December 3, 2022 by zygot Link to comment Share on other sites More sharing options...
0 Guest Posted December 3, 2022 Share Posted December 3, 2022 Hi @silantyeved ,How far did you come, and where do you get stuck? What HDL language are you using? If it's VHDL I may be able to review your work. Cheers, Sidney Link to comment Share on other sites More sharing options...
0 silantyeved Posted December 4, 2022 Author Share Posted December 4, 2022 thanks again @zygot (I will take a look at the debugger tool post) and @reddish I am still very much stuck at the same place as I was before. I think I should step back and understand where the fault is actually coming from (is it OS, FPGA or even USB cable related). Link to comment Share on other sites More sharing options...
0 Guest Posted December 4, 2022 Share Posted December 4, 2022 Hi @silantyeved A few concrete steps to help you in debugging: (1) Are you capable to get an LED to blink for a well-defined time on the Arty board (say, at 1 Hz, so 1 cycle per second)? If not, first you have to make sure you can do that; the UART stuff is a step up in complexity from that. If you can't get this to work, let us know. (2) Then, change your HDL to increase the frequency to 4800 Hz. if you have one, verify on an oscilloscope that you see a nice square wave at 4800 Hz, on some output FPGA pin. If not, report back. (3) Connect the 4800 Hz to the TX side of the UART. Concretely, if your serial output signal is called UART_OUT, this means you should have something like this in your constraints: set_property -dict { PACKAGE_PIN D10 IOSTANDARD LVCMOS33 } [get_ports { UART_OUT }]; Since on the Arty A7 board, the D10 pin of the FPGA chip is connected to the TX pin of the serial-to-USB chip. (4) If you run that program, you are now outputting a valid 9600 baud datastream to the serial-to-USB chip, and it will dutifully transfer that to the PC, if the PC opens the device for reading. On your PC side, start minicom or another terminal program at 9600 baud, 8 databits, no parity, and 1 stop-bit. You should see a continuous stream of "U" characters coming in (ASCII code 0x55, binary "01010101"). This works because the start bit, data bits, and stop bit at 9600 baud form a nice and continuous 4800 Hz square wave. If not, you may be looking at the wrong TTY device, or you may have no permissions, or there can be some more possble but less likely causes. If you want us to be able to help you, try these steps and report back where you get stuck. I have gotten serial communication to work on about 10 different FPGA boards (including the Arty) so I'm sure we can pinpoint the problem; but you need to provide concrete information on what you tried and what you saw. Just saying "I am stuck" doesn't provide enough information on my side to be able to figure out what is going wrong on your side. Link to comment Share on other sites More sharing options...
0 zygot Posted December 4, 2022 Share Posted December 4, 2022 (edited) Did you look over the VHDL in the reference project in the link that I provided in my last post? It has everything that you should need to at least see data flow between your OS and the FPGA ( OK, you will actually have to write a simple entity to use the IP ). The testbench has a full duplex UART. The first step in programmable logic development is to verify that your logic is at least correct on the behavioral and RTL level; and that is done in simulation. Vivado has the ability to do simulation. If you can't get even a basic simulation to work then trying to get a design to work on hardware will be very difficult. If it works in simulation, then you can at least simplify the debugging process that allows you to do what you want to do. Does this code in the UartDebuggerproject make any sense to you? Were you able to run a simulation in Vivado and look at the component signals? Unless you are trying to complete a course assignment there's no embarrassment asking questions. But as reddish pointed out, it's hard to help when you don't have enough information to work with. Edited December 4, 2022 by zygot Link to comment Share on other sites More sharing options...
0 silantyeved Posted December 4, 2022 Author Share Posted December 4, 2022 @reddish thanks a lot. I was able to get a continuous stream of "U"s out in minicom by using 10417 as a count param to switch LEDs (and then UART pin) on and off: I suppose that confirms that: 1. UART output pin on an FPGA is working as expected 2. Minicom is set up correctly I will appreciate any further guidance you may give me to get the echo working. Ed Link to comment Share on other sites More sharing options...
0 silantyeved Posted December 4, 2022 Author Share Posted December 4, 2022 @zygot yet to look at it Link to comment Share on other sites More sharing options...
0 Guest Posted December 4, 2022 Share Posted December 4, 2022 (edited) Hi @silantyeved Indeed this confirms that a lot in your design is working, and that there are no issues with USB traffic or permissions in linux, etc. I kindly invite you to re-read my previous message, because it lists the obvious next steps: One important thing when doing FPGA designs is that you really need to chop stuff up in small steps (and or modules), and you need to build confidence at each step that everything is working as expected. This is a good idea already for "normal" programming, but it is an order of magnitude more important in FPGA work because debugging a complicated HDL design is so much harder. You want to avoid debugging as much as possible. So the chopping-up of your "loopback" end-goal from where you are now consists of (a) implementing a state machine that is capable of transmitting something other than 0x55; (b) making sure this state-machine has a nice interface; (c) forget the "TX" side for the time being and implement a serial receiver that is capable of recognizing the start bit falling edge and gets the timing right to sample the incoming data bits smack in the middle of their baud periods, showing the end result on the Arty's LEDs once it's done; (d) make sure the receiver has a proper interface and then finally (e) tie together the TX and RX sides to make a loopback. Five steps, each could take hours or days if you haven't done this before, and that's fine. You will learn a lot in the process. FPGA programming is quite hard, I'm afraid. If you don't like hard work, you can find plenty of UART implementations by googling -- some of them are even well done, although you won't be able to judge which ones until you get the necessary experience. But really, I thoroughly recommend doing it yourself, as it is a perfect opportunity to make a lot of mistakes in a relatively small design, and the experience will teach you a lot of things that will come in handy later when you want to do more advanced designs. Edited December 5, 2022 by reddish Link to comment Share on other sites More sharing options...
0 silantyeved Posted December 9, 2022 Author Share Posted December 9, 2022 Thanks for your guidance @reddish. My current state of affairs is as follows. I have switched focus to RX side of UART with goal of outputting first (or last?) 4 bits of an ASCII character via Arty's LEDs. While, I am observing some action on the LEDs, it is definitely not consistent with binary representations of characters I am sending to USB file descriptor via UNIX shell. Exact symptoms are as follows: When I do: echo "A" > /dev/ttyUSB1 I get the following output on the LEDs (PFA). In fact this output presents itself for any character I try to send. My prime suspect is timing. I am not certain that I have gotten the counter correct, because fiddling with it can lead to different outputs on LEDs, though by no means does it lead to expected output on LEDs. For inspiration I have used Verilog code from https://nandland.com/project-7-uart-part-1-receive-data-from-computer/. Here is the code that I am programming Arty with: `timescale 1ns / 1ps module top( input clock, input sw1, input sw2, output[0:3] led, output[0:3] led_g, input uart_rx, output uart_tx ); // UART BAUD // (100,000,000 (CLK) / 9600 (BAUD)) = 10417 parameter CLKS_PER_BIT = 10417; reg [31:0] reg_clks_cnt = 0; // RX localparam IDLE = 3'b000; localparam RX_START_BIT = 3'b001; localparam RX_DATA_BITS = 3'b010; localparam RX_STOP_BIT = 3'b011; localparam CLEANUP = 3'b101; reg [3:0] rx_state; reg [7:0] rx_byte; reg [2:0] rx_byte_idx; reg [7:0] led_reg; reg [3:0] debug_reg; always @(posedge clock) begin case(rx_state) IDLE: begin reg_clks_cnt <= 0; rx_byte_idx <= 0; if (uart_rx == 1'b0) // start bit begin rx_state <= RX_START_BIT; debug_reg <= 4'b1111; end else begin rx_state <= IDLE; end end RX_START_BIT: begin if (reg_clks_cnt == (CLKS_PER_BIT - 1) / 2) begin if (uart_rx == 1'b0) // check start bit still low at the middle of BAUD period begin reg_clks_cnt <= 0; rx_state <= RX_DATA_BITS; end else begin rx_state <= IDLE; end end else begin // still sampling for the middle of start bit reg_clks_cnt <= reg_clks_cnt + 1; rx_state <= RX_START_BIT; end end RX_DATA_BITS: begin if (reg_clks_cnt < CLKS_PER_BIT - 1) begin reg_clks_cnt <= reg_clks_cnt + 1; rx_state <= RX_DATA_BITS; end else begin reg_clks_cnt <= 0; rx_byte[rx_byte_idx] <= uart_rx; if (rx_byte_idx < 7) begin rx_byte_idx <= rx_byte_idx + 1; rx_state <= RX_DATA_BITS; end else begin rx_byte_idx <= 0; rx_state <= RX_STOP_BIT; end end end RX_STOP_BIT: begin if (reg_clks_cnt < CLKS_PER_BIT - 1) begin reg_clks_cnt <= reg_clks_cnt + 1; rx_state <= RX_STOP_BIT; end else begin reg_clks_cnt <= 0; rx_state <= CLEANUP; end end CLEANUP: begin rx_state <= IDLE; end default: begin rx_state <= IDLE; end endcase end always @ (posedge clock) begin if (sw1) begin led_reg <= debug_reg; end else begin led_reg <= rx_byte; end end assign led = led_reg; endmodule Any suggestions as to how I can debug this further? Link to comment Share on other sites More sharing options...
0 Guest Posted December 9, 2022 Share Posted December 9, 2022 Your "echo" commands also emits a newline (0x0a). Try echo -n "A" instead. Link to comment Share on other sites More sharing options...
0 silantyeved Posted December 9, 2022 Author Share Posted December 9, 2022 That was it, @reddish! Tested with A-G and so far I can see the last 4 bits of each letter being displayed by LEDs as expected. I will test a bit more with the current design and then will do the same but pointing `led_reg` at the first 4 bits instead; or even better, switching between first and last 4 bits using a switch. After, I will get to the next portion of you initial suggestion and clean up the RX module interface and then start tying in TX part of the UART. Link to comment Share on other sites More sharing options...
0 Guest Posted December 9, 2022 Share Posted December 9, 2022 Awesome, nice and steady progress towards your goal, and I think you're learning a lot in the process! Link to comment Share on other sites More sharing options...
0 silantyeved Posted December 10, 2022 Author Share Posted December 10, 2022 Got it! Again, thanks for your help and support @reddish! I did end up learning a lot in the process. Attaching verilog that got me here -- any feedback on it will be highly appreciated. uart_echo.zip Link to comment Share on other sites More sharing options...
0 Guest Posted December 10, 2022 Share Posted December 10, 2022 Cool! I cannot really judge your verilog, I'm more of a VHDL guy myself ...... :) Link to comment Share on other sites More sharing options...
Question
silantyeved
Originally posted under a different category:
Link to comment
Share on other sites
15 answers to this question
Recommended Posts
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 accountSign in
Already have an account? Sign in here.
Sign In Now