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

📄 generate_ddr_sim_model.pl

📁 基于NIOS II的ddr2控制器,配有详细的文档,经验证后可使用.
💻 PL
📖 第 1 页 / 共 5 页
字号:
              {name => "dq_temp",      width => $dq_width},
              
              ),
             e_assign->news
             (
              ["cke"   => $default_pin_prefix."cke"],
              ["cs_n"  => $default_pin_prefix."cs_n"],
              ["ras_n" => $default_pin_prefix."ras_n"],
              ["cas_n" => $default_pin_prefix."cas_n"],
              ["we_n"  => $default_pin_prefix."we_n"],
              ["dm"    => $default_pin_prefix."dm"],
              ["ba"    => $default_pin_prefix."ba"],
              ["a"     => $default_pin_prefix."a"],
              ),
             );
    
        # my $x;
        # if ($number_of_lump_delays > 1) {
            # for ($x=0; $x < ($number_of_lump_delays ); $x++) {            
                # #print "connecting lump delay $x out of $number_of_lump_delays\n";
                # $module->add_contents
                # (
                    # e_signal->news
                    # (
                       # {name => "dqs_out_".$x,     width => $dqs_width},
                       # {name => "dq_out_".$x,      width => $dq_width},
                    # )
                # );
            # }
        # }
    
             
             
        # Now the fun begins ;-)
    
        $module->add_contents
            (
             # Define txt_code based on ras/cas/we
             e_assign->new
             ({
                 lhs => e_signal->new({name => "cmd_code", width => 3}),
                 rhs => "{ras_n, cas_n, we_n}",
             }),
             e_sim_wave_text->new
             ({
                 out     => "txt_code",
                 selecto => "cmd_code",
                 table   =>
                     [
                      "3'h0" => "LMR",
                      "3'h1" => "ARF",
                      "3'h2" => "PRE",
                      "3'h3" => "ACT",
                      "3'h4" => " WR",
                      "3'h5" => " RD",
                      "3'h6" => "BST",
                      "3'h7" => "NOP",
                      ],
                     default => "BAD",
                 }),
             # "Inhibit" if no chip_selects,
             e_signal->new({name => "CODE", width=> 8*3, never_export => 1}),
             e_assign->new(["CODE" => "(\&cs_n) ? $STR_INH : txt_code"]),
             );
    
        ## Row/Col Address Construction:
        # We're constructing a monolithic address into a single large array.
        # If there are multiple chip-selects, we assume they are one-hot
        # encoded (that's what our controller drives).
    
       
        # First, we'll build up row/bank. (arb == address_row_bank)
        my $arb_rhs;
        #my $arb_width = $WSA->{sdram_bank_width} + $WSA->{sdram_row_width};
        my $arb_width = $ba_width + $row_width;
    
        $arb_rhs = "{ba, a}";
        # if ($ba_width == 1)
        # {
            # # We only have 2 banks, row/addr build as {row,bank}
            # $arb_rhs = "{a, ba}";
        # }
        # elsif ($ba_width == 2)
        # {
            # # 4 banks construct address as {bank[1],row,bank[0]}
            # $arb_rhs = "{ba[1], a, ba[0]}"
        # }
    
        # then we'll tack cs_encoded bits as the top bits, if applicable
        # (acrb == addr_chip-select_row_bank)
        my $acrb_rhs;
        my $acrb_width = $arb_width;
        if ($num_chipselects < 2)
        {
            # Single chipselect does not affect address:
            $acrb_rhs  = $arb_rhs;
        }
        else
        {
            # Multiple chipselects are encoded to create high order addr bits.
            # Note that &one_hot_encoding outputs a properly ordered @list!
            my %cs_encode_hash = 
                ( default => ["cs_encode" => $num_chipselect_address_bits."'h0"] );
            my @raw_cs = &one_hot_encoding($num_chipselects);
            # print "\&make_sodimm: num_cs = $num_chipselects \t \@raw_cs = @raw_cs\n";
            my $cs_count = 0;
            foreach my $chip_select (@raw_cs) {
                $cs_encode_hash{$chip_select} =
                    [
                     e_assign->new
                     (
                      ["cs_encode" => $num_chipselect_address_bits."'h".$cs_count],
                      )
                     ];
                $cs_count++;
            } # foreach (@raw_cs)
    
            # Create the cs_encode signal, and use a case statement to define it.
            $module->add_contents
                (
                 e_signal->news
                 (
                  {name => "cs",        width=> $num_chipselects},
                  {name => "cs_encode", width=> $num_chipselect_address_bits},
                  ),
                 e_assign->new(["cs" => "~cs_n"]), # invert cs_n for encoding
                 e_process->new({
                     clock   => "",
                     comment =>
                         "Encode 1-hot ChipSelects into high order address bit(s)",
                     contents=>
                         [
                          e_case->new({
                              switch => "cs",
                              parallel => 1,
                              contents => {%cs_encode_hash},
                          }),
                          ],
                 }),
                 );
            # prepend the encoded bits as upper order addr bits, and remember width
            $acrb_rhs    = "{cs_encode, $arb_rhs}";
            $acrb_width += $num_chipselect_address_bits;
        }
        # define/assign final construction signals
        # (ac_rhs == addr_col), constructed to avoid A[10] for large col_width
        my $ac_rhs = "a[".($col_width-1).":1]";
        # if ($col_width < 11) {
            # $ac_rhs = "a[".($col_width-1).":0]";
        # } elsif ($col_width == 11) {
            # $ac_rhs = "{a[11],a[9:0]}";
        # } else {
            # $ac_rhs = "{a[".$col_width.":11],a[9:0]}";
        # }
        my $read_addr_width = $acrb_width + $col_width;
        $module->add_contents
            (
             e_signal->news
             (
              #{name => "addr_crb", width=> $acrb_width},
              {name => "addr_col", width=> $col_width - 1},
              {name => "test_addr",width=> $read_addr_width},
              # {name => "temp_addr",width=> $read_addr_width},
              ),
             e_signal->news
             (
              {name => "rd_addr_pipe_0", width=> $read_addr_width, default_value => "0",export => 0, never_export => 1},
              {name => "rd_addr_pipe_1", width=> $read_addr_width, default_value => "0",export => 0, never_export => 1},
              {name => "rd_addr_pipe_2", width=> $read_addr_width, default_value => "0",export => 0, never_export => 1},
              {name => "rd_addr_pipe_3", width=> $read_addr_width, default_value => "0",export => 0, never_export => 1},
              {name => "rd_addr_pipe_4", width=> $read_addr_width, default_value => "0",export => 0, never_export => 1},
              {name => "rd_addr_pipe_5", width=> $read_addr_width, default_value => "0",export => 0, never_export => 1},
              {name => "read_addr_delayed", width=> $read_addr_width, default_value => "0",export => 0, never_export => 1},
              {name => "rmw_address", width=> $read_addr_width, default_value => "0",export => 0, never_export => 1},
          
              {name => "wr_addr_pipe_0", width=> $read_addr_width, default_value => "0",export => 0, never_export => 1},
              {name => "wr_addr_pipe_1", width=> $read_addr_width, default_value => "0",export => 0, never_export => 1},
              {name => "wr_addr_pipe_2", width=> $read_addr_width, default_value => "0",export => 0, never_export => 1},
              {name => "wr_addr_pipe_3", width=> $read_addr_width, default_value => "0",export => 0, never_export => 1},
              {name => "wr_addr_pipe_4", width=> $read_addr_width, default_value => "0",export => 0, never_export => 1},
              {name => "wr_addr_pipe_5", width=> $read_addr_width, default_value => "0",export => 0, never_export => 1},
              {name => "wr_addr_delayed", width=> $read_addr_width, default_value => "0",export => 0, never_export => 1},
              {name => "wr_burst_counter", width=> $read_addr_width, default_value => "0",export => 0, never_export => 1},
              {name => "rd_burst_counter", width=> $read_addr_width, default_value => "0",export => 0, never_export => 1},
              ),
             e_assign->news
             (
              ["addr_col" => $ac_rhs],
              # ["test_addr"=> "{addr_crb, addr_col}"],
              ),
             );
    
        ## Define some random necessary variables:
        # we only support up to a max cas_latency of 3, and just soak up that many
        #resources, and pluck off an earlier version if the cas_latency is set
        #lower during LMR...
        $module->add_contents
            (
             e_signal->news
             (
              {name => "rd_valid_pipe",   width=> 6}, # was 5?
              {name => "wr_valid_pipe",   width=> 6}, # was 5?
              #{name => "latency",         width=> 3},
              {name => "index",           width=> 3},
              ),
             );
        
        ## Set up ram read/wr var's and initial block to readmem our dat file:
        $module->add_contents
            (
             e_signal->news
             (
              {name => "rmw_temp", width=> $mem_width},
              {name => "mem_bytes",width=> $mem_width},
              {name => "read_data",width=> $mem_width},
              {name => "read_temp",width=> $mem_width,export => 0, never_export => 1},
              {name => "read_valid",width=> 1,export => 0, never_export => 1},
              {name => "read_cmd",width=> 1,export => 0, never_export => 1},
              {name => "write_valid_r" , width => 1, export => 0, never_export => 1},
              {name => "read_valid_r"  , width => 1, export => 0, never_export => 1},
              {name => "write_valid_r2", width => 1, export => 0, never_export => 1},
              {name => "write_valid_r3", width => 1, export => 0, never_export => 1},
              {name => "write_to_ram_r", width => 1, export => 0, never_export => 1},
              {name => "read_valid_r2" , width => 1, export => 0, never_export => 1},
              {name => "read_valid_r3" , width => 1, export => 0, never_export => 1},
              {name => "read_valid_r4" , width => 1, export => 0, never_export => 1},             
  
              {name => "burstmode",width=> 1,export => 0, never_export => 1},
              {name => "burstlength",width=> 3,export => 0, never_export => 1},
              ),
             e_assign->new(["current_row" => "{cs_n,ba}"]),
             );
    
        #sjh - No need for *read* masking with DDR
        # # Try to make life easier by defining the necessary number of byte lane
        # #field descriptors like 7:0, 15:8, etc...
        my %lanes;
        my $byte_lane;
        # # assign rmw_temp[7:0]= dqm[0] ? mem_bytes[7:0] : $dq[7:0]
        # if ($mem_mask_width > 1) {
            # for (0 .. ($mem_mask_width-1))
            # {
                # $byte_lane = $_;
                # $lanes{$byte_lane} = (($byte_lane*8)+7).":".($byte_lane*8);
                # $module->add_contents
                    # (
                     # e_assign->new
                     # (
                      # ["rmw_temp[$lanes{$byte_lane}]" =>
                       # "dm[$byte_lane] ? ".
                       # "mem_bytes[$lanes{$byte_lane}] : ".$dq."[$lanes{$byte_lane}]"]
                      # )
                     # );
            # } # for (0 to ($dm_width-1))
        # } else {
            # $module->add_contents
                # (
                 # e_assign->new(["rmw_temp" => "dm ? mem_bytes : ".$dq])
                 # );
        # }
        
        # Build the Main Process:
        $module->add_contents
            (
             e_process->new
             ({
                 comment => " Decode commands into their actions",
                 contents => 
                     [
                      e_if->new({
                          comment => " No Activity if the clock is",
                          condition => "cke",
                          then => 
                              [
                              e_if->new({
                                   comment   => " This is a read command",
                                   condition => "(cmd_code == 3'b101)",
                                   then      => [e_assign->news 
                                                 (["read_cmd" => "1'b1"],
                                                  # ["rd_addr_pipe_0" => "{ba,open_rows[current_row],addr_col}"],
                                                 ),
                                                ],
                                   else      => ["read_cmd"  => "1'b0"],
                               }),
                               
                               e_if->new({
                                   comment   => " This is a write command",
                                   condition => "(cmd_code == 3'b100)",
                                   then      => [e_assign-> news
                                                 (["write_cmd" => "1'b1"],
                                                  #["wr_addr_pipe_0" => "{ba,open_rows[current_row],addr_col}"],

⌨️ 快捷键说明

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