Jump to content
  • 0

Nexys 4 to PC UART communication


Manas

Question

Hi

I am trying to send data from Nexys 4 Artix 7 FPGA Board to PC. I using uart to send the data at 9600 baud rate. The uart takes data through the switch and I am using SW(0 to 7) for this. The data transfer takes place only when button is press(btnU). I wanted to make this transfer automatic without having the need to use the button but have not been able to get it done. I have taken the code from http://www.instructables.com/id/UART-Communication-on-Basys-3-FPGA-Dev-Board-Power/?ALLSTEPS. I have made some change to replace the btnU with "State" to initiate the the data transfer. For this purpose i have written a module where the input State determines whether to initiate the uart just like the btnU. The modules transmit and transmitter are sub-modules to the XADC module.

Please find my code below:

module transmit
(
input clk, //clock signal
input State,
output reg transmit //transmit signal
);


always @(posedge clk) begin     
if (State ==  1)
    transmit <= 1; 
else
    transmit <= 0;
end
endmodule

-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
module transmitter(
input clk, 
input transmit, 
input [7:0] data,
output reg TxD 
);

//internal variables
reg [3:0] bitcounter; 
reg [13:0] counter; 
reg state,nextstate; 
reg [9:0] rightshiftreg; 
reg shift; 
reg load;
reg clear; 

//UART transmission logic
always @ (posedge clk) 
begin 
        counter <= counter + 1;  
            if (counter >= 10415) 
               begin 
                  state <= nextstate; 
                  counter <=0; 
                  if (load) rightshiftreg <= {1'b1,data,1'b0};
                  if (clear) bitcounter <=0; 
                  if (shift) 
                     begin 
                        rightshiftreg <= rightshiftreg >> 1; 
                        bitcounter <= bitcounter + 1; 
                     end
               end
         end
 

//state machine

always @ (posedge clk)  
//always @ (state or bitcounter or transmit)
begin
    load <=0; 
    shift <=0; 
    clear <=0; 
    TxD <=1; 
    case (state)
        0: begin 
             if (transmit) begin 
             nextstate <= 1; 
             load <=1; 
             shift <=0; 
             clear <=0; 
             end 
        else begin 
             nextstate <= 0; 
             TxD <= 1; 
             end
           end
        1: begin  // transmit state
             if (bitcounter >=10) begin // check if transmission is complete or not. If complete
             nextstate <= 0; // set nextstate back to 0 to idle state
             clear <=1; // set clear to 1 to clear all counters
             end 
        else begin
             nextstate <= 1; // set nextstate to 1 to stay in transmit state
             TxD <= rightshiftreg[0]; // shift the bit to output TxD
             shift <=1; // set shift to 1 to continue shifting the data
             end
           end
         default: nextstate <= 0;                      
    endcase
end


endmodule

-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

The problem is that i have not been able to implement this without making use of button to initiate the data transfer. Without the use of button the communication between Nexys 4  Board and PC doesn't take place. I can only see the RX Led blinking on FPGA board but not the data on teraterm. Could you please help me to find the solution to this issue?

Regards

Manas 

Link to comment
Share on other sites

11 answers to this question

Recommended Posts

@Manas,

Looking over your code, it looks like you haven't set any initial conditions.  For example, in the first module you show, what keeps Vivado from optimizing State and transmit to being permanently one's?  You might wish to add in a line:

initial State = 1'b0; // and another

initial transmit = 1'b0;

You might also wish to work your way through your code doing this to all variables whose initial state matters.

Incidentally, in practice a UART should always require some event to get it started.  Something to tell it when to go, and what to print. 

If you are curious, you can find my own transmit UART implementation here, as well as a hello world application here.  It uses Verilator together with a C++ UART simulator to prove that it works successfully offline.  That way I know that the hello world module will works before I ever try it on my board.

Yours,

Dan

Link to comment
Share on other sites

Hi

The following code is where i set the initial condition.Modules 'transmit' and 'transmitter' are sub-modules. Using State, I am trying to set the transmit module to initiate the trigger operation.

module XADCdemo(
   input CLK100MHZ,
   input vauxp11,
   input vauxn11,
   output reg [15:0] LED,
   output [7:0] an,
   output dp,
   output [6:0] seg,
   output TxD,   
   input [7:0] sw 
 );
   wire transmit;
   wire enable;
   wire [6:0] Address;
   wire ready;
   wire [15:0] data;
   
   reg State = 0;
   reg triggeredState;
   reg [32:0] decimal;
   
   reg [3:0] dig0;
   reg [3:0] dig1;
   reg [3:0] dig2;
   reg [3:0] dig3;
   reg [3:0] dig4;
   reg [3:0] dig5;
   reg [3:0] dig6;
//   wire test  
  initial LED = 16'h0F;
   
   //xadc instantiation
   xadc_wiz_0  XLXI_7 (.daddr_in(Address), 
                     .dclk_in(CLK100MHZ), 
                     .den_in(enable), 
                     .di_in(), 
                     .dwe_in(), 
                     .busy_out(),                    
                     .vauxp11(vauxp11),
                     .vauxn11(vauxn11),
                     .vn_in(), 
                     .vp_in(), 
                     .alarm_out(), 
                     .do_out(data), 
                     .reset_in(),
                     .eoc_out(enable),
                     .channel_out(Address),
                     .drdy_out(ready));
                     
      reg [32:0] count; 
      always @ (posedge(CLK100MHZ))
      begin
      
        if(count == 20000000)begin
        
        decimal = data >> 4;
        
        if (decimal >= 2458) 
                begin
                LED<= 16'b1111111111111111;
                State <= 1;
                end
                else
                begin
                LED<= 16'b111;
                State <= 0;
                end
        
      //looks nicer if our max value is 1V instead of .999755
        if(decimal >= 4093)
        begin
            dig0 = 0;
            dig1 = 0;
            dig2 = 0;
            dig3 = 0;
            dig4 = 0;
            dig5 = 0;
            dig6 = 1;
            count = 0;
        end
        else 
        begin
            decimal = decimal * 250000;
            decimal = decimal >> 10;
            
            
            dig0 = decimal % 10;
            decimal = decimal / 10;
            
            dig1 = decimal % 10;
            decimal = decimal / 10;
                   
            dig2 = decimal % 10;
            decimal = decimal / 10;
            
            dig3 = decimal % 10;
            decimal = decimal / 10;
            
            dig4 = decimal % 10;
            decimal = decimal / 10;
                   
            dig5 = decimal % 10;
            decimal = decimal / 10; 
            
            dig6 = decimal % 10;
            decimal = decimal / 10; 
            
            count = 0;
        end
       end
       
      count = count + 1;
               
      end
      
      DigitToSeg segment1(.in1(dig0),
                         .in2(dig1),
                         .in3(dig2),
                         .in4(dig3),
                         .in5(dig4),
                         .in6(dig5),
                         .in7(dig6),
                         .in8(),
                         .mclk(CLK100MHZ),
                         .an(an),
                         .dp(dp),
                         .seg(seg));  
                         

transmit D2 (.clk(CLK100MHZ), .state(State) , .transmit(transmit));
transmitter T1 (.clk(CLK100MHZ), .transmit(transmit), .TxD(TxD), .data(sw)); 
endmodule

---------------------------------------------------------------------------------------------------------------

The problem is while implementing this I am not able to receive any data on the PC. I can only see the RX led blinking. Could you please help me solve this issue?

Regards

Manas

Link to comment
Share on other sites

@Manas,

Actually, this was the code I was looking at:

always @(posedge clk) begin     
if (State ==  1)
    transmit <= 1; 
else
    transmit <= 0;
end

Because you never included a line such as "initial State = 1'b0;" and it's companion line "initial transmit = 1'b0;", the synthesizer is removing this logic: setting State to be 1'b1 permanently, and hence transmit will be 1'b1 permanently as well, and then ... your code doesn't work like you would like.

Dan

Link to comment
Share on other sites

Hi D@n,

Thanks for the feedback. Following your suggested i was able to get it working. Now I am trying to send  string of characters instead of using the switches to send a single character. The problem is I am not able to get it done with by code. I am facing issues with how to properly declare the string and connect it with "data" of transmitter module.

Suggestions on how to achieve this will very helpful.

Regards

Manas

Link to comment
Share on other sites

@Manas

You may find the updated version of the Nexys Video XADC Demo helpful.

It does not transmit its data over UART, but the state machine implemented in OLED_master.v should be able to be nicely adapted.

In particular, you will need to pay attention to the base_str parameters, and the ascii write control signals going to the OLED controller. write_start, write_done, and write_ascii_data are the signals to pay attention to here. For the OLED controller, they handle writing ascii data into memory inside of the controller module. In adapting the state machine, they will be data sent to the uart controller, a flag to start the uart controller, and a response from the controller when it has finished transmitting a byte. These signals, controlled by the looping state path set up in the "Active" part of the oled_master state machine sequentially shift out a string modified with converted XADC data.

Hope this helps,

Arthur

Link to comment
Share on other sites

Hi

In the code below  a character array is declared using vhdl. I am unable to come up with verilog code.

I am using the digilent github resource on GPIO for Nexys 4 Artix 7. In it there is GPIO_Demo.vhd, which declares ascii character in vhdl. I am trying to do the same but not able to get the module to work. I am facing errors with the verilog transition. Please find time to resolve this issue.

------------------------------------------------------- ----------------------------------------

GPIO_Demo.vhd: constant WELCOME_STR : CHAR_ARRAY(0 to 26) := (X"0A",  --\n
                                                              X"0D",  --\r
                                                              X"4E",  --N
                                                              X"45",  --E
                                                              X"58",  --X
                                                              X"59",  --Y
                                                              X"53",  --S
                                                              X"34",  --4
                                                              X"20",  -- 
                                                              X"47",  --G
                                                              X"50",  --P
                                                              X"49",  --I
                                                              X"4F",  --O
                                                              X"2F",  --/
                                                              X"55",  --U
                                                              X"41",  --A
                                                              X"52",  --R
                                                              X"54",  --T
                                                              X"20",  -- 
                                                              X"44",  --D
                                                              X"45",  --E
                                                              X"4D",  --M
                                                              X"4F",  --O
                                                              X"21",  --!
                                                              X"0A",  --\n
                                                              X"0A",  --\n
                                                              X"0D"); --\r

-----------------------------------------------------------------------------------------------------------------

Regards

Manas

Link to comment
Share on other sites

@Manas,

You can find Verilog code for both a Hello World UART application as well as one that prints out the Gettysburg address here.  Both examples initialize an array prior to transmission, and indeed treat this array as ROM memory.  The Gettysburg address example, though, needed two solutions to implementing the array.  The first, and best, solution is to use readmemh.  This sets up everything in one line.  There's even a program within the distribution to build the hex file, should that be part of what you are struggling with.  The problem with this solution, as I discovered searching the web, is that ISE's XST can't handle hex files.  Hence, the other approach is just a long list of Verilog initial statements.

This sounds like it is what you are looking for, let me know if not.

Dan

Link to comment
Share on other sites

Hi D@n

I have made some changes in the transmitter module to send a string of characters but I am only getting the first character on the pc, remaining characters are not coming through. Below is the code :

`timescale 1ns / 1ps

module transmitter(
input clk, //UART input clock
//input reset, // reset signal
input transmit, //btn signal to trigger the UART communication
//input [7:0] data, // data transmitted
output reg TxD // Transmitter serial output. TxD will be held high during reset, or when no transmissions aretaking place. 
    );

//internal variables
reg [3:0] bitcounter; //4 bits counter to count up to 10
reg [13:0] counter; //14 bits counter to count the baud rate, counter = clock / baud rate
reg state,nextstate,tx_char; // initial & next state variable
// 10 bits data needed to be shifted out during transmission.
//The least significant bit is initialized with the binary value "0" (a start bit) A binary value "1" is introduced in the most significant bit 
reg [9:0] rightshiftreg; 
reg shift; //shift signal to start bit shifting in UART
reg load; //load signal to start loading the data into rightshift register and add start and stop bit
reg clear; //clear signal to start reset the bitcounter for UART transmission
reg [7 :0] data;
always @(posedge clk) begin
  case (char_count)
    8'd0: data <= 8'b01100001; //a
    8'd1: data <= 8'b01100001;
    8'd2: data <= 8'b01100001;
    8'd3: data <= 8'b01100001;
    8'd4: data <= 8'b01100001;
    8'd5: data <= 8'b01100001;
    8'd6: data <= 8'b00000000;
    default: data <= 8'b01111010; //z
 endcase
end    

reg [2 :0] char_count;
//reg reset;

always @(posedge clk) begin
  if (tx_char == 1) begin
    char_count <= char_count + 1;
    //reset <= 1;
    end
    else begin
    char_count <= 0;
    end
end  


//UART transmission logic
always @ (posedge clk) 
begin 
    //if (reset) 
      // begin // reset is asserted (reset = 1)
      //  state <=0; // state is idle (state = 0)
      //  counter <=0; // counter for baud rate is reset to 0 
      //  bitcounter <=0; //counter for bit transmission is reset to 0
      // end
   // else begin
         counter <= counter + 1; //counter for baud rate generator start counting 
            if (counter >= 10415) //if count to 10416 (from 0 to 10415)
               begin 
                  state <= nextstate; //previous state change to next state
                  counter <=0; // reset couter to 0
                  if (load) rightshiftreg <= {1'b1,data,1'b0}; //load the data if load is asserted
                  if (clear) bitcounter <=0; // reset the bitcounter if clear is asserted
                  if (shift) 
                     begin // if shift is asserted
                        rightshiftreg <= rightshiftreg >> 1; //right shift the data as we transmit the data from lsb
                        bitcounter <= bitcounter + 1; //count the bitcounter
                     end
               end
         end
//end 

//state machine

always @ (posedge clk) //trigger by positive edge of clock, 
//always @ (state or bitcounter or transmit)
begin
    load <=0; // set load equal to 0 at the beginning
    shift <=0; // set shift equal to 0 at the beginning
    clear <=0; // set clear equal to 0 at the beginning
    TxD <=1; // set TxD equals to during no transmission
    case (state)
        0: begin // idle state
             if (transmit) begin // assert transmit input
             nextstate <= 1; // Move to transmit state
             load <=1; // set load to 1 to prepare to load the data
             shift <=0; // set shift to 0 so no shift ready yet
             clear <=0; // set clear to 0 to avoid clear any counter
             end 
        else begin // if transmit not asserted
             nextstate <= 0; // next state is back to idle state
             TxD <= 1; 
             end
           end
        1: begin  // transmit state
             if (bitcounter >=10) begin // check if transmission is complete or not. If complete
             tx_char <= 1; 
             clear <=1; // set clear to 1 to clear all counters
             end 
        else begin // if transmisssion is not complete 
             nextstate <= 1; // set nextstate to 1 to stay in transmit state
             TxD <= rightshiftreg[0]; // shift the bit to output TxD
             shift <=1; // set shift to 1 to continue shifting the data
             end
           end
        2: begin 
             if (char_count == 7) begin
             tx_char <= 0;
             clear <= 1;
             end
        else if (bitcounter >= 10) begin
             clear <= 1;
             
             end
         else begin
             tx_char <= 1;
             TxD <= rightshiftreg[0];
             shift <= 1;
             end    
           end             
         default: nextstate <= 0;                      
    endcase
end


endmodule

The problem is that I am mot getting except the first character. Remaining part of the string is not sent through. Please help me solve this solve issue.

Regards

Manas 

Link to comment
Share on other sites

@Manas,

So, I tried to compile what you just posted and got several errors.

  1. You don't define char_count before using it.  Vivado is known to make poor assumptions about undefined variables--usually that they are wires all set to ... whatever Vivado feels like that day.
  2. I'm getting an error on your big case statement over "state", in that you are using 32-bit values to define each state, whereas you only need two bit values.  Try using 2'h0 instead of 0, 2'h1 instead of 1, etc.  Worse, you only define state above to be a 1-bit value.  (One bit values can never equal 2 ...)

So, I made the included changes to try to fix those bugs.

I then compiled and built your code within Verilator, using the UART simulator (copied below) from the wbuart32 project, and ran the result.  Looking at the VCD file that resulted (to big to attach) using gtkwave, ...

  1. The design never leaves state = 0.  Indeed, looking at the big case statement, nextstate is set to a next state, but ... I never saw anything to set state to ... whatever it was supposed to be next.  Hence, the simulation did a lot of nothing.
  2. But ... this wasn't your experience on your board.  I think that's because you never set an initial value for your state.  Vivado tends to default initial values to be all ones, whereas Verilator has a different opinion regarding what initial values should be.  You, as the designer, should be setting anything that you are assuming will have an initial value.  :D

Hope this helps,

Dan

manas.tgz

Link to comment
Share on other sites

Hi

I have taken your suggestion and ran it in Vivado 2015.2. I tried using 2'h0 instead of 0, 2'h1 instead of 1 but the in vivado its showing synthesis error.

The problem I am facing is that this code is not giving any output. I made some changes in the uart state fsm logic. The output I am expecting to see is a string of characters in the TeraTerm. The code is shown below:

module transmitter(
input clk, //UART input clock
//input reset, // reset signal
input transmit, //btn signal to trigger the UART communication
//input [7:0] data, // data transmitted
output reg TxD // Transmitter serial output. TxD will be held high during reset, or when no transmissions aretaking place. 
    );

//internal variables
reg [3:0] bitcounter; //4 bits counter to count up to 10
reg [13:0] counter; //14 bits counter to count the baud rate, counter = clock / baud rate
reg [1:0]  state,nextstate; // initial & next state variable
// 10 bits data needed to be shifted out during transmission.
//The least significant bit is initialized with the binary value "0" (a start bit) A binary value "1" is introduced in the most significant bit 
reg [9:0] rightshiftreg; 
reg shift; //shift signal to start bit shifting in UART
reg load; //load signal to start loading the data into rightshift register and add start and stop bit
reg clear; //clear signal to start reset the bitcounter for UART transmission
reg [7 :0] data;
reg cena;
initial cena = 1'b0;
always @(posedge clk) begin
  case (char_count)
    8'd0: data <= 8'b01010100;
    8'd1: data <= 8'b01100001;
    8'd2: data <= 8'b01100001;
    8'd3: data <= 8'b01100001;
    8'd4: data <= 8'b01100001;
    8'd5: data <= 8'b01100001;
    8'd6: data <= 8'b01111010;
    default: data <= 8'b01100001;
 endcase
end    

reg [2 :0] char_count;
//reg reset;

always @(posedge clk) begin
  if (transmit) begin
    char_count <= 0;
    //reset <= 1;
    end
    else if (cena == 1) begin
    char_count <= char_count + 1;
    end
end  

//localparam INI = 0;
//localparam TXCAR = 1;
//localparam NEXTCAR = 2;
//localparam STOP = 3;


//UART transmission logic
always @ (posedge clk) 
begin 
    //if (reset) 
       //begin // reset is asserted (reset = 1)
       // state <=0; // state is idle (state = 0)
        //counter <=0; // counter for baud rate is reset to 0 
        //bitcounter <=0; //counter for bit transmission is reset to 0
       //end
    //else begin
         counter <= counter + 1; //counter for baud rate generator start counting 
            if (counter >= 10415) //if count to 10416 (from 0 to 10415)
               begin 
                  state <= nextstate; //previous state change to next state
                  counter <=0; // reset couter to 0
                  if (load) rightshiftreg <= {1'b1,data,1'b0}; //load the data if load is asserted
                  if (clear) bitcounter <=0; // reset the bitcounter if clear is asserted
                  if (shift) 
                     begin // if shift is asserted
                        rightshiftreg <= rightshiftreg >> 1; //right shift the data as we transmit the data from lsb
                        bitcounter <= bitcounter + 1; //count the bitcounter
                     end
               end
         end
//end 

//state machine

always @ (posedge clk) //trigger by positive edge of clock, 
//always @ (state or bitcounter or transmit)
begin
    load <=0; // set load equal to 0 at the beginning
    shift <=0; // set shift equal to 0 at the beginning
    clear <=0; // set clear equal to 0 at the beginning
    TxD <=1; // set TxD equals to during no transmission
    cena <= 0;
   case (state)
            // initial state
        0:begin
            if (transmit)    begin
            load <= 1;
            TxD <= rightshiftreg[0];
            shift <= 1;
            nextstate <= 1;
            end
        else begin
            TxD <=1;
            end
            
            end
        1:begin
            if (bitcounter >= 10) begin
            clear <=1;
            nextstate <= 2;
            end
            end
        2:begin
            cena <= 1;
            if (char_count == 7) begin
            TxD <= 1 ;
            end
            else begin
            nextstate<= 0;
            end            
            end 
         default: nextstate <= 0;                      
    endcase
end


endmodule
 

-------------------------------------------------------------------------------------------

Please suggest what changes have to made to make this code work properly. 

Regards

Manas

 

 

 

 

Link to comment
Share on other sites

@Manas,

Your still using 3-bits for a char_count variable, but testing for 8-bits near line 23.  Changing the 8'd0 to 3'd0 and so on should fix that.

Beyond that, you *really* need to try to simulate your code.  Take a look at what can be done with GTKWave (attached).  Using Gtkwave, you can look and see what your problem(s) are.  For example, shouldn't bitcounter be incrementing?

Dan

Screenshot_2017-04-04_08-46-49.png

Link to comment
Share on other sites

Archived

This topic is now archived and is closed to further replies.

×
×
  • Create New...