OpenCores
URL https://opencores.org/ocsvn/hssdrc/hssdrc/trunk

Subversion Repositories hssdrc

[/] [hssdrc/] [trunk/] [rtl/] [hssdrc_decoder_state.v] - Rev 3

Compare with Previous | Blame | View Log

//
// Project      : High-Speed SDRAM Controller with adaptive bank management and command pipeline
// 
// Project Nick : HSSDRC
// 
// Version      : 1.0-beta 
//  
// Revision     : $Revision: 1.1 $ 
// 
// Date         : $Date: 2008-03-06 13:52:43 $ 
// 
// Workfile     : hssdrc_decoder_state.v
// 
// Description  : sdram command sequence decoder
// 
// HSSDRC is licensed under MIT License
// 
// Copyright (c) 2007-2008, Denis V.Shekhalev (des00@opencores.org) 
// 
// Permission  is hereby granted, free of charge, to any person obtaining a copy of
// this  software  and  associated documentation files (the "Software"), to deal in
// the  Software  without  restriction,  including without limitation the rights to
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
// the  Software, and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:
// 
// The  above  copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
// 
// THE  SOFTWARE  IS  PROVIDED  "AS  IS",  WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR  A  PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT  HOLDERS  BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN  AN  ACTION  OF  CONTRACT,  TORT  OR  OTHERWISE,  ARISING  FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
 
 
`include "hssdrc_timescale.vh"
 
`include "hssdrc_timing.vh"
`include "hssdrc_define.vh"
 
 
module hssdrc_decoder_state (
  clk               ,
  reset             ,
  sclr              ,
  //
  ba_map_update     ,
  ba_map_clear      ,
  ba_map_pre_act_rw ,
  ba_map_act_rw     ,
  ba_map_rw         ,
  ba_map_all_close  ,
  //
  arb_write         ,
  arb_read          ,
  arb_refr          ,
  arb_rowa          ,
  arb_cola          ,
  arb_ba            ,
  arb_burst         ,
  arb_chid          ,
  arb_ready         ,
  //
  dec_pre_all       ,
  dec_refr          ,
  dec_pre           ,
  dec_act           ,
  dec_read          ,
  dec_write         ,  
  //
  dec_pre_all_enable,
  dec_refr_enable   ,
  dec_pre_enable    ,
  dec_act_enable    ,
  dec_read_enable   ,
  dec_write_enable  ,
  //
  dec_locked        ,
  dec_last          ,
  //
  dec_rowa          ,
  dec_cola          ,
  dec_ba            ,
  dec_chid          ,
  //
  dec_burst
  );
 
  input   wire  clk  ;
  input   wire  reset;
  input   wire  sclr ;
 
  //-------------------------------------------------------------------------------------------------- 
  // bank map interface 
  //-------------------------------------------------------------------------------------------------- 
 
  output  logic ba_map_update     ;
  output  logic ba_map_clear      ;
  input   wire  ba_map_pre_act_rw ;
  input   wire  ba_map_act_rw     ;
  input   wire  ba_map_rw         ;
  input   wire  ba_map_all_close  ;
 
  //-------------------------------------------------------------------------------------------------- 
  // interface from input arbiter 
  //-------------------------------------------------------------------------------------------------- 
 
  input   wire    arb_write ;
  input   wire    arb_read  ;
  input   wire    arb_refr  ;
  input   rowa_t  arb_rowa  ;
  input   cola_t  arb_cola  ;
  input   ba_t    arb_ba    ;  
  input   burst_t arb_burst ;
  input   chid_t  arb_chid  ;
  output  logic   arb_ready ;
 
  //-------------------------------------------------------------------------------------------------- 
  // inteface to output arbiter
  //-------------------------------------------------------------------------------------------------- 
 
  // logical commands 
  output logic          dec_pre_all       ;   
  output logic          dec_refr          ;   
  output logic          dec_pre           ;   
  output logic          dec_act           ;   
  output logic          dec_read          ;   
  output logic          dec_write         ;   
  // logical commands en
  input  wire          dec_pre_all_enable ;
  input  wire          dec_refr_enable    ;
  input  wire          dec_pre_enable     ;
  input  wire          dec_act_enable     ;
  input  wire          dec_read_enable    ;
  input  wire          dec_write_enable   ;
  // addititional signal                  
  output logic         dec_locked         ;     
  output logic         dec_last           ;     
  // control path                         
  output rowa_t        dec_rowa           ;     
  output cola_t        dec_cola           ;     
  output ba_t          dec_ba             ;     
  output chid_t        dec_chid           ;     
  //                                      
  output sdram_burst_t dec_burst          ; 
 
  //-------------------------------------------------------------------------------------------------- 
  //
  //-------------------------------------------------------------------------------------------------- 
 
  localparam int cTrp_m1  = cTrp  - 1;
  localparam int cTrcd_m1 = cTrcd - 1; 
 
  typedef enum {
    STATE_RESET_BIT   ,   // need for create simple true ready condition 
    STATE_IDLE_BIT    , 
    STATE_DECODE_BIT  , 
    STATE_PRE_BIT     , 
    STATE_TRP_BIT     , 
    STATE_ACT_BIT     , 
    STATE_TRCD_BIT    ,
    STATE_RW_BIT      , 
    STATE_ADDR_INC_BIT, 
    STATE_PRE_ALL_BIT , 
    STATE_REFR_BIT      
    } state_bits_e;
 
  //-------------------------------------------------------------------------------------------------- 
  //
  //-------------------------------------------------------------------------------------------------- 
 
  enum bit [10:0] {
    STATE_RESET     = (11'h1 << STATE_RESET_BIT)     , 
    STATE_IDLE      = (11'h1 << STATE_IDLE_BIT)      , 
    STATE_DECODE    = (11'h1 << STATE_DECODE_BIT)    , 
    STATE_PRE       = (11'h1 << STATE_PRE_BIT)       , 
    STATE_TRP       = (11'h1 << STATE_TRP_BIT)       , 
    STATE_ACT       = (11'h1 << STATE_ACT_BIT)       , 
    STATE_TRCD      = (11'h1 << STATE_TRCD_BIT)      , 
    STATE_RW        = (11'h1 << STATE_RW_BIT)        , 
    STATE_ADDR_INC  = (11'h1 << STATE_ADDR_INC_BIT)  , 
    STATE_PRE_ALL   = (11'h1 << STATE_PRE_ALL_BIT)   ,
    STATE_REFR      = (11'h1 << STATE_REFR_BIT)
    } state, next_state;
 
  logic   refr_mode       ; 
  logic   write_mode      ; 
 
  logic   burst_done      ; 
  logic   early_burst_done;
 
  cola_t  cola_latched  ;
  rowa_t  rowa_latched  ;
  ba_t    ba_latched    ;  
  chid_t  chid_latched  ;
 
  logic [3:0] burst_latched   ;
  logic [3:0] burst_shift_cnt ;
 
  logic [3:0] available_burst ; 
 
  logic [3:0] remained_burst      ; 
  logic [1:0] remained_burst_high ;
  logic [1:0] remained_burst_low  ;
  logic [1:0] remained_burst_low_latched;
 
  logic [3:0] last_used_burst; 
 
  wire trp_cnt_done; 
  wire trcd_cnt_done; 
 
  //-------------------------------------------------------------------------------------------------- 
  // use shift register instead of counter for trp time count 
  //-------------------------------------------------------------------------------------------------- 
 
  generate
    if (cTrp_m1 <= 1) begin : no_trp_cnt_generate 
 
      assign trp_cnt_done = 1'b1; 
 
    end 
    else begin : trp_cnt_generate 
 
      logic [cTrp_m1-2:0] trp_cnt;
 
      always_ff @(posedge clk) begin
        if (state [STATE_TRP_BIT])
          trp_cnt <= (trp_cnt << 1) | 1'b1; 
        else 
          trp_cnt <= '0;
      end 
 
      assign trp_cnt_done = trp_cnt [cTrp_m1-2]; 
 
    end 
  endgenerate 
 
  //-------------------------------------------------------------------------------------------------- 
  // use shift register instead of counter for trcd time count 
  //-------------------------------------------------------------------------------------------------- 
 
  generate
    if (cTrcd_m1 <= 1) begin : no_trcd_cnt_generate
 
      assign trcd_cnt_done = 1'b1;
 
    end 
    else begin : trcd_cnt_generate
 
      logic [cTrcd_m1-2:0] trcd_cnt; 
 
      always_ff @(posedge clk) begin 
        if (state [STATE_TRCD_BIT])
          trcd_cnt <= (trcd_cnt << 1) | 1'b1; 
        else 
          trcd_cnt <= '0;
      end 
 
      assign trcd_cnt_done = trcd_cnt [cTrcd_m1-2];
 
    end 
  endgenerate
 
  //-------------------------------------------------------------------------------------------------- 
  //
  //-------------------------------------------------------------------------------------------------- 
 
  always_comb begin : fsm_jump_decode 
 
    next_state = STATE_RESET; 
 
    unique case (1'b1) 
 
      state [STATE_RESET_BIT] : begin 
        next_state = STATE_IDLE; 
      end 
 
      state [STATE_IDLE_BIT] : begin 
        if (arb_write | arb_read | arb_refr)
          next_state = STATE_DECODE; 
        else 
          next_state = STATE_IDLE;
      end 
      //
      // decode branch 
      // 
      state [STATE_DECODE_BIT] : begin 
        if (refr_mode) begin : shorten_refresh_decode
 
          if (ba_map_all_close) 
            next_state = STATE_REFR; 
          else 
            next_state = STATE_PRE_ALL; 
 
        end 
        else begin : mode_of_rw_decode
 
          if (ba_map_pre_act_rw) 
            next_state = STATE_PRE; 
          else if (ba_map_rw) 
            next_state = STATE_RW; 
          else // if (ba_map_act_rw) 
            next_state = STATE_ACT;
 
        end 
      end 
      //
      // pre branch 
      // 
      state [STATE_PRE_BIT] : begin 
        if (dec_pre_enable) 
 
          if (cTrp_m1 == 0)
            next_state = STATE_ACT; 
          else 
            next_state = STATE_TRP;
 
        else 
          next_state = STATE_PRE;
      end 
 
      state [STATE_TRP_BIT] : begin 
        if (trp_cnt_done) 
          next_state = STATE_ACT; 
        else 
          next_state = STATE_TRP;
      end 
      //
      // act branch
      // 
      state [STATE_ACT_BIT] : begin 
        if (dec_act_enable) 
 
          if (cTrcd_m1 == 0)
            next_state = STATE_RW; 
          else 
            next_state = STATE_TRCD;
 
        else 
          next_state = STATE_ACT;
      end 
 
      state [STATE_TRCD_BIT] : begin 
        if (trcd_cnt_done) 
          next_state = STATE_RW;
        else 
          next_state = STATE_TRCD;
      end 
      //
      // data branch 
      // 
      state [STATE_RW_BIT] : begin 
        if ((dec_write_enable & write_mode) | (dec_read_enable & ~write_mode)) begin : burst_done_decode
 
          if (burst_done)
            next_state = STATE_IDLE; 
          else 
            next_state = STATE_ADDR_INC;
 
        end 
        else begin 
          next_state = STATE_RW;
        end           
      end 
 
      state [STATE_ADDR_INC_BIT] : begin 
        next_state = STATE_RW;
      end 
      //
      // refresh breanch 
      //
      state [STATE_PRE_ALL_BIT] : begin 
        if (dec_pre_all_enable)
          next_state = STATE_REFR; 
        else 
          next_state = STATE_PRE_ALL;
      end 
 
      state [STATE_REFR_BIT] : begin 
        if (dec_refr_enable)
          next_state = STATE_IDLE; 
        else 
          next_state = STATE_REFR;
      end 
 
    endcase 
  end 
 
  //---------------------------------------------------------------------------------------------------
  // 
  //---------------------------------------------------------------------------------------------------
 
  always_ff @(posedge clk or posedge reset) begin : fsm_register_process
    if (reset)      state <= STATE_RESET;
    else if (sclr)  state <= STATE_RESET; 
    else            state <= next_state; 
  end 
 
  //---------------------------------------------------------------------------------------------------
  // 
  //---------------------------------------------------------------------------------------------------
 
  assign arb_ready   = state[STATE_IDLE_BIT];
 
  assign dec_pre_all = state[STATE_PRE_ALL_BIT]; 
  assign dec_refr    = state[STATE_REFR_BIT];
  assign dec_pre     = state[STATE_PRE_BIT];
  assign dec_act     = state[STATE_ACT_BIT];
  assign dec_read    = state[STATE_RW_BIT] & ~write_mode;
  assign dec_write   = state[STATE_RW_BIT] &  write_mode;
  assign dec_last    = state[STATE_RW_BIT] & burst_done ;
 
  // 
  // instead of decode state_refr_bit & state_pre_all_bit we can use refresh mode register 
  // 
 
  assign dec_locked = refr_mode;   
 
  //-------------------------------------------------------------------------------------------------- 
  //
  //-------------------------------------------------------------------------------------------------- 
 
  assign ba_map_update   = state[STATE_DECODE_BIT] & ~refr_mode;
  assign ba_map_clear    = state[STATE_DECODE_BIT] &  refr_mode;
 
  always_ff @(posedge clk) begin : mode_logic 
    if (state [STATE_IDLE_BIT]) begin 
      refr_mode   <= arb_refr; 
      write_mode  <= arb_write;
    end 
  end 
 
  //-------------------------------------------------------------------------------------------------- 
  //
  //-------------------------------------------------------------------------------------------------- 
 
  always_ff @(posedge clk) begin : addr_chid_logic
 
    if (state[STATE_IDLE_BIT]) begin 
      rowa_latched <= arb_rowa;
      ba_latched   <= arb_ba;
      chid_latched <= arb_chid;
    end 
 
    if (state[STATE_IDLE_BIT]) 
      cola_latched <= arb_cola; 
    else if (state[STATE_ADDR_INC_BIT])
      cola_latched <= cola_latched + last_used_burst;
 
  end 
 
  assign dec_cola  = cola_latched;
  assign dec_rowa  = rowa_latched;
  assign dec_ba    = ba_latched;
  assign dec_chid  = chid_latched;
 
 
  //-------------------------------------------------------------------------------------------------- 
  // alligned burst max cycles is 4 
  // burst [3:2] == 0 & burst[1:0] <= available_burst. 1 cycle is burst 
  // burst [3:2] != 0 & burst[1:0] <= available_burst. 1 cycle is burst             shift_cnt burst_done 
  // burst [ 1.. 4] : encoded with [ 4'd0 :  4'd3] : cycle is 1 : burst_shift_cnt =  4'b0000    1
  // burst [ 5.. 8] : encoded with [ 4'd4 :  4'd7] : cycle is 2 : burst_shift_cnt =  4'b0001    0
  // burst [ 9..12] : encoded with [ 4'd8 : 4'd11] : cycle is 3 : burst_shift_cnt =  4'b0010    0
  // burst [13..16] : encoded with [4'd12 : 4'd15] : cycle is 4 : burst_shift_cnt =  4'b0100    0
  // 
 
  // not alligned burst max cycles is 5                                             shift_cnt burst_done 
  // burst [ 1.. 4] : encoded with [ 4'd0 :  4'd3] : cycle is 2 : burst_shift_cnt =  4'b0001    0
  // burst [ 5.. 8] : encoded with [ 4'd4 :  4'd7] : cycle is 3 : burst_shift_cnt =  4'b0010    0
  // burst [ 9..12] : encoded with [ 4'd8 : 4'd11] : cycle is 4 : burst_shift_cnt =  4'b0100    0
  // burst [13..16] : encoded with [4'd12 : 4'd15] : cycle is 5 : burst_shift_cnt =  4'b1000    0
  //-------------------------------------------------------------------------------------------------- 
 
  always_ff @(posedge clk) begin : burst_latch_logic 
    if (state[STATE_IDLE_BIT]) 
      burst_latched  = arb_burst;      
  end 
 
  // remember that burst has -1 offset 
  // available burst has -1 offset too
 
  assign available_burst      = 4'b0011 - {2'b00, cola_latched[1:0]}; 
 
  assign remained_burst       = burst_latched - available_burst - 1'b1; 
  assign remained_burst_high  = remained_burst[3:2];
  assign remained_burst_low   = remained_burst[1:0];
 
  assign early_burst_done     = burst_shift_cnt[0];
 
  always_ff @(posedge clk) begin : burst_logic 
    if (state[STATE_DECODE_BIT]) begin 
 
      if (burst_latched <= available_burst) begin 
 
        burst_shift_cnt <= '0;
 
        burst_done   <= 1'b1;        // only 1 transaction will be 
        dec_burst    <= burst_latched[1:0];
 
      end 
      else begin 
 
        burst_shift_cnt   <= '0;
        burst_shift_cnt[remained_burst_high] <= 1'b1;
 
        remained_burst_low_latched <= remained_burst_low;
 
        burst_done <= 1'b0; // more then 2 transaction will be  
 
        dec_burst    <= available_burst[1:0]; 
        last_used_burst <= {2'b00, available_burst[1:0]} + 1'b1; // + 1 is compensation of -1 offset 
 
      end     
    end 
    else if (state[STATE_ADDR_INC_BIT]) begin 
 
      burst_shift_cnt <= burst_shift_cnt >> 1;      
 
      burst_done <= early_burst_done;
      //
      if (early_burst_done)
        dec_burst <= remained_burst_low_latched; // no transaction any more 
      else 
        dec_burst <= 2'b11; 
      // 
      last_used_burst <= 4'b0011 + 1'b1;
    end 
  end 
 
endmodule 
 

Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.