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

Subversion Repositories sd_mmc_emulator

[/] [sd_mmc_emulator/] [trunk/] [rtl/] [registers.v] - Rev 2

Compare with Previous | Blame | View Log

// $Id: registers.v 912 2015-05-14 21:41:57Z nxp20190 $
//
// @brief Sango X7 Main SPI registers.
//
// @Author Roger Williams <roger.williams@nxp.com>
//
// (c) 2015 NXP Semiconductors. All rights reserved.
//
// PROPRIETARY INFORMATION
//
// The information contained in this file is the property of NXP Semiconductors.
// Except as specifically authorized in writing by NXP, the holder of this file:
// (1) shall keep all information contained herein confidential and shall protect
// same in whole or in part from disclosure and dissemination to all third parties
// and (2) shall use same for operation and maintenance purposes only.
// -----------------------------------------------------------------------------
// 0.03.1  2015-05-14 (RAW) Hard-code some parameters to get this working today
// 0.03.0  2015-05-13 (RAW) Adapted from XCtrl4 code for initial X7
//------------------------------------------------------------------------------
 
`include "registers_def.v"
`include "timescale.v"
 
module tg_registers
  (
   input 			clk_i, rst_i, we_i, oe_i, cs_i,
   input [3:0]			adr_i,
   input [15:0]			dat_i,
   output reg [15:0]		dat_o = 16'b0,
   input [`TG_REG_BITS_R]	reg_r,
   output [`TG_REG_BITS_W]	reg_w,
   output [`TG_REG_BITS_CTL]	reg_ctl
   );
 
   reg [15:0] 			dat_i_sync = 16'b0;
   reg [15:0] 			dat_i_dly = 16'b0;
   reg [3:0] 			addr_keep = 4'b0;
   reg 				wr_keep = 1'b0;
   reg 				rd_keep = 1'b0;
   reg 				wr_dly = 1'b0;
   reg 				wr_dly1 = 1'b0;
   reg 				w_strobe = 1'b0;
   reg 				w_strobe_dly = 1'b0;
   wire 			wr_strobe = wr_dly & ~wr_dly1;
 
   // RW registers, strobes
   reg [15:0] 			tctrl = 16'h0000;
   reg 				tctrl_ld = 1'b0;
/* -----\/----- EXCLUDED -----\/-----
   reg [31:0] 			tqueue = 32'h00000000;
 -----/\----- EXCLUDED -----/\----- */
   reg [15:0] 			tqueue = 16'h0000; // HACK!
   reg 				tqueue_ld = 1'b0;
/* -----\/----- EXCLUDED -----\/-----
   reg 				tqueue_ld_dly = 1'b0;
 -----/\----- EXCLUDED -----/\----- */
   reg [15:0] 			mctrl = 16'h0000;
   reg 				mctrl_ld = 1'b0;
   reg [15:0] 			mconf = 16'h0400;
   reg 				mconf_ld = 1'b0;
   reg [15:0] 			debug = 16'h0000;
   reg 				debug_ld = 1'b0;
/* -----\/----- EXCLUDED -----\/-----
   reg [15:0] 			wr_multi = 16'b00;
   reg 				wr_multi_ld = 1'b0;
   reg [15:0] 			rd_multi = 16'b0;
 -----/\----- EXCLUDED -----/\----- */
   reg 				mqueue_rd = 0;
 
   assign reg_w = {debug, mconf, mctrl, tqueue, tctrl, dat_i_dly};
/* -----\/----- EXCLUDED -----\/-----
   assign reg_ctl = {mqueue_rd, tqueue_ld | tqueue_ld_dly};
 -----/\----- EXCLUDED -----/\----- */
   assign reg_ctl = {mqueue_rd, tqueue_ld};	// HACK!
 
   // synchronise inputs
   always @ (posedge clk_i)
     if (rst_i) begin
        rd_keep <= 0;
        wr_keep <= 0;
        addr_keep <= 0;
     end
     else begin
        rd_keep <= cs_i & oe_i;
        wr_keep <= cs_i & we_i;
        if (rd_keep | wr_keep)
          addr_keep <= adr_i;
     end
 
   // write pipeline
   always @ (posedge clk_i)
     if (rst_i) begin
        wr_dly <= 0;
        wr_dly1 <= 0;
        dat_i_sync <= 0;
     end
     else begin
        wr_dly <= wr_keep;
        wr_dly1 <= wr_dly;
        dat_i_dly <= dat_i_sync;
        if (wr_keep)
          dat_i_sync <= dat_i;
     end
 
   // address decoding
   always @ (posedge clk_i) 
     if (rst_i) begin
        tctrl_ld <= 0;
        tqueue_ld <= 0;
        mctrl_ld <= 0;
        debug_ld <= 0;
        mconf_ld <= 0;
/* -----\/----- EXCLUDED -----\/-----
        wr_multi_ld <= 0;
 -----/\----- EXCLUDED -----/\----- */
        mqueue_rd <= 0;
	w_strobe <= 0;
/* -----\/----- EXCLUDED -----\/-----
        tqueue_ld_dly <= 0;
 -----/\----- EXCLUDED -----/\----- */
     end
     else begin
        tctrl_ld <= wr_strobe & (addr_keep == `TG_TCTRL_AD);
/* -----\/----- EXCLUDED -----\/-----
        tqueue_ld <= wr_strobe & (addr_keep == (`TG_TQUEUE_AD | 5'd2));
 -----/\----- EXCLUDED -----/\----- */
        tqueue_ld <= wr_strobe & (addr_keep == `TG_TQUEUE_AD); // HACK!
        mctrl_ld <= wr_strobe & (addr_keep == `TG_MCTRL_AD);
        mconf_ld <= wr_strobe & (addr_keep == `TG_MCONF_AD);
        debug_ld <= wr_strobe & (addr_keep == `TG_DEBUG_AD);
/* -----\/----- EXCLUDED -----\/-----
        wr_multi_ld <= wr_strobe & (addr_keep == `TG_TQUEUE_AD);
 -----/\----- EXCLUDED -----/\----- */
        mqueue_rd <= rd_keep & (addr_keep == `TG_MQUEUE_AD);
	w_strobe <= tctrl_ld | mctrl_ld;
/* -----\/----- EXCLUDED -----\/-----
        tqueue_ld_dly <= tqueue_ld;
 -----/\----- EXCLUDED -----/\----- */
     end
 
   // W writes need to be valid for 2 clk200 cycles
   always @ (posedge clk_i)
     if (rst_i) begin
        tctrl <= 0;
        mctrl <= 0;
	w_strobe_dly <= 0;
     end
     else begin
	w_strobe_dly <= w_strobe;
        if (w_strobe_dly) begin
           tctrl <= 0;
           mctrl <= 0;
	end
	else begin
           if (tctrl_ld)
             tctrl <= dat_i_dly;
           if (mctrl_ld)
             mctrl <= dat_i_dly;
	end
     end
 
   // RW writes
   always @ (posedge clk_i)
     if (rst_i) begin
        mconf <= 16'h0400;
        debug <= 16'h0000;
/* -----\/----- EXCLUDED -----\/-----
        wr_multi <= 0;
        tqueue <= 32'h00000000;
 -----/\----- EXCLUDED -----/\----- */
        tqueue <= 16'h0000;			// HACK!
     end
     else begin
        if (debug_ld)
          debug <= dat_i_dly;
        if (mconf_ld)
          mconf <= dat_i_dly;
/* -----\/----- EXCLUDED -----\/-----
        if (wr_multi_ld)
          wr_multi <= dat_i_dly;
 -----/\----- EXCLUDED -----/\----- */
        if (tqueue_ld) begin
/* -----\/----- EXCLUDED -----\/-----
           tqueue[31:16] <= dat_i_dly;
           tqueue[15:0] <= wr_multi;
 -----/\----- EXCLUDED -----/\----- */
           tqueue <= dat_i_dly;			// HACK!
        end
     end
 
   // reads for RW and R registers
   always @ (posedge clk_i)
     if (rst_i) begin
        dat_o <= 0;
/* -----\/----- EXCLUDED -----\/-----
        rd_multi <= 0;
 -----/\----- EXCLUDED -----/\----- */
     end
     else if (rd_keep)
       case (addr_keep)
         `TG_TQ_STAT_AD: dat_o <= reg_r[`TG_TQ_STAT_INDEX];
         `TG_MQ_STAT_AD: dat_o <= reg_r[`TG_MQ_STAT_INDEX];
         `TG_DEBUG_AD: dat_o <= debug;
         `TG_MCONF_AD: dat_o <= mconf;
         `TG_MQUEUE_AD: dat_o <= reg_r[`TG_MQUEUE_INDEX];
/* -----\/----- EXCLUDED -----\/-----
         `TG_TQUEUE_AD: {rd_multi, dat_o} <= tqueue; // verify correct order
	 `TG_TQUEUE_AD + 2: dat_o <= rd_multi;
 -----/\----- EXCLUDED -----/\----- */
         `TG_TQUEUE_AD: dat_o <= reg_r[`TG_TQUEUE_INDEX]; // HACK!
         default: dat_o <= 0;
       endcase
 
endmodule
 
module registers
  (
   input			clk_i, rst_i, we_i, oe_i, cs_i,
   input [5:0]			adr_i,
   input [15:0]			dat_i,
   output reg [15:0]		dat_o = 16'b0,
   input [`REG_BITS_R]		reg_r,
   output [`REG_BITS_W]		reg_w
   );
 
   reg [15:0] 			dat_i_sync = 16'b0;
   reg [15:0] 			dat_i_dly = 16'b0;
   reg [5:0] 			addr_keep = 6'b0;
   reg 				wr_keep = 1'b0;
   reg 				rd_keep = 1'b0;
   reg 				wr_dly = 1'b0;
   reg 				wr_dly1 = 1'b0;
   reg 				w_strobe = 1'b0;
   reg 				w_strobe_dly = 1'b0;
   wire 			wr_strobe = wr_dly & ~wr_dly1;
 
   // RW registers, strobes
   reg [15:0] 			conf = 16'b0;
   reg 				conf_ld = 1'b0;
   reg [15:0] 			trig_src = 16'b0;
   reg 				trig_src_ld = 1'b0;
   reg [15:0] 			ctrl = 16'b0;
   reg 				ctrl_ld = 1'b0;
   reg [15:0] 			irq_mask = 16'b0;
   reg 				irq_mask_ld = 1'b0;
   reg [15:0] 			irq_clr = 16'b0;
   reg 				irq_clr_ld = 1'b0;
   reg [15:0] 			sync = 16'b0;
   reg 				sync_ld = 1'b0;
   reg [15:0] 			filter = 16'd10000;
   reg 				filter_ld = 1'b0;
 
   assign reg_w = {filter, sync, irq_clr, irq_mask, ctrl, trig_src, conf, dat_i_dly};
 
   // synchronise inputs
   always @ (posedge clk_i)
     if (rst_i) begin
        rd_keep <= 0;
        wr_keep <= 0;
        addr_keep <= 0;
     end
     else begin
        rd_keep <= cs_i & oe_i;
        wr_keep <= cs_i & we_i;
        if (rd_keep | wr_keep)
          addr_keep <= adr_i;
     end
 
   // write pipeline
   always @ (posedge clk_i)
     if (rst_i) begin
        wr_dly <= 0;
        wr_dly1 <= 0;
        dat_i_sync <= 0;
     end
     else begin
        wr_dly <= wr_keep;
        wr_dly1 <= wr_dly;
        dat_i_dly <= dat_i_sync;
        if (wr_keep)
          dat_i_sync <= dat_i;
     end
 
   // address decoding
   always @ (posedge clk_i)
     if (rst_i) begin
        conf_ld <= 0;
        trig_src_ld <= 0;
        ctrl_ld <= 0;
        irq_mask_ld <= 0;
        irq_clr_ld <= 0;
        sync_ld <= 0;
        filter_ld <= 0;
	w_strobe <= 0;
     end
     else begin
        conf_ld <= wr_strobe & (addr_keep == `CONF_AD);
        trig_src_ld <= wr_strobe & (addr_keep == `TRIG_SRC_AD);
	ctrl_ld <= wr_strobe & (addr_keep == `CTRL_AD);
        irq_mask_ld <= wr_strobe & (addr_keep == `IRQ_MASK_AD);
	irq_clr_ld <= wr_strobe & (addr_keep == `IRQ_CLR_AD);
        sync_ld <= wr_strobe & (addr_keep == `SYNC_AD);
        filter_ld <= wr_strobe & (addr_keep == `FILTER_AD);
	w_strobe <= ctrl_ld | irq_clr_ld;
     end
 
   // W writes
   always @ (posedge clk_i)
     if (rst_i) begin
        ctrl <= 0;
        irq_clr <= 0;
	w_strobe_dly <= 0;
     end
     else begin
	w_strobe_dly <= w_strobe;
        if (w_strobe_dly) begin
           ctrl <= 0;
           irq_clr <= 0;
	end
	else begin
           if (ctrl_ld)
             ctrl <= dat_i_dly;
           if (irq_clr_ld)
             irq_clr <= dat_i_dly;
	end
     end
 
   // RW writes
   always @ (posedge clk_i)
     if (rst_i) begin
        conf <= 16'h0000;
        trig_src <= 16'h0000;
        irq_mask <= 16'h0000;
        sync <= 16'h0000;
        filter <= 16'd10000;
     end
     else begin
        if (conf_ld)
          conf <= dat_i_dly;
        if (trig_src_ld)
          trig_src <= dat_i_dly;
        if (irq_mask_ld)
          irq_mask <= dat_i_dly;
        if (sync_ld)
          sync <= dat_i_dly;
        if (filter_ld)
          filter <= dat_i_dly;
     end
 
   // reads for RW and R registers
   always @ (posedge clk_i)
     if (rst_i) begin
        dat_o <= 0;
     end
     else if (rd_keep)
       case (addr_keep)
         `STAT_AD: dat_o <= reg_r[`STAT_INDEX];
         `IRQ_AD: dat_o <= reg_r[`IRQ_INDEX];
         `VERSION_AD: dat_o <= reg_r[`VERSION_INDEX];
         `CONF_AD: dat_o <= conf;
         `TRIG_SRC_AD: dat_o <= trig_src;
         `IRQ_MASK_AD: dat_o <= irq_mask;
         `SYNC_AD: dat_o <= sync;
         `FILTER_AD: dat_o <= filter;
         default: dat_o <= 0;
       endcase
 
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.