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

Subversion Repositories socgen

[/] [socgen/] [trunk/] [Projects/] [opencores.org/] [adv_debug_sys/] [Hardware/] [adv_dbg_if/] [rtl/] [verilog/] [adbg_jfifo_module.v] - Rev 135

Compare with Previous | Blame | View Log

/////////////////////////////////////////////////////////////////////
////                                                              ////
////  adbg_jfifo_module.v                                         ////
////                                                              ////
////                                                              ////
////  This file is part of the SoC Advanced Debug Interface.      ////
////                                                              ////
////  Author(s):                                                  ////
////       Nathan Yawn (nathan.yawn@opencores.org)                ////
////                                                              ////
////                                                              ////
////                                                              ////
//////////////////////////////////////////////////////////////////////
////                                                              ////
//// Copyright (C) 2010       Authors                             ////
////                                                              ////
//// This source file may be used and distributed without         ////
//// restriction provided that this copyright statement is not    ////
//// removed from the file and that any derivative work contains  ////
//// the original copyright notice and the associated disclaimer. ////
////                                                              ////
//// This source file is free software; you can redistribute it   ////
//// and/or modify it under the terms of the GNU Lesser General   ////
//// Public License as published by the Free Software Foundation; ////
//// either version 2.1 of the License, or (at your option) any   ////
//// later version.                                               ////
////                                                              ////
//// This source is distributed in the hope that it will be       ////
//// useful, but WITHOUT ANY WARRANTY; without even the implied   ////
//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR      ////
//// PURPOSE.  See the GNU Lesser General Public License for more ////
//// details.                                                     ////
////                                                              ////
//// You should have received a copy of the GNU Lesser General    ////
//// Public License along with this source; if not, download it   ////
//// from http://www.opencores.org/lgpl.shtml                     ////
////                                                              ////
//////////////////////////////////////////////////////////////////////
 
 
 
 
// Module interface
module `VARIANT`JFIFO_MODULE (
			 // JTAG signals
			 tck_i,
			 module_tdo_o,
			 tdi_i,
 
			 // TAP states
			 capture_dr_i,
			 shift_dr_i,
			 update_dr_i,
 
			 data_register_i,  // the data register is at top level, shared between all modules
			 module_select_i,
			 rst_i,
 
                         jsp_data_out,
                         biu_wr_strobe,			    
 
			 // WISHBONE 
			 wb_clk_i, wb_dat_i, wb_stb_i 
 
			 );
 
   // JTAG signals
   input         tck_i;
   output        module_tdo_o;
   input         tdi_i;  // This is only used by the CRC module - data_register_i[MSB] is delayed a cycle
 
   // TAP states
   input         capture_dr_i;
   input         shift_dr_i;
   input         update_dr_i;
   input [52:0]  data_register_i;
   input         module_select_i;
   input         rst_i;
   output [7:0]  jsp_data_out;
   output        biu_wr_strobe;
 
 
   // WISHBONE slave interface
   input         wb_clk_i;
   input  [7:0]  wb_dat_i;
   input         wb_stb_i;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
   reg [7:0]   jsp_data_out;      
 
   // Declare inputs / outputs as wires / registers
   wire 	 module_tdo_o;
 
 
   // NOTE:  For the rest of this file, "input" and the "in" direction refer to bytes being transferred
   // from the PC, through the JTAG, and into the BIU FIFO.  The "output" direction refers to data being
   // transferred from the BIU FIFO, through the JTAG to the PC.
 
   // The read and write bit counts are separated to allow for JTAG chains with multiple devices.
   // The read bit count starts right away (after a single throwaway bit), but the write count
   // waits to receive a '1' start bit.
 
   // Registers to hold state etc.
   reg [3:0] 	 read_bit_count;            // How many bits have been shifted out
   reg [3:0]   write_bit_count;      // How many bits have been shifted in
   reg [3:0] 	 input_word_count;     // space (bytes) remaining in input FIFO (from JTAG)
   reg [3:0]     output_word_count;    // bytes remaining in output FIFO (to JTAG)
   reg [3:0] 	 user_word_count;     // bytes user intends to send from PC
   reg [7:0] 	 data_out_shift_reg;  // parallel-load output shift register
 
 
   // Control signals for the various counters / registers / state machines
   reg 		 rd_bit_ct_en;         // enable bit counter
   reg 		 rd_bit_ct_rst;        // reset (zero) bit count register
   reg 		 wr_bit_ct_en;         // enable bit counter
   reg 		 wr_bit_ct_rst;        // reset (zero) bit count register   
   reg 		 in_word_ct_sel;       // Selects data for byte counter.  0 = data_register_i, 1 = decremented byte count
   reg 		 out_word_ct_sel;       // Selects data for byte counter.  0 = data_register_i, 1 = decremented byte count
   reg 		 in_word_ct_en;     // Enable input byte counter register
   reg           out_word_ct_en;    // Enable output byte count register
   reg           user_word_ct_en;   // Enable user byte count registere
   reg           user_word_ct_sel;  // selects data for user byte counter.  0 = user data, 1 = decremented byte count
   reg 		 out_reg_ld_en;     // Enable parallel load of data_out_shift_reg
   reg 		 out_reg_shift_en;  // Enable shift of data_out_shift_reg
   reg 		 out_reg_data_sel;  // 0 = BIU data, 1 = byte count data (also from BIU)
   reg 		 biu_rd_strobe;      // Indicates that the bus unit should ACK the last read operation + start another
   reg 		 biu_wr_strobe;   // Indicates BIU should latch input + begin a write operation
 
 
   // Status signals
   wire 	 in_word_count_zero;   // true when input byte counter is zero
   wire 	 out_word_count_zero;   // true when output byte counter is zero
   wire          user_word_count_zero; // true when user byte counter is zero
   wire 	 rd_bit_count_max;     // true when bit counter is equal to current word size
   wire 	 wr_bit_count_max;     // true when bit counter is equal to current word size
 
   // Intermediate signals
   wire [3:0] 	 data_to_in_word_counter;  // output of the mux in front of the input byte counter reg
   wire [3:0] 	 data_to_out_word_counter;  // output of the mux in front of the output byte counter reg
   wire [3:0] 	 data_to_user_word_counter;  // output of mux in front of user word counter
   wire [3:0] 	 decremented_in_word_count;
   wire [3:0] 	 decremented_out_word_count;
   wire [3:0] 	 decremented_user_word_count;
   wire [3:0] 	 count_data_in;         // from data_register_i
   wire [7:0] 	 data_to_biu;           // from data_register_i
   wire [7:0] 	 data_from_biu;         // to data_out_shift_register
   wire [3:0] 	 biu_space_available;
   wire [3:0] 	 biu_bytes_available;
   wire [7:0] 	 out_reg_data;           // parallel input to the output shift register
   wire [7:0] 	 count_data_from_biu;
 
 
 
 
   //////////////////////////////////////
 
 
   always @ (posedge tck_i or posedge rst_i)
     begin
	if(rst_i)                   jsp_data_out <= 8'h00;
	else if(biu_wr_strobe)      jsp_data_out <= data_to_biu;
        else                        jsp_data_out <= jsp_data_out;
     end
 
 
 
   /////////////////////////////////////////////////
   // Combinatorial assignments
 
   assign count_data_from_biu = {biu_bytes_available, biu_space_available};
   assign count_data_in = {tdi_i,data_register_i[52:50]};  // Second nibble of user data
   assign data_to_biu   = {tdi_i,data_register_i[52:46]};
 
   //////////////////////////////////////
   // Input bit counter
 
   always @ (posedge tck_i or posedge rst_i)
     begin
	if(rst_i)             write_bit_count <= 4'h0;
	else if(wr_bit_ct_rst)   write_bit_count <= 4'h0;
	else if(wr_bit_ct_en)    write_bit_count <= write_bit_count + 4'h1;
     end
 
   assign wr_bit_count_max = (write_bit_count == 4'h7) ? 1'b1 : 1'b0;
 
   //////////////////////////////////////
   // Output bit counter
 
   always @ (posedge tck_i or posedge rst_i)
     begin
	if(rst_i)             read_bit_count <= 4'h0;
	else if(rd_bit_ct_rst)   read_bit_count <= 4'h0;
	else if(rd_bit_ct_en)    read_bit_count <= read_bit_count + 4'h1;
     end
 
   assign rd_bit_count_max = (read_bit_count == 4'h7) ? 1'b1 : 1'b0;
 
   ////////////////////////////////////////
   // Input word counter
 
   assign data_to_in_word_counter = (in_word_ct_sel) ?  decremented_in_word_count : biu_space_available;
   assign decremented_in_word_count = input_word_count - 4'h1;
 
   always @ (posedge tck_i or posedge rst_i)
     begin
	if(rst_i)
	  input_word_count <= 4'h0;
	else if(in_word_ct_en)
	  input_word_count <= data_to_in_word_counter;
     end
 
   assign in_word_count_zero = (input_word_count == 4'h0);
 
   ////////////////////////////////////////
   // Output word counter
 
   assign data_to_out_word_counter = (out_word_ct_sel) ?  decremented_out_word_count : biu_bytes_available;
   assign decremented_out_word_count = output_word_count - 4'h1;
 
   always @ (posedge tck_i or posedge rst_i)
     begin
	if(rst_i)
	  output_word_count <= 4'h0;
	else if(out_word_ct_en)
	  output_word_count <= data_to_out_word_counter;
     end
 
   assign out_word_count_zero = (output_word_count == 4'h0);
 
   ////////////////////////////////////////
   // User word counter
 
   assign data_to_user_word_counter = (user_word_ct_sel) ?  decremented_user_word_count : count_data_in;
   assign decremented_user_word_count = user_word_count - 4'h1;
 
   always @ (posedge tck_i or posedge rst_i)
     begin
	if(rst_i)                 user_word_count <= 4'h0;
	else if(user_word_ct_en)  user_word_count <= data_to_user_word_counter;
     end
 
   assign user_word_count_zero = (user_word_count == 4'h0);
 
   /////////////////////////////////////////////////////
   // Output register and TDO output MUX
 
 
   assign out_reg_data = (out_reg_data_sel) ? count_data_from_biu   : data_from_biu;
 
   always @ (posedge tck_i or posedge rst_i)
     begin
	if(rst_i)                 data_out_shift_reg     <= 8'h0;
	else if(out_reg_ld_en)    data_out_shift_reg     <= out_reg_data;
	else if(out_reg_shift_en) data_out_shift_reg     <= {1'b0, data_out_shift_reg[7:1]};
     end
 
   assign module_tdo_o = data_out_shift_reg[0];
 
   ////////////////////////////////////////
   // Bus Interface Unit (to JTAG  UART)
   // It is assumed that the BIU has internal registers, and will
   // latch write data (and ack read data) on rising clock edge 
   // when strobe is asserted
 
   `VARIANT`JFIFO_BIU jsp_biu_i (
			   // Debug interface signals
			   .tck_i             (tck_i),
			   .rst_i             (rst_i),
			   .data_o            (data_from_biu),
			   .bytes_available_o (biu_bytes_available),
			   .bytes_free_o      (biu_space_available),
			   .rd_strobe_i       (biu_rd_strobe),
			   .wr_strobe_i       (biu_wr_strobe),
 
			   // Wishbone slave signals
			   .wb_clk_i        (wb_clk_i),
			   .wb_dat_i        (wb_dat_i),
			   .wb_stb_i        (wb_stb_i)
 
			   );
 
 
   ////////////////////////////////////////
   // Input Control FSM
 
   // Definition of machine state values.
   // Don't worry too much about the state encoding, the synthesis tool
   // will probably re-encode it anyway.
 
`define STATE_wr_idle     3'h0
`define STATE_wr_wait     3'h1
`define STATE_wr_counts   3'h2
`define STATE_wr_xfer     3'h3
 
   reg [2:0] wr_module_state;       // FSM state
   reg [2:0] wr_module_next_state;  // combinatorial signal, not actually a register
 
 
 
 
`ifndef SYNTHESIS   
 
reg [8*16-1:0] wr_module_string;
 
always @(*) begin
   case (wr_module_state)
      `STATE_wr_idle:      wr_module_string = "wr_idle";
      `STATE_wr_wait:      wr_module_string = "wr_wait";
      `STATE_wr_counts:    wr_module_string = "wr_counts";
      `STATE_wr_xfer:      wr_module_string = "wr_xfer";
      default:             wr_module_string = "-XXXXXX-";
   endcase
 
   $display("%t  %m   JFifo wr_module State   = %s",$realtime, wr_module_string);
end
 
`endif //  `ifndef SYNTHESIS
 
 
 
 
 
 
 
 
   // sequential part of the FSM
   always @ (posedge tck_i or posedge rst_i)
     begin
	if(rst_i)
	  wr_module_state <= `STATE_wr_idle;
	else  
	  wr_module_state <= wr_module_next_state;
     end
 
 
   // Determination of next state; purely combinatorial
   always @ (wr_module_state or module_select_i or update_dr_i or capture_dr_i 
	     or shift_dr_i or wr_bit_count_max or tdi_i)
     begin
	case(wr_module_state)
	  `STATE_wr_idle:
	    begin
`ifdef ADBG_JSP_SUPPORT_MULTI
	       if(module_select_i && capture_dr_i) wr_module_next_state = `STATE_wr_wait;
`else
	       if(module_select_i && capture_dr_i) wr_module_next_state = `STATE_wr_counts;
`endif
	       else wr_module_next_state = `STATE_wr_idle;
	    end
	   `STATE_wr_wait:
	   begin 
	     	 if(update_dr_i) wr_module_next_state = `STATE_wr_idle;
	    	  else if(module_select_i && tdi_i  && shift_dr_i     ) wr_module_next_state = `STATE_wr_counts;  // got start bit
	       else wr_module_next_state = `STATE_wr_wait;
	   end
	  `STATE_wr_counts:
	    begin
	       if(update_dr_i)                                 wr_module_next_state = `STATE_wr_idle;
	       else if(wr_bit_count_max   && shift_dr_i )      wr_module_next_state = `STATE_wr_xfer;
	       else                                            wr_module_next_state = `STATE_wr_counts;
	    end
 
	  `STATE_wr_xfer:
	    begin
	       if(update_dr_i) wr_module_next_state = `STATE_wr_idle;
	       else wr_module_next_state = `STATE_wr_xfer;
	    end
 
	  default: wr_module_next_state = `STATE_wr_idle;  // shouldn't actually happen...
	endcase
     end
 
 
   // Outputs of state machine, pure combinatorial
   always @ (wr_module_state or wr_module_next_state or module_select_i or update_dr_i or capture_dr_i or shift_dr_i
	     or in_word_count_zero or out_word_count_zero or wr_bit_count_max or decremented_in_word_count
	     or decremented_out_word_count or user_word_count_zero)
     begin
	// Default everything to 0, keeps the case statement simple
	wr_bit_ct_en = 1'b0;         // enable bit counter
	wr_bit_ct_rst = 1'b0;        // reset (zero) bit count register
	in_word_ct_sel = 1'b0;       // Selects data for byte counter.  0 = data_register_i, 1 = decremented byte count
	user_word_ct_sel = 1'b0;  // selects data for user byte counter, 0 = user data, 1 = decremented count
	in_word_ct_en = 1'b0;     // Enable input byte counter register
	user_word_ct_en = 1'b0;   // enable user byte count register
	biu_wr_strobe = 1'b0;    // Indicates BIU should latch input + begin a write operation
 
	case(wr_module_state)
	  `STATE_wr_idle:
	    begin
	       in_word_ct_sel = 1'b0;
 
	       // Going to transfer; enable count registers and output register
	       if(wr_module_next_state != `STATE_wr_idle) begin
		  wr_bit_ct_rst = 1'b1;
		  in_word_ct_en = 1'b1;
	       end
	    end
 
	  // This state is only used when support for multi-device JTAG chains is enabled.
	  `STATE_wr_wait:
	    begin
	       wr_bit_ct_en = 1'b0;  // Don't do anything, just wait for the start bit.
	    end
 
	  `STATE_wr_counts:
	    begin
	       if(shift_dr_i) begin // Don't do anything in PAUSE or EXIT states...
		  wr_bit_ct_en = 1'b1;
		  user_word_ct_sel = 1'b0;
 
		  if(wr_bit_count_max) begin
		     wr_bit_ct_rst = 1'b1;
		     user_word_ct_en = 1'b1;
		  end
	       end
	    end
 
	  `STATE_wr_xfer:
	    begin
	       if(shift_dr_i) begin  // Don't do anything in PAUSE or EXIT states
		  wr_bit_ct_en = 1'b1;
		  in_word_ct_sel = 1'b1;
		  user_word_ct_sel = 1'b1;
 
		  if(wr_bit_count_max) begin  // Start biu transactions, if word counts allow
		     wr_bit_ct_rst = 1'b1;
 
		     if(!(in_word_count_zero || user_word_count_zero)) begin
			biu_wr_strobe = 1'b1;
			in_word_ct_en = 1'b1;
			user_word_ct_en = 1'b1;
		     end
 
		  end
	       end
	    end
 
	  default: ;
	endcase
     end
 
   ////////////////////////////////////////
   // Output Control FSM
 
   // Definition of machine state values.
   // Don't worry too much about the state encoding, the synthesis tool
   // will probably re-encode it anyway.
 
`define STATE_rd_idle     3'h0
`define STATE_rd_counts   3'h1
`define STATE_rd_rdack   3'h2
`define STATE_rd_xfer  3'h3
 
// We do not send the equivalent of a 'start bit' (like the one the input FSM
// waits for when support for multi-device JTAG chains is enabled).  Since the
// input and output are going to be offset anyway, why bother...
 
   reg [2:0] rd_module_state;       // FSM state
   reg [2:0] rd_module_next_state;  // combinatorial signal, not actually a register
 
 
 
 
 
 
 
 
 
`ifndef SYNTHESIS   
 
reg [8*16-1:0] rd_module_string;
 
always @(*) begin
   case (rd_module_state)
      `STATE_rd_idle:      rd_module_string = "rd_idle";
      `STATE_rd_counts:    rd_module_string = "rd_counts";
      `STATE_rd_rdack:     rd_module_string = "rd_rdack";
      `STATE_rd_xfer:      rd_module_string = "rd_xfer";
      default:             rd_module_string = "-XXXXXX-";
   endcase
 
   $display("%t  %m   JFifo rd_module State   = %s",$realtime, rd_module_string);
end
 
`endif //  `ifndef SYNTHESIS
 
 
 
 
 
 
 
 
   // sequential part of the FSM
   always @ (posedge tck_i or posedge rst_i)
     begin
	if(rst_i)
	  rd_module_state <= `STATE_rd_idle;
	else
	  rd_module_state <= rd_module_next_state;
     end
 
 
   // Determination of next state; purely combinatorial
   always @ (rd_module_state or module_select_i or update_dr_i or capture_dr_i or shift_dr_i or rd_bit_count_max)
     begin
	case(rd_module_state)
	  `STATE_rd_idle:
	    begin
	       if(module_select_i && capture_dr_i) rd_module_next_state = `STATE_rd_counts;
	       else rd_module_next_state = `STATE_rd_idle;
	    end
	  `STATE_rd_counts:
	    begin
	       if(update_dr_i) rd_module_next_state = `STATE_rd_idle;
	       else if(rd_bit_count_max  && shift_dr_i ) rd_module_next_state = `STATE_rd_rdack;
	       else rd_module_next_state = `STATE_rd_counts;
	    end
	  `STATE_rd_rdack:
	    begin
               if(update_dr_i) rd_module_next_state = `STATE_rd_idle;
	       else if(shift_dr_i ) rd_module_next_state = `STATE_rd_xfer;
               else rd_module_next_state = `STATE_rd_rdack;
	    end
	  `STATE_rd_xfer:
	    begin
	       if(update_dr_i) rd_module_next_state = `STATE_rd_idle;
	       else if(rd_bit_count_max  && shift_dr_i ) rd_module_next_state = `STATE_rd_rdack;
	       else rd_module_next_state = `STATE_rd_xfer;
	    end
 
	  default: rd_module_next_state = `STATE_rd_idle;  // shouldn't actually happen...
	endcase
     end
 
 
   // Outputs of state machine, pure combinatorial
   always @ (rd_module_state or rd_module_next_state or module_select_i or update_dr_i or capture_dr_i or shift_dr_i
	     or in_word_count_zero or out_word_count_zero or rd_bit_count_max or decremented_in_word_count
	     or decremented_out_word_count)
     begin
	// Default everything to 0, keeps the case statement simple
	rd_bit_ct_en = 1'b0;         // enable bit counter
	rd_bit_ct_rst = 1'b0;        // reset (zero) bit count register
	out_word_ct_sel = 1'b0;       // Selects data for byte counter.  0 = data_register_i, 1 = decremented byte count
	out_word_ct_en = 1'b0;    // Enable output byte count register
	out_reg_ld_en = 1'b0;     // Enable parallel load of data_out_shift_reg
	out_reg_shift_en = 1'b0;  // Enable shift of data_out_shift_reg
	out_reg_data_sel = 1'b0;  // 0 = BIU data, 1 = byte count data (also from BIU)
	biu_rd_strobe = 1'b0;     // Indicates that the bus unit should ACK the last read operation + start another
 
	case(rd_module_state)
	  `STATE_rd_idle:
	    begin
	       out_reg_data_sel = 1'b1;
	       out_word_ct_sel = 1'b0;
 
	       // Going to transfer; enable count registers and output register
	       if(rd_module_next_state != `STATE_rd_idle) begin
		  out_reg_ld_en = 1'b1;
		  rd_bit_ct_rst = 1'b1;
		  out_word_ct_en = 1'b1;
	       end
	    end
 
	  `STATE_rd_counts:
	    begin
	       if(shift_dr_i) begin // Don't do anything in PAUSE or EXIT states...
		  rd_bit_ct_en = 1'b1;
		  out_reg_shift_en = 1'b1;
 
		  if(rd_bit_count_max) begin
		     rd_bit_ct_rst = 1'b1;
 
		     // Latch the next output word, but don't ack until STATE_rd_rdack
		     if(!out_word_count_zero) begin
			out_reg_ld_en = 1'b1;
			out_reg_shift_en = 1'b0;
		     end
		  end
	       end
	    end
 
	  `STATE_rd_rdack:
	    begin
	       if(shift_dr_i) begin  // Don't do anything in PAUSE or EXIT states
		  rd_bit_ct_en = 1'b1;
		  out_reg_shift_en = 1'b1;
		  out_reg_data_sel = 1'b0;
 
		  // Never have to worry about bit_count_max here.
 
		  if(!out_word_count_zero) begin
		     biu_rd_strobe = 1'b1;
		  end
	       end
	    end
 
	  `STATE_rd_xfer:
	    begin
	       if(shift_dr_i) begin  // Don't do anything in PAUSE or EXIT states
		  rd_bit_ct_en = 1'b1;
		  out_word_ct_sel = 1'b1;
		  out_reg_shift_en = 1'b1;
		  out_reg_data_sel = 1'b0;
 
		  if(rd_bit_count_max) begin  // Start biu transaction, if word count allows
		     rd_bit_ct_rst = 1'b1;
 
		     // Don't ack the read byte here, we do it in STATE_rdack
		     if(!out_word_count_zero) begin
			out_reg_ld_en = 1'b1;
			out_reg_shift_en = 1'b0;
			out_word_ct_en = 1'b1;
		     end
		  end
	       end
	    end
 
	  default: ;
	endcase
     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.