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

📄 pci_master32_sm.v

📁 这是用pci-wishbone核和16450串口核在xilinx的fpga上实现的串口程序
💻 V
📖 第 1 页 / 共 2 页
字号:
        latency_timer <= #`FF_DELAY latency_timer - 1'b1 ;end// master abort indicators - when decode time out occurres and still no target response is receivedwire do_master_abort = decode_to && pci_trdy_in && pci_stop_in && pci_devsel_in ;reg mabort1 ;always@(posedge reset_in or posedge clk_in)begin    if (reset_in)        mabort1 <= #`FF_DELAY 1'b0 ;    else        mabort1 <= #`FF_DELAY do_master_abort ;endreg mabort2 ;always@(posedge reset_in or posedge clk_in)begin    if ( reset_in )        mabort2 <= #`FF_DELAY 1'b0 ;    else        mabort2 <= #`FF_DELAY mabort1 ;end// master abort is only asserted for one clock cycleassign mabort_out = mabort1 && ~mabort2 ;// register indicating when master should do timeout termination (latency timer expires)reg timeout ;always@(posedge reset_in or posedge clk_in)begin    if (reset_in)        timeout <= #`FF_DELAY 1'b0 ;    else        timeout <= #`FF_DELAY (latency_time_out && ~pci_frame_out_in && pci_gnt_in || timeout ) && ~wait_out ;endwire timeout_termination = sm_turn_arround && timeout && pci_stop_reg_in ;// frame control logic// frame is forced to 0 (active) when state machine is in idle state, since only possible next state is address state which always drives frame activewire force_frame = ~sm_idle ;// slow signal for frame calculated from various registers in the corewire slow_frame  = last_in || (latency_time_out && pci_gnt_in) || (next_last_in && sm_data_phases) || mabort1 ;// critical timing frame logic in separate module - some combinations of target signals force frame to inactive state immediately after sampled asserted// (STOP)pci_frame_crit frame_iob_feed(    .pci_frame_out      (pci_frame_out),    .force_frame_in     (force_frame),    .slow_frame_in      (slow_frame),    .pci_stop_in        (pci_stop_in)) ;// frame IOB flip flop's clock enable signal// slow clock enable - calculated from internal - non critical pathswire frame_load_slow = sm_idle || sm_address || mabort1 ;// critical clock enable for frame IOB in separate module - target response signals actually allow frame value change - critical timingpci_frame_load_crit frame_iob_ce(    .pci_frame_load_out (pci_frame_load_out),    .sm_data_phases_in  (sm_data_phases),    .frame_load_slow_in (frame_load_slow),    .pci_trdy_in        (pci_trdy_in),    .pci_stop_in        (pci_stop_in)) ;// IRDY driving// non critical path for IRDY calculationwire irdy_slow = pci_frame_out_in && mabort1 || mabort2 ;// critical path in separate modulepci_irdy_out_crit irdy_iob_feed(    .pci_irdy_out       (pci_irdy_out),    .irdy_slow_in       (irdy_slow),    .pci_frame_out_in   (pci_frame_out_in),    .pci_trdy_in        (pci_trdy_in),    .pci_stop_in        (pci_stop_in)) ;// transfer FF indicator - when first transfer occurs it is set to 1 so backend can distinguish between disconnects and retries.wire sm_transfer = sm_data_phases ;reg transfer ;wire transfer_input = sm_transfer && (~(pci_trdy_in || pci_devsel_in) || transfer) ;always@(posedge clk_in or posedge reset_in)begin    if (reset_in)        transfer <= #`FF_DELAY 1'b0 ;    else        transfer <= #`FF_DELAY transfer_input ;endassign first_out = ~transfer ;// fast transfer status output - it's only negated target ready, since wait indicator qualifies valid transferassign wtransfer_out = ~pci_trdy_in ;// registered transfer status output - calculated from registered target response inputsassign rtransfer_out = ~(pci_trdy_reg_in || pci_devsel_reg_in) ;// registered error status - calculated from registered target response inputsassign rerror_out    = (~pci_stop_reg_in && pci_devsel_reg_in) ;// retry is signalled to backend depending on registered target response or when latency timer expiresassign retry_out = timeout_termination || (~pci_stop_reg_in && ~pci_devsel_reg_in) ;// AD output flip flops' clock enable// new data is loaded to AD outputs whenever state machine is idle, bus was granted and bus is in idle state or// when address phase is about to be finishedwire ad_load_slow = sm_address ;wire ad_load_on_grant = sm_idle && pci_frame_in && pci_irdy_in ;pci_mas_ad_load_crit mas_ad_load_feed(    .ad_load_out         (ad_load_out),    .ad_load_in          (ad_load_slow),    .ad_load_on_grant_in (ad_load_on_grant),    .pci_gnt_in          (pci_gnt_in));// next data loading is allowed when state machine is in transfer state and operation is a writeassign ad_load_on_transfer_out = sm_data_phases && do_write ;// request for a bus is issued anytime when backend is requesting a transaction and state machine is in idle stateassign pci_req_out = ~(req_in && sm_idle) ;// change state signal is actually clock enable for state register// Non critical path for state change enable:// state is always changed when:// - address phase is finishing// - state machine is in turn arround state// - state machine is in transfer state and master abort termination is in progresswire ch_state_slow = sm_address || sm_turn_arround || sm_data_phases && ( pci_frame_out_in && mabort1 || mabort2 ) ;// a bit more critical change state enable is calculated with GNT signalwire ch_state_med  = ch_state_slow || sm_idle && u_have_pci_bus && req_in && rdy_in ;// most critical change state enable - calculated from target response signalspci_mas_ch_state_crit state_machine_ce(    .change_state_out   (change_state),    .ch_state_med_in    (ch_state_med),    .sm_data_phases_in  (sm_data_phases),    .pci_trdy_in        (pci_trdy_in),    .pci_stop_in        (pci_stop_in)) ;// ad enable driving// also divided in several categories - from less critical to most critical in separate module//wire ad_en_slowest  = do_write && (sm_address || sm_data_phases && ~pci_frame_out_in) ;//wire ad_en_on_grant = sm_idle && pci_frame_in && pci_irdy_in || sm_turn_arround ;//wire ad_en_slow     = ad_en_on_grant && ~pci_gnt_in || ad_en_slowest ;//wire ad_en_keep     = sm_data_phases && do_write && (pci_frame_out_in && ~mabort1 && ~mabort2) ;wire ad_en_slow     = do_write && ( sm_address || ( sm_data_phases && !( ( pci_frame_out_in && mabort1 ) || mabort2 ) ) ) ;wire ad_en_on_grant = ( sm_idle && pci_frame_in && pci_irdy_in ) || sm_turn_arround ;// critical timing ad enable - calculated from grant inputpci_mas_ad_en_crit ad_iob_oe_feed(    .pci_ad_en_out      (pci_ad_en_out),    .ad_en_slow_in      (ad_en_slow),    .ad_en_on_grant_in  (ad_en_on_grant),    .pci_gnt_in         (pci_gnt_in)) ;// cbe enable drivingwire cbe_en_on_grant = sm_idle && pci_frame_in && pci_irdy_in || sm_turn_arround ;wire cbe_en_slow     = cbe_en_on_grant && ~pci_gnt_in || sm_address || sm_data_phases && ~pci_frame_out_in ;wire cbe_en_keep     = sm_data_phases && pci_frame_out_in && ~mabort1 && ~mabort2 ;// most critical cbe enable in separate module - calculated with most critical target inputspci_cbe_en_crit cbe_iob_feed(    .pci_cbe_en_out     (pci_cbe_en_out),    .cbe_en_slow_in     (cbe_en_slow),    .cbe_en_keep_in     (cbe_en_keep),    .pci_stop_in        (pci_stop_in),    .pci_trdy_in        (pci_trdy_in)) ;// IRDY enable is equal to FRAME enable delayed for one clockassign pci_irdy_en_out   = pci_frame_en_in ;// frame enable driving - sometimes it's calculated from non critical pathswire frame_en_slow = (sm_idle && u_have_pci_bus && req_in && rdy_in) || sm_address || (sm_data_phases && ~pci_frame_out_in) ;wire frame_en_keep = sm_data_phases && pci_frame_out_in && ~mabort1 && ~mabort2 ;// most critical frame enable - calculated from heavily constrained target inputs in separate modulepci_frame_en_crit frame_iob_en_feed(    .pci_frame_en_out   (pci_frame_en_out),    .frame_en_slow_in   (frame_en_slow),    .frame_en_keep_in   (frame_en_keep),    .pci_stop_in        (pci_stop_in),    .pci_trdy_in        (pci_trdy_in)) ;// state machine next state definitionsalways@(    cur_state or    do_write or    pci_frame_out_in)begin    // default values for state machine outputs    wait_out                = 1'b1 ;    wdata_selector          = SEL_ADDR_BC ;    sm_idle                 = 1'b0 ;    sm_address              = 1'b0 ;    sm_data_phases          = 1'b0 ;    sm_turn_arround         = 1'b0 ;    case ( cur_state )        S_IDLE: begin                    // indicate the state                    sm_idle      = 1'b1 ;                    // assign next state - only possible is address - if state machine is supposed to stay in idle state                    // outside signals disable the clock                    next_state     = S_ADDRESS ;                    wdata_selector = SEL_DATA_BE ;                end        S_ADDRESS:  begin                        // indicate the state                        sm_address  = 1'b1 ;                        // select appropriate data/be for outputs                        wdata_selector = SEL_NEXT_DATA_BE ;                        // only possible next state is transfer state                        next_state = S_TRANSFER ;                    end        S_TRANSFER: begin                        // during transfers wait indicator is inactive - all status signals are now valid                        wait_out               = 1'b0 ;                        // indicate the state                        sm_data_phases         = 1'b1 ;                        // select appropriate data/be for outputs                        wdata_selector = SEL_NEXT_DATA_BE ;                        if ( pci_frame_out_in )                        begin                            // when frame is inactive next state will be turn arround                            next_state = S_TA_END ;                        end                        else                            // while frame is active state cannot be anything else then transfer                            next_state = S_TRANSFER ;                    end        S_TA_END:   begin                        // wait is still inactive because of registered statuses                        wait_out = 1'b0 ;                        // indicate the state                        sm_turn_arround = 1'b1 ;                        // next state is always idle                        next_state = S_IDLE ;                    end        default:    next_state = S_IDLE ;    endcaseend// ad and cbe lines multiplexer for write datareg [1:0] rdata_selector ;always@(posedge clk_in or posedge reset_in)begin    if ( reset_in )        rdata_selector <= #`FF_DELAY SEL_ADDR_BC ;    else    if ( change_state )        rdata_selector <= #`FF_DELAY wdata_selector ;endalways@(rdata_selector or address_in or bc_in or data_in or be_in or next_data_in or next_be_in)begin    case ( rdata_selector )        SEL_ADDR_BC:    begin                            pci_ad_out  = address_in ;                            pci_cbe_out = bc_in ;                        end        SEL_DATA_BE:    begin                            pci_ad_out  = data_in ;                            pci_cbe_out = be_in ;                        end        SEL_NEXT_DATA_BE,        2'b10:              begin                                pci_ad_out  = next_data_in ;                                pci_cbe_out = next_be_in ;                            end    endcaseend// data output mux for readsalways@(mabort_out or pci_ad_reg_in)begin    if ( mabort_out )        data_out = 32'hFFFF_FFFF ;    else        data_out = pci_ad_reg_in ;endendmodule

⌨️ 快捷键说明

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