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

📄 em_uart.pl

📁 UART RS232 IPCORE for sopc builder
💻 PL
📖 第 1 页 / 共 3 页
字号:

  my $newline      = "\n";
  my $cr           = "\n";
  my $double_quote = "\"";
  


  $char_stream =~ s/\\n\\r/\n/sg;
  
  $char_stream     =~ s/\\n/$newline/sg;
  $char_stream     =~ s/\\r/$cr/sg;
  $char_stream     =~ s/\\\"/$double_quote/sg;

  my $crlf = "\n\r";
  $char_stream =~ s/\n/$crlf/smg;

  $Options->{stream_length} = length ($char_stream);
  
  $Options->{char_data_file} = $Options->{name} . "_input_data_stream.dat";
  $Options->{char_mutex_file} = $Options->{name} . "_input_data_mutex.dat";

  my $sim_dir_name = $project->simulation_directory();
  &Create_Dir_If_Needed($sim_dir_name);

  open (DATFILE, "> $sim_dir_name/$Options->{char_data_file}") 
    or &ribbit ("couldn't open $sim_dir_name/$Options->{char_data_file} ($!)");

  my $addr = 0;
  foreach my $char (split (//, $char_stream)) {
    printf DATFILE "\@%X\n", $addr; 
    printf DATFILE "%X\n", ord($char);
    $addr++;
  }

  printf DATFILE "\@%X\n", $addr;
  printf DATFILE "%X\n", 0;

  close DATFILE;

  open (MUTFILE, "> $sim_dir_name/$Options->{char_mutex_file}") 
   or &ribbit ("couldn't open $sim_dir_name/$Options->{char_mutex_file} ($!)");
  

  if ($Options->{interactive_in})
  { # force user to use interactive window if selected by making mutex 0
      printf MUTFILE "0\n";
  }
  else
  { # set up proper stream file size in Mutex:
      printf MUTFILE "%X\n", $addr;
  }

  close MUTFILE;
  $Options->{mutex_file_size} = $addr;
}


































sub make_uart
{
  my ($project) = (@_);

  my $module  = $project->top();
  my $Options = &copy_of_hash ($project->WSA());




  $Options->{name}       = $module->name();
  $Options->{clock_freq} = 
    $project->system_ptf->{WIZARD_SCRIPT_ARGUMENTS}{clock_freq};


  my $int_in_section = 
$project->spaceless_module_ptf($Options->{name})->{SIMULATION}{INTERACTIVE_IN};
  my $int_out_section=
$project->spaceless_module_ptf($Options->{name})->{SIMULATION}{INTERACTIVE_OUT};
  my $interactive_in = 0; # default to non-interactive mode.
  my $interactive_out= 0;

  my $int_key;
  my $this_int_section;

  foreach $int_key (sort(keys (%{$int_in_section}))) {
      $this_int_section = $int_in_section->{$int_key};
      $interactive_in = $this_int_section->{enable};

  }


  foreach $int_key (sort(keys (%{$int_out_section}))) {
      $this_int_section = $int_out_section->{$int_key};
      $interactive_out = $this_int_section->{enable};

  }

  $Options->{interactive_in} = $interactive_in;
  $Options->{interactive_out}= $interactive_out;

  &Validate_Uart_Options ($Options, $project);




  &Setup_Input_Stream ($Options, $project);
  




  return if $project->_software_only();







  $Options->{tx_module_name}  = $Options->{name} . "_tx";
  $Options->{rx_module_name}  = $Options->{name} . "_rx";
  $Options->{reg_module_name} = $Options->{name} . "_regs";
  $Options->{log_module_name} = $Options->{name} . "_log";

  my $tx_module  = &make_uart_tx  ($Options);
  my $rx_module  = &make_uart_rx  ($Options);
  my $reg_module = &make_uart_regs($Options);
  my $log_instance = &make_uart_log ($Options);






  my $marker = e_default_module_marker->new ($module);







  e_assign->add(["clk_en", 1]);

  e_instance->add ({module => $tx_module });
  e_instance->add ({module => $rx_module });
  e_instance->add ({module => $reg_module});

  $module->add_contents ( $log_instance );



  if ($Options->{interactive_in})
  {
      &Perlcopy ($project->_module_lib_dir . "/uart.pl",
		 $project->simulation_directory () . "/uart.pl" );
  }


  if ($Options->{interactive_out})
  {
      &Perlcopy ($project->_module_lib_dir . "/tail-f.pl",
                 $project->simulation_directory () . "/tail-f.pl" );
  }
  










  e_avalon_slave->add ({name => "s1"});

  return $module;
}







sub make_uart_log {
    my ($Options) = (@_);
    return e_log->new ({
	name            => $Options->{"log_module_name"},
	tag             => "simulation",
	port_map        => {
	    "valid"	=> "~tx_ready",
	    "strobe"	=> "tx_wr_strobe",
	    "data"	=> "tx_data",
	    "log_file"	=> $Options->{log_file},
	},
    });

};

sub make_uart_tx
{
  my ($Options) = (@_);


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

# calculation the text for the code
 my $parity_expr = "";
     $parity_expr = "1'b0"        if ($Options->{parity} =~ /^S0$/i);
     $parity_expr = "1'b1"        if ($Options->{parity} =~ /^S1$/i);
     $parity_expr = "  ^tx_data " if ($Options->{parity} =~ /^E$/i );
     $parity_expr = "~(^tx_data)" if ($Options->{parity} =~ /^O$/i );


# calculating the size of the shift reister
  my $tx_shift_bits =
    ($Options->{stop_bits}             )  +   # stop bits.
    ($Options->{parity} =~ /N/i ? 0 : 1)  +   # parity bit (opt.)
    ($Options->{data_bits}             )  +   # "payload"
    (1                                 )  ;   # start-bit


  if($Options->{use_fifo} == 0)
  {
      e_assign->add (["tx_wr_strobe_onset",  "tx_wr_strobe && begintransfer"]),  # cruben  this should be based on if you need a fifo or not
           e_signal->add(["tx_data", $Options->{data_bits}]);
  }
  else
  {
   	  e_assign->add (["tx_wr_strobe_onset",  "tx_wr_strobe && tx_ready"]),  #cruben
           e_signal->add(["tx_data", $Options->{data_bits}]);
  }

  my $load_val_expr = &concatenate ("\{$Options->{stop_bits} \{1'b1\}\}",
                                    $parity_expr,
                                    "tx_data",
                                    "1'b0",
                                   );

  e_assign->add ({lhs => e_signal->add (["tx_load_val", $tx_shift_bits]),
                  rhs => $load_val_expr,
  });










  e_assign->add (["shift_done", "~(|tx_shift_register_contents)"]);

# added an additional port used when with fifos  cruben
#  e_register->add ({out => e_port->add (["do_load_shifter",1,"out"]),
#                     in  => "(~tx_ready) && shift_done",
#                    })if  $Options->{use_fifo};

  e_register->add ({out => "do_load_shifter",
                     in  => "(~tx_ready) && shift_done",
                    });











  e_register->add ({
    out         => e_port->add (["tx_ready", 1, "out"]),
    sync_set    => "do_load_shifter",
    sync_reset  => "tx_wr_strobe_onset",
    async_value => "1'b1",
  });




  e_register->add ({
    out        => "tx_overrun",
    sync_set   => "(~tx_ready && tx_wr_strobe_onset)",
    sync_reset => "status_wr_strobe",
  })if  !$Options->{use_fifo};

  e_register->add ({
    out         => "tx_shift_empty",
    in          => "tx_ready && shift_done",
    async_value => "1'b1",
  });













  e_register->add ({
      out        => e_signal->add({name  => "baud_rate_counter",
                                   width => $Options->{divisor_bits}
                                  }),
      in         => "baud_rate_counter - 1",
      sync_set   => "baud_rate_counter_is_zero || do_load_shifter",
      set_value  => "baud_divisor",
    });

  e_assign->add(["baud_rate_counter_is_zero", "baud_rate_counter == 0"]);

  e_register->add ({out    => "baud_clk_en",
                    in     => "baud_rate_counter_is_zero",
                   });









  e_assign->add(["do_shift", "baud_clk_en  &&
                             (~shift_done) &&
                             (~do_load_shifter)"
   ]);

  e_shift_register->add ({
    serial_out   => "tx_shift_reg_out",
    serial_in    => "1'b0",
    parallel_in  => "tx_load_val",
    parallel_out => "tx_shift_register_contents",
    shift_length => $tx_shift_bits,
    direction    => "LSB-first",
    load         => "do_load_shifter",
    shift_enable => "do_shift",
  });










  e_register->add({
    out         => "pre_txd",
    in          => "tx_shift_reg_out",
    enable      => "~shift_done",
    async_value => "1",
  });

  e_register->add ({
    out         => "txd",
    in          => "pre_txd & ~do_force_break",
    async_value => "1",
  });

  return $module;
}
















































sub make_uart_rx
{
  my ($Options) = (@_);






  $Options->{rx_source_module_name} =
    $Options->{rx_module_name} . "_stimulus_source";
  my $stim_module = &make_uart_rxd_source($Options);


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

  e_instance->add ({module => $stim_module});










  e_register->add({
    out    => "sync_rxd",
    in     => "source_rxd",
    delay  => 2,
  });



  e_edge_detector->add({
    in     => "sync_rxd",
    out    => "rxd_falling",
    edge   => "falling",
  });

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






 if($Options->{use_fifo} == 0)
  {
      e_assign->add (["rx_rd_strobe_onset", "rx_rd_strobe && begintransfer"]);
  }
  else
  {
   	  e_assign->add (["rx_rd_strobe_onset", "rx_rd_strobe"]);
  }
























  e_signal->add (["half_bit_cell_divisor", $Options->{divisor_bits} - 1]);
  e_assign->add ({
    lhs => "half_bit_cell_divisor",
    rhs => 'baud_divisor [baud_divisor.msb : 1]',
  });

  e_mux->add ({
    lhs     => e_signal->add (["baud_load_value", $Options->{divisor_bits}]),
    table   => [rxd_edge => "half_bit_cell_divisor"],
    default => "baud_divisor",
  });

  e_register->add ({
    out       => e_signal->add(["baud_rate_counter",$Options->{divisor_bits}]),
    in        => "baud_rate_counter - 1",
    sync_set  => "baud_rate_counter_is_zero || rxd_edge",
    set_value => "baud_load_value",
  });

  e_assign->add (["baud_rate_counter_is_zero", "baud_rate_counter == 0"]);

  e_register->add ({
    in        => "baud_rate_counter_is_zero",
    out       => "baud_clk_en",
    sync_set  => "rxd_edge",
    set_value => "0",
  });










  e_assign->add (["sample_enable", "baud_clk_en && rx_in_process"]);

  e_register->add ({
    out         => "do_start_rx",
    in          => "0",
    sync_set    => "(~rx_in_process && rxd_falling)",
    set_value   => "1",
    async_value => "0",
  });







  my $rx_shift_bits = 
    (1                                 )  +   # stop bit.
    ($Options->{parity} =~ /N/i ? 0 : 1)  +   # parity bit (opt.)
    ($Options->{data_bits}             )  +   # "payload"
    (1                                 )  ;

  e_shift_register->add ({
    parallel_out => "rxd_shift_reg",
    serial_in    => "sync_rxd",
    serial_out   => "shift_reg_start_bit_n",
    parallel_in  => "\{$rx_shift_bits\{1'b1\}\}",
    shift_length => $rx_shift_bits,
    direction    => "LSB-first",
    load         => "do_start_rx",
    shift_enable => "sample_enable",
  });

  e_assign->add (["rx_in_process", "shift_reg_start_bit_n"]);



  e_signal->add (["raw_data_in", $Options->{data_bits}]);








  my $start_bit_sig = e_signal->add(["unused_start_bit", 1]);
  $start_bit_sig->never_export(1);

  my    @register_segments = ("stop_bit"  );
  push (@register_segments,   "parity_bit") unless $Options->{parity} =~/^N$/i;
  push (@register_segments,   "raw_data_in",
                              "unused_start_bit");

  e_assign->add([&concatenate (@register_segments), "rxd_shift_reg"]);









  e_assign->adds(["is_break",         "~(|rxd_shift_reg)"      ],
                 ["is_framing_error", "~stop_bit && ~is_break" ]);




  e_edge_detector->add ({
    out    => "got_new_char",
    in     => "rx_in_process",
    edge   => "falling",
  });

  e_register->add({
    in     => "raw_data_in",
    out    => e_signal->add(["rx_data", $Options->{data_bits}]),
    enable => "got_new_char",
  });

  e_register->add({
    out        => "framing_error",
    sync_set   => "(got_new_char && is_framing_error)",
    sync_reset => "status_wr_strobe",
  });

  e_register->add({
    out        => "break_detect",
    sync_set   => "(got_new_char && is_break)",
    sync_reset => "status_wr_strobe",
  });

  e_register->add({
    out        => "rx_overrun",
    sync_set   => "(got_new_char && rx_char_ready)",
    sync_reset => "status_wr_strobe",
  });

  e_register->add({
    out        => e_port->add (["rx_char_ready", 1, "out"]),
    sync_set   => "got_new_char",
    sync_reset => "rx_rd_strobe_onset",
    priority   => "reset",
  });



  if ($Options->{parity} =~ /^N$/i) {
    e_assign->add (["parity_error", "0"]);
  } else {
    my $correct_parity_expr = "";
    $correct_parity_expr = "0"               if $Options->{parity} =~ /^S0$/i;
    $correct_parity_expr = "1"               if $Options->{parity} =~ /^S1$/i;
    $correct_parity_expr = " (^raw_data_in)" if $Options->{parity} =~ /^E$/i;
    $correct_parity_expr = "~(^raw_data_in)" if $Options->{parity} =~ /^O$/i;

    e_assign->add (["correct_parity", $correct_parity_expr]);

    e_assign->add ({
      lhs    => "is_parity_error",
      rhs    => "(correct_parity != parity_bit) && ~is_break",
    });

    e_register->add ({
      out        => "parity_error",
      sync_set   => "got_new_char && is_parity_error",
      sync_reset => "status_wr_strobe",
    });
  }

⌨️ 快捷键说明

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