1
\$\begingroup\$

I am trying to generate a Verilog code for transmitter that sends data at 1 start bit and 1 stop bit from FPGA and receive on my PC at 1 stop bit. If anyone can provide a link or suggestion, it will be highly appreciated.

Code is as follows:

module tb_tx_serial (input clk, output TxD);

  // Inputs
  reg TxD_start=0;
  reg [7:0] TxD_data=0;
  reg [7:0] count=0;

  // Outputs
  //wire TxD;
  wire TxD_busy;

  // Instantiate the Unit Under Test (UUT)
  async_transmitter uut (
    .clk(clk), 
    .TxD_start(TxD_start), 
    .TxD_data(TxD_data), 
    .TxD(TxD), 
    .TxD_busy(TxD_busy)
  );

  always @(posedge clk) begin
    //if(count <= 6) begin
      TxD_start <= 1'b1;
      TxD_data <= count; 
    // else TxD_data <= 8'b10111011;
  end

  always @(posedge clk) begin
    count <= count + 1;
  end

endmodule

module async_transmitter (
  input clk,
  input TxD_start,
  input [7:0] TxD_data,
  output TxD,
  output TxD_busy
);

  // Assert TxD_start for (at least) one clock cycle to start transmission of TxD_data
  // TxD_data is latched so that it doesn't have to stay valid while it is being sent

  parameter ClkFrequency = 50000000;  // 50MHz
  parameter Baud = 9600;

  //generate
  //  if(ClkFrequency<Baud*8 && (ClkFrequency % Baud!=0)) ASSERTION_ERROR PARAMETER_OUT_OF_RANGE("Frequency incompatible with requested Baud rate");
  //endgenerate

  ////////////////////////////////
`ifdef SIMULATION
  wire BitTick = 1'b1;  // output one bit per clock cycle
`else
  wire BitTick;

  BaudTickGen #(ClkFrequency, Baud) tickgen (
    .clk(clk), 
    .enable(TxD_busy), 
    .tick(BitTick)
  );
`endif

  reg [3:0] TxD_state = 0;
  wire TxD_ready = (TxD_state==0);

  assign TxD_busy = ~TxD_ready;

  reg [7:0] TxD_shift = 0;

  always @(posedge clk) begin
    if (TxD_ready & TxD_start)
      TxD_shift <= TxD_data;
    else if (TxD_state[3] & BitTick)
      TxD_shift <= (TxD_shift >> 1);

    case(TxD_state)
    4'b0000: if (TxD_start) TxD_state <= 4'b0100;
    4'b0100: if (BitTick) TxD_state <= 4'b1000;  // start bit
    4'b1000: if (BitTick) TxD_state <= 4'b1001;  // bit 0
    4'b1001: if (BitTick) TxD_state <= 4'b1010;  // bit 1
    4'b1010: if (BitTick) TxD_state <= 4'b1011;  // bit 2
    4'b1011: if (BitTick) TxD_state <= 4'b1100;  // bit 3
    4'b1100: if (BitTick) TxD_state <= 4'b1101;  // bit 4
    4'b1101: if (BitTick) TxD_state <= 4'b1110;  // bit 5
    4'b1110: if (BitTick) TxD_state <= 4'b1111;  // bit 6
    4'b1111: if (BitTick) TxD_state <= 4'b0010;  // bit 7
    4'b0010: if (BitTick) TxD_state <= 4'b0011;  // stop1
    4'b0011: if (BitTick) TxD_state <= 4'b0000;  // stop2
    default: if (BitTick) TxD_state <= 4'b0000;
    endcase
  end

  assign TxD = (TxD_state<4) | (TxD_state[3] & TxD_shift[0]);  // put together the start, data and stop bits

endmodule

////////////////////////////////////////////////////////
// dummy module used to be able to raise an assertion in Verilog
//module ASSERTION_ERROR();
//endmodule

`timescale 1ns / 1ps

////////////////////////////////////////////////////////
module BaudTickGen
(
  input clk, enable,
  output tick  // generate a tick at the specified baud rate * oversampling
);
  parameter ClkFrequency = 50000000;
  parameter Baud = 9600;
  parameter Oversampling = 1;

  function integer log2(input integer v); 
    begin 
      log2=0; 
      while (v>>log2) log2 = log2 + 1; 
    end 
  endfunction

  localparam AccWidth = log2(ClkFrequency/Baud)+8;  // +/- 2% max timing error over a byte

  reg [AccWidth:0] Acc = 0;
  localparam ShiftLimiter = log2(Baud*Oversampling >> (31-AccWidth));  // this makes sure Inc calculation doesn't overflow
  localparam Inc = ((Baud*Oversampling << (AccWidth-ShiftLimiter))+(ClkFrequency>>(ShiftLimiter+1)))/(ClkFrequency>>ShiftLimiter);

  always @(posedge clk) begin
    if (enable) 
      Acc <= Acc[AccWidth-1:0] + Inc[AccWidth:0]; 
    else Acc <= Inc[AccWidth:0];
  end

  assign tick = Acc[AccWidth];

endmodule

Test bench:

`timescale 1ns / 1ps
module test_srltst;

    // Inputs
    reg clk;

    // Outputs
    wire TxD;

    // Instantiate the Unit Under Test (UUT)
    tb_tx_serial uut (
        .clk(clk), 
        .TxD(TxD)
    );

    initial
    begin
        clk = 0;
        forever #10 clk = ~clk;
    end

endmodule

Dont know it would help or not, but I have provided this in my UCF file for UART

#NET "TxD" LOC = "M14" | IOSTANDARD = LVTTL | DRIVE = 8 | SLEW = SLOW ;
\$\endgroup\$
  • \$\begingroup\$ Have you worked on making a block diagram? Some shifter, register group etc can be used. \$\endgroup\$ – sharvil111 Dec 22 '15 at 7:05
  • \$\begingroup\$ i executed a code that implements the same, but that is only working when i give a constant data say 8'hAB. When I give TxD_data <= TxD_data + 1 , it doesnt work. \$\endgroup\$ – shaam Dec 22 '15 at 7:07
  • \$\begingroup\$ every attempt to give a varying data to TxD-data fails the communication \$\endgroup\$ – shaam Dec 22 '15 at 7:43
  • \$\begingroup\$ Please edit your question to add additional material, rather than putting it into comments. \$\endgroup\$ – Dave Tweed Dec 22 '15 at 13:13
1
\$\begingroup\$

I have a Working code for UART Transmitter in VHDL from my latest project. I'm not familiar with verilog. If you are comfortable in VHDL, go through the following code.It's a simple FSM model and easily understandable.

    library IEEE;
    use IEEE.STD_LOGIC_1164.ALL;
    use IEEE.STD_LOGIC_ARITH.ALL;
    use IEEE.STD_LOGIC_UNSIGNED.ALL;

    entity Tx_UART_Macro is
        Port ( rst,en,clk, parity, odd_even : in  STD_LOGIC;
                tx_din                           : in  STD_LOGIC_VECTOR (8 downto 1);
                rd,tx_dout,frame_ok          : out  STD_LOGIC);
        attribute fsm_encoding: string;
        attribute fsm_encoding of Tx_UART_Macro: entity is "gray";

    end Tx_UART_Macro;

    architecture Behavioral of Tx_UART_Macro is
    type state is(idle,rd_data,start,increment,transmit,stop,frame_gap,parity_st);
    signal current_state, next_state : state;
    signal count            : integer range 0 to 15;
    signal frame_count  : integer range 0 to 7;
    signal tx_din_sig   : STD_LOGIC_VECTOR(8 downto 1);
    signal par_cnt      : STD_LOGIC_VECTOR(1 downto 0);
    signal tx_reg       : STD_LOGIC_VECTOR(4 downto 0); 

    begin
    process(rst,clk)
    begin 
            if(rst='1')then
            count   <= 0;
            tx_dout <= '1';
            current_state <= idle;
            rd <='0';
            frame_count <=0;
            tx_din_sig <= (others=>'0');
            par_cnt <= "00";
            frame_ok        <= '0';

            elsif ( rising_edge(clk)) then
                current_state <= next_state;
                case next_state is
                when idle =>
                    count <= 0; 
                    tx_dout <= '1';
                    rd <='0';
                    frame_count <=0;
                    par_cnt <= "00";
                    frame_ok        <= '0';

                when rd_data =>
                    rd <= '1';
                    tx_din_sig <= tx_din;

                when start =>
                    tx_dout <='0';

                    when increment =>
                    count <= count+1;

                    when transmit =>
                    tx_dout <= tx_din_sig(count);

                    when parity_st=>
                        tx_dout  <= tx_din_sig(1)  xor tx_din_sig(2)  xor tx_din_sig(3)  xor tx_din_sig(4)  xor
                                        tx_din_sig(5)  xor tx_din_sig(6)  xor tx_din_sig(7)  xor tx_din_sig(8)  xor odd_even;
                        par_cnt <= par_cnt + '1';

                    when stop =>
                    tx_dout <= '1';

                    when frame_gap =>
                    frame_count <=  frame_count +   1;
                    frame_ok        <= '1';

                    when others =>
                        count   <= 0;
                        tx_dout <= '1';
                        rd <='0';
                        frame_count <=0;
                        tx_din_sig <= (others=>'0');
                        frame_ok        <= '0';


                    end case;
                    end if;
        end process;
        process(current_state,en,count,frame_count, par_cnt,parity)
        begin
            next_state <= current_state;
            case current_state is
            when idle =>
            if(en ='1') then
                next_state <= rd_data;
            else
                next_state <= idle;
                end if;  
            when rd_data =>

            next_state <= start;        

            when    start =>
                next_state <= increment;
            when increment =>
            if(count < 9) then 
                next_state <= transmit;
            else
                if(parity = '1') then
                    next_state <= parity_st;
                else
                    next_state <= stop;
                end if; 
            end if; 
            when transmit =>
                next_state <= increment;
            when parity_st=>
                if(par_cnt = "10") then
                    next_state <= stop;
                else
                    next_state <= parity_st;
                end if; 
            when stop =>
                next_state <= frame_gap;
            when frame_gap =>
                next_state <= idle;
            when others =>
                next_state <= idle;
        end case;
        end process;
    end Behavioral;
|improve this answer|||||
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.