código de verificación UART RS232 UART

1

Estoy tratando de generar un código Verilog para el transmisor que envía datos en 1 bit de inicio y 1 bit de parada desde FPGA y recibo en mi PC con 1 bit de parada. Si alguien puede proporcionar un enlace o sugerencia, será muy apreciado.

El código es el siguiente:

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

Banco de pruebas:

'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

No sé si ayudaría o no, pero he proporcionado esto en mi archivo UCF para UART

#NET "TxD" LOC = "M14" | IOSTANDARD = LVTTL | DRIVE = 8 | SLEW = SLOW ;
    
pregunta shaam

1 respuesta

1

Tengo un código de trabajo para el transmisor UART en VHDL de mi último proyecto. No estoy familiarizado con verilog. Si se siente cómodo con VHDL, lea el siguiente código. Es un modelo FSM simple y fácil de entender.

    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;
    
respondido por el Behin

Lea otras preguntas en las etiquetas