⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 em_uart.pl

📁 UART RS232 IPCORE for sopc builder
💻 PL
📖 第 1 页 / 共 3 页
字号:
  return $module;
}



























sub make_uart_regs
{


  my ($Options) = (@_);


  my $module = e_module->new ({name  => $Options->{reg_module_name}});
  my $marker = e_default_module_marker->new ($module);







  e_register->add({
   out => e_signal->add (["readdata",           16]),
   in  => e_signal->add (["selected_read_data", 16]),
  });

#irq get connected automatically so I have to cahnge the name so it will not
if ( $SBI->{Has_IRQ})
{
  e_register->add({
    out    => "irq",
    in     => "qualified_irq",
  });
}
else
{
  e_register->add({
    out    => "irqs",
    in     => "qualified_irq",
  });
}


  e_port->adds (
    ["address",          3,                        "in" ],
    ["writedata",       16,                        "in" ],
    ["tx_wr_strobe",     1,                        "out"],
    ["status_wr_strobe", 1,                        "out"],
    ["rx_rd_strobe",     1,                        "out"],
    ["baud_divisor",     $Options->{divisor_bits}, "out"],
  );

#  e_assign->adds(
#    ["rx_rd_strb",      "rx_char_ready"],
#    ["tx_wr_strb",      "tx_shift_empty && ~tx_empty"],) if  $Options->{use_fifo};

  e_assign->adds(
    ["status_wr_strobe",  "chipselect && ~write_n && (address == 3'd2)"],
    ["control_wr_strobe", "chipselect && ~write_n && (address == 3'd3)"],);

  e_assign->add(["rx_rd_strobe",      "chipselect && ~read_n  && (address == 3'd0)"])if  !$Options->{use_fifo};
  e_assign->add(["rx_fifo_rd_strobe",      "chipselect && ~read_n  && (address == 3'd0) && begintransfer"])if  $Options->{use_fifo};
  e_assign->add(["rx_rd_strobe",      "rx_char_ready && rx_not_full"])if  $Options->{use_fifo};
  e_assign->add(["tx_wr_strobe",      "chipselect && ~write_n && (address == 3'd1)"])if  !$Options->{use_fifo};
  e_assign->add(["tx_fifo_wr_strobe",      "chipselect && ~write_n && (address == 3'd1) && begintransfer"])if  $Options->{use_fifo};
  e_assign->add(["tx_wr_strobe",      "tx_ready && tx_not_empty"])if  $Options->{use_fifo};
  e_assign->add([ e_signal->add (["reset",1]),"~reset_n",]) if  $Options->{use_fifo};

  e_assign->add([
     "divisor_wr_strobe", "chipselect && ~write_n  && (address == 3'd4)",
  ]) if !$Options->{fixed_baud};
  e_assign->add([
     "eop_char_wr_strobe","chipselect && ~write_n  && (address == 3'd5)",
  ]) if  $Options->{use_eop_register};





  my $tx_data_sig = e_signal->add(["tx_data", $Options->{data_bits}]);
  $tx_data_sig->export(1);

  e_register->add ({
    out    => $tx_data_sig,
    in     => "writedata\[tx_data.msb : 0\]",
    enable => "tx_wr_strobe",
  })if !$Options->{use_fifo};  #fifo will supply if present
  e_register->add ({
    out    => $tx_data_sig,
    in     => "tx_fifo_q",
    enable => "tx_wr_strobe",
  })if $Options->{use_fifo};  #fifo will supply if present

  e_register->add ({
    out    => e_signal->add(["control_reg", $Options->{num_control_reg_bits}]),
    in     => "writedata\[control_reg.msb:0\]",
    enable => "control_wr_strobe",
  });

  e_register->add ({
    out    => e_signal->add(["eop_char_reg", $Options->{data_bits}]),
    in     => "writedata\[eop_char_reg.msb:0\]",
    enable => "eop_char_wr_strobe",
  }) if $Options->{use_eop_register};


  e_register->add ({
    out        => "tx_overrun",
    sync_set   => "tx_full && tx_fifo_wr_strobe",
    sync_reset => "status_wr_strobe",
  })if  $Options->{use_fifo};


  e_edge_detector->add ({
    tag  => "simulation",
    out  => "do_write_char",
    in   => "tx_ready",
  });

  e_process->add ({
    tag  => "simulation",
    contents => [
      e_if->new ({
      tag  => "simulation",
      condition       => "do_write_char",
      then            => [
        e_sim_write->new ({
          spec_string => '%c',
          expressions => ["tx_data"],
        })
      ],
    }),
  ]});



  e_signal->add (["divisor_constant", $Options->{divisor_bits}]);
  e_assign->add ({
    tag  => $Options->{sim_true_baud} ? "normal" : "synthesis",
    lhs  => "divisor_constant",
    rhs  => $Options->{baud_divisor_constant}
  });
  e_assign->add ({
    tag   => "simulation",
    lhs   => "divisor_constant",
    rhs   => 4,
  }) if !$Options->{sim_true_baud};




  if ($Options->{fixed_baud}) {
    e_assign->add(["baud_divisor", "divisor_constant"]);
  } else {
    e_register->add ({
      in          => "writedata\[baud_divisor.msb:0\]",
      out         => "baud_divisor",
      enable      => "divisor_wr_strobe",
      async_value => "divisor_constant",
    });
  }







  if ($Options->{use_cts_rts}) {
    e_register->add ({
      in          => "~cts_n",
      out         => "cts_status_bit",
      async_value => 1,
    });

    e_edge_detector->add ({
      in     => "cts_status_bit",
      out    => "cts_edge",
      edge   => "any",
    });

    e_register->add ({
      out         => "dcts_status_bit",
      sync_set    => "cts_edge",
      sync_reset  => "status_wr_strobe",
      async_value => 0,
    });




    e_assign->add (["rts_n", "~rts_control_bit"]);
  } else {


    e_assign->adds (["cts_status_bit",  0],
                    ["dcts_status_bit", 0]);
  }







  e_signal->adds({name => "rts_control_bit", never_export => 1},
                 {name => "ie_dcts",         never_export => 1});

  my @control_reg_bits = ();

  push (@control_reg_bits, "ie_eop"  ) if $Options->{use_eop_register};
  push (@control_reg_bits, "rts_control_bit",
                           "ie_dcts" ) if ($Options->{use_cts_rts} |
                                           $Options->{use_eop_register});

  push (@control_reg_bits, "do_force_break",
                           "ie_any_error",
                           "ie_rx_char_ready",
                           "ie_tx_ready",
                           "ie_tx_shift_empty",
                           "ie_tx_overrun",
                           "ie_rx_overrun",
                           "ie_break_detect",
                           "ie_framing_error",
                           "ie_parity_error",
       );

  e_assign->add([&concatenate(@control_reg_bits), "control_reg"]);




  e_assign->add ({
    lhs    => "any_error",
    rhs    => join (" ||\n", "tx_overrun",
                             "rx_overrun",
                             "parity_error",
                             "framing_error",
                             "break_detect",
                   ),
  });

  my @status_reg_bits = ();
  push (@status_reg_bits, "eop_status_bit",
                          "cts_status_bit",
                          "dcts_status_bit",
                          "1'b0",
                          "any_error",
                          "rx_char_ready",
                          "tx_ready",
                          "tx_shift_empty",
                          "tx_overrun",
                          "rx_overrun",
                          "break_detect",
                          "framing_error",
                          "parity_error",
       )if  !$Options->{use_fifo};

 push (@status_reg_bits, "eop_status_bit",
                          "cts_status_bit",
                          "dcts_status_bit",
                          "1'b0",
                          "any_error",
                          "rx_not_empty",
                          "tx_not_full",
                          "tx_shift_empty",
                          "tx_overrun",
                          "rx_overrun",
                          "break_detect",
                          "framing_error",
                          "parity_error",
       )if  $Options->{use_fifo};

  e_assign->add ({
    lhs => e_signal->add(["status_reg", $Options->{num_status_reg_bits}]),
    rhs => &concatenate (@status_reg_bits),
  });

# comment


  if ( $Options->{use_fifo})
  {
    e_register->add({
      in => "rx_not_empty",
    });
    e_register->add({
      in => "tx_not_full",
    });
    e_register->add({
      in => "rx_rd_strobe",
    });
    
    e_register->add({
      in => "rx_fifo_rd_strobe",
    });
 #   e_register->add({
 #     in => "tx_ready",
 #   });
    e_register->add({
      in => "tx_wr_strobe",
    });

    e_assign->adds
      ([e_port->new (["dataavailable", 1, "out"]),  "d1_rx_not_empty"],
       [e_port->new (["readyfordata",  1, "out"]),  "d1_tx_not_full" ] );
  }
  else
  {
    e_register->add({
      in => "rx_char_ready",
    });
    e_register->add({
      in => "tx_ready",
    });

    e_assign->adds
      ([e_port->new (["dataavailable", 1, "out"]),  "d1_rx_char_ready"],
       [e_port->new (["readyfordata",  1, "out"]),  "d1_tx_ready"     ] );
  }
my $fifo_address_bits = log2($Options->{fifo_size});
if ( $Options->{use_fifo})
{


  my $in_tx_port_map = {
              rdreq   => 'd1_tx_wr_strobe',  #needs to be one clock late
              sclr	  => 'reset',
              clock   => 'clk',
              wrreq	  => 'tx_fifo_wr_strobe',
              data    => "writedata\[tx_data.msb:0\]",
  };
  my $out_tx_port_map = {
			  q       => 'tx_fifo_q',
              usedw    => 'tx_used',
              empty => 'tx_empty',
              full  => 'tx_full',
             };

  my $in_rx_port_map = {
              rdreq   => 'd1_rx_fifo_rd_strobe',
              sclr	  => 'reset',
              clock   => 'clk',
              wrreq	  => 'd1_rx_rd_strobe',
              data    => 'rx_data',

             };

  my $out_rx_port_map = {
              q       => 'rx_data_b',
              usedw    => 'rx_used',
              empty => 'rx_empty',
              full  => 'rx_full',

             };

  my $parameter_map = {
              lpm_width               => $Options->{data_bits},
              lpm_numwords            => $Options->{fifo_size},
			  lpm_widthu			  => $fifo_address_bits,
			  lpm_type				  => qq("scfifo"),
			  lpm_showahead			  => qq("ON"),
			  overflow_checking	  => qq("ON"),
			  underflow_checking	  => qq("ON"),
			  use_eab			  => qq("ON"),
			  };

  e_blind_instance->add({
             tag            => 'normal',
             use_sim_models => 1,
             name           => 'write_fifo',
             module         => 'scfifo',
             in_port_map    => $in_tx_port_map,
             out_port_map   => $out_tx_port_map,
            parameter_map  => $parameter_map,
          });

# e_instance->new({
#             name            => 'write_fifo',
#             module          => 'scfifo',
#             port_map    	 => {
#             	'rdreq'   		 => 'do_load_shifter',
#              	'sclr'	  	 	 => 'reset',
#              	'clock'   	 	 => 'clk',
#              	'wrreq'	  	 	 => 'tx_wr_strobe',
#              	'data'    	 	 => "writedata\[tx_data.msb:0\]",  #"writedata\[tx_data.msb : 0\]"  $Options->{data_bits}
#			  	'q'       	 	 => 'tx_data',
#              	'usedw'    	 	 => 'tx_used',
#              	'empty' 		 => 'tx_empty',
#              	'full'  		 => 'tx_full',
#             }
 #            parameter_map  => $parameter_map,
  #        });

  e_blind_instance->add({
             tag            => 'normal',
             use_sim_models => 1,
             name           => 'read_fifo',
             module         => 'scfifo',
             in_port_map    => $in_rx_port_map,
             out_port_map   => $out_rx_port_map,
             parameter_map  => $parameter_map,
          });
  e_signal->add(["rx_buff_used", $fifo_address_bits+1]);
  e_signal->add(["tx_buff_used", $fifo_address_bits+1]);
  e_signal->add(["rx_used", $fifo_address_bits]);
  e_signal->add(["tx_used", $fifo_address_bits]);
  e_signal->add(["rx_data_b", $Options->{data_bits}]);
  e_signal->add(["tx_fifo_q", $Options->{data_bits}]);
  
  e_assign->add(["rx_buff_used", "\{rx_full,rx_used\}"]);
  e_assign->add(["rx_not_empty", "~rx_empty"]);
  e_assign->add(["rx_not_full", "~rx_full"]);
  e_assign->add(["tx_buff_used", "\{tx_full,tx_used\}"]);
  e_assign->add(["tx_not_full", "~tx_full"]);
  e_assign->add(["tx_not_empty", "~tx_empty"]);
}

  if ($Options->{fifo_export_used} && $Options->{use_fifo}) {
      e_port->add(["rxused", ($fifo_address_bits + 1), "out"]);
      e_port->add(["txused", ($fifo_address_bits + 1), "out"]);
      e_assign->add(["txused", "tx_buff_used"]);
      e_assign->add(["rxused", "rx_buff_used"]);
  }
  if ($Options->{use_eop_register}) {
     e_register->add ({
        out         => "eop_status_bit",

        sync_set    => "(rx_rd_strobe && (eop_char_reg == rx_data)) ||
                        (tx_wr_strobe &&
                          (eop_char_reg == writedata\[tx_data.msb:0\]))",
        sync_reset  => "status_wr_strobe",
        async_value => 0,
     });
     e_assign->add
         ([e_port->new (["endofpacket", 1, "out"]), "eop_status_bit"]);
  } else {

     e_assign->add (["eop_status_bit", "1'b0"]);
  }

  my @read_mux_table = (
    "(address == 3'd1)" => "tx_data",
    "(address == 3'd2)" => "status_reg",
    "(address == 3'd3)" => "control_reg",
  );

  push (@read_mux_table, "(address == 3'd0)" => "rx_data")
    if !$Options->{use_fifo};

  push (@read_mux_table, "(address == 3'd0)" => "rx_data_b")
    if $Options->{use_fifo};

  push (@read_mux_table, "(address == 3'd4)" => "baud_divisor")
    if !$Options->{fixed_baud};

  push (@read_mux_table, "(address == 3'd5)" => "eop_char_reg")
    if  $Options->{use_eop_register};

  push (@read_mux_table, "(address == 3'd6)" => "rx_buff_used")
    if $Options->{use_fifo};

  push (@read_mux_table, "(address == 3'd7)" => "tx_buff_used")
    if $Options->{use_fifo};

  e_mux->add ({
    lhs    => e_signal->add(["selected_read_data", 16]),
    table  => \@read_mux_table,
    type   => "and-or",
  });




  my @irq_terms = ();
  push (@irq_terms, "(ie_dcts           && dcts_status_bit )")
    if $Options->{use_cts_rts};
  push (@irq_terms, "(ie_eop            && eop_status_bit  )")
    if $Options->{use_eop_register};

  push (@irq_terms, "(ie_any_error      && any_error      )",
                    "(ie_tx_shift_empty && tx_shift_empty )",
                    "(ie_tx_overrun     && tx_overrun     )",
                    "(ie_rx_overrun     && rx_overrun     )",
                    "(ie_break_detect   && break_detect   )",
                    "(ie_framing_error  && framing_error  )",
                    "(ie_parity_error   && parity_error   )",
                    "(ie_rx_char_ready  && rx_char_ready  )",
                    "(ie_tx_ready       && tx_ready       )",
       )if  !$Options->{use_fifo};

  push (@irq_terms, "(ie_any_error      && any_error      )",
                    "(ie_tx_shift_empty && tx_shift_empty )",
                    "(ie_tx_overrun     && tx_overrun     )",
                    "(ie_rx_overrun     && rx_overrun     )",
                    "(ie_break_detect   && break_detect   )",
                    "(ie_framing_error  && framing_error  )",
                    "(ie_parity_error   && parity_error   )",
                    "(ie_rx_char_ready  && rx_char_ready  )",
                    "(ie_tx_ready       && tx_not_full    )",
       )if  $Options->{use_fifo};

  e_assign->add (["qualified_irq", join (" ||\n", @irq_terms)]);

  return $module,
}




















sub make_uart_rxd_source
{
  my ($Options) = (@_);
  my $module = e_module->new ({name  => $Options->{rx_source_module_name}});
  my $marker = e_default_module_marker->new ($module);






  e_port->adds(
    ["rxd",           1,                        "in"],
    ["source_rxd",    1,                       "out"],
    ["rx_char_ready", 1,                        "in"],
    ["clk",           1,                        "in"],
    ["clk_en",        1,                        "in"],
    ["reset_n",       1,                        "in"],
    ["rx_char_ready", 1,                        "in"],
    ["baud_divisor",  $Options->{divisor_bits}, "in"],
  );





  e_assign->add({
   tag  => "synthesis",
   lhs  => "source_rxd",
   rhs  => "rxd",
  });








  my @dummies = e_signal->adds (
    ["unused_overrun"],
    ["unused_ready"  ],
    ["unused_empty"  ],
  );

  foreach my $dummy_sig (@dummies) {
    $dummy_sig->never_export   (1);
  }

  e_instance->add ({
    module             => $Options->{"tx_module_name"},
    name               => "stimulus_transmitter",
    tag                => "simulation",
    port_map           => {
      txd                => "source_rxd",
      tx_overrun         => "unused_overrun",
      tx_ready           => "unused_ready",
      tx_shift_empty     => "unused_empty",
      do_force_break     => "1'b0",
      status_wr_strobe   => "1'b0",
      tx_data            => "d1_stim_data",
      begintransfer      => "do_send_stim_data",
      tx_wr_strobe       => "1'b1",
    },
  });





  e_signal->add ({
    tag             => "simulation",
    name            => "stim_data",
    width           => $Options->{data_bits},
  });


  e_register->add ({
    tag    => "simulation",
    in     => "stim_data",
    out    => e_signal->add(["d1_stim_data", $Options->{data_bits}]),
    enable => "do_send_stim_data",
  });
















  my $size = &max ($Options->{mutex_file_size} + 1, 1024);  

  e_drom->add ({
     name	    => $module->name()."_character_source_rom",
     rom_size       => $size,
     dat_name	    => $Options->{char_data_file},
     mutex_name	    => $Options->{char_mutex_file},
     interactive    => $Options->{interactive_in},
     port_map	    => {"q"         => "stim_data",
			"new_rom"   => "new_rom_pulse",
			"incr_addr" => "do_send_stim_data",
		    }
  });





















  e_edge_detector->add ({
    tag             => "simulation",
    out             => "pickup_pulse",
    in              => "rx_char_ready",
    edge            => "falling",
  });





  e_assign->add ({
    tag             => "simulation",
    lhs             => "do_send_stim_data",
    rhs             => "(pickup_pulse || new_rom_pulse) && safe",
  });

  return $module;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -