diff options
| author | Ben Hilburn <ben.hilburn@ettus.com> | 2013-10-10 10:17:27 -0700 | 
|---|---|---|
| committer | Ben Hilburn <ben.hilburn@ettus.com> | 2013-10-10 10:17:27 -0700 | 
| commit | 0df4b801a34697f2058b4a7b95e08d2a0576c9db (patch) | |
| tree | be10e78d1a97c037a9e7492360a178d1873b9c09 /fpga/usrp3/lib/wishbone | |
| parent | 6e7bc850b66e8188718248b76b729c7cf9c89700 (diff) | |
| download | uhd-0df4b801a34697f2058b4a7b95e08d2a0576c9db.tar.gz uhd-0df4b801a34697f2058b4a7b95e08d2a0576c9db.tar.bz2 uhd-0df4b801a34697f2058b4a7b95e08d2a0576c9db.zip  | |
Squashed B200 FPGA Source. Code from Josh Blum, Ian Buckley, and Matt Ettus.
Diffstat (limited to 'fpga/usrp3/lib/wishbone')
| -rw-r--r-- | fpga/usrp3/lib/wishbone/Makefile.srcs | 19 | ||||
| -rw-r--r-- | fpga/usrp3/lib/wishbone/axi_stream_to_wb.v | 246 | ||||
| -rw-r--r-- | fpga/usrp3/lib/wishbone/i2c_master_bit_ctrl.v | 538 | ||||
| -rw-r--r-- | fpga/usrp3/lib/wishbone/i2c_master_byte_ctrl.v | 344 | ||||
| -rw-r--r-- | fpga/usrp3/lib/wishbone/i2c_master_defines.v | 64 | ||||
| -rw-r--r-- | fpga/usrp3/lib/wishbone/i2c_master_top.v | 301 | ||||
| -rw-r--r-- | fpga/usrp3/lib/wishbone/settings_bus.v | 46 | ||||
| -rw-r--r-- | fpga/usrp3/lib/wishbone/settings_readback.v | 40 | ||||
| -rw-r--r-- | fpga/usrp3/lib/wishbone/simple_uart.v | 65 | ||||
| -rw-r--r-- | fpga/usrp3/lib/wishbone/simple_uart_rx.v | 71 | ||||
| -rw-r--r-- | fpga/usrp3/lib/wishbone/simple_uart_tb.v | 127 | ||||
| -rw-r--r-- | fpga/usrp3/lib/wishbone/simple_uart_tx.v | 69 | ||||
| -rw-r--r-- | fpga/usrp3/lib/wishbone/wb_1master.v | 464 | 
13 files changed, 2394 insertions, 0 deletions
diff --git a/fpga/usrp3/lib/wishbone/Makefile.srcs b/fpga/usrp3/lib/wishbone/Makefile.srcs new file mode 100644 index 000000000..6459de834 --- /dev/null +++ b/fpga/usrp3/lib/wishbone/Makefile.srcs @@ -0,0 +1,19 @@ +# +# Copyright 2010-2012 Ettus Research LLC +# + +################################################## +# Wishbone Perifs +################################################## +WISHBONE_SRCS = $(abspath $(addprefix $(BASE_DIR)/../lib/wishbone/, \ +simple_uart_rx.v \ +simple_uart_tx.v \ +simple_uart.v \ +wb_1master.v \ +settings_bus.v \ +settings_readback.v \ +i2c_master_top.v \ +i2c_master_bit_ctrl.v \ +i2c_master_byte_ctrl.v \ +axi_stream_to_wb.v \ +)) diff --git a/fpga/usrp3/lib/wishbone/axi_stream_to_wb.v b/fpga/usrp3/lib/wishbone/axi_stream_to_wb.v new file mode 100644 index 000000000..a71daf063 --- /dev/null +++ b/fpga/usrp3/lib/wishbone/axi_stream_to_wb.v @@ -0,0 +1,246 @@ +// +// Copyright 2012 Ettus Research LLC +// + + +// AXI stream to/from wishbone +// Input is an axi stream which wites into a BRAM. +// Output is an axi stream which reads from a BRAM. +// This RAM can also be accessed from a wishbone interface. + +// From the wishbone interface we need to be able to: + +// Ask the module if a completed packet is available. +// Read number of bytes/lines in the BRAM. +// Release the completed packet. + +// Ask the module if an outgoing slot is available. +// Write number of bytes/lines in the BRAM. +// Release the completed packet. + +module axi_stream_to_wb +#( +    parameter AWIDTH = 13, //WB addr width and buffering size in bytes +    parameter UWIDTH = 4, //stream user width +    parameter CTRL_ADDR = 0 //ctrl/status register +) +( +    //-- the wishbone interface +    input clk_i, input rst_i, +    input we_i, input stb_i, input cyc_i, output reg ack_o, +    input [AWIDTH-1:0] adr_i, input [31:0] dat_i, output [31:0] dat_o, + +    //-- the axi stream interface input +    input [63:0] rx_tdata, +    input [3:0] rx_tuser, +    input rx_tlast, +    input rx_tvalid, +    output rx_tready, + +    //-- the axi stream interface output +    output [63:0] tx_tdata, +    output [3:0] tx_tuser, +    output tx_tlast, +    output tx_tvalid, +    input tx_tready, + +    output [31:0] debug_rx, +    output [31:0] debug_tx +); + +    //drive the ack signal +    always @(posedge clk_i) begin +        if (rst_i) ack_o <= 0; +        else ack_o <= stb_i & ~ack_o; +    end + +    //control registers, status +    reg [AWIDTH-1:0] tx_bytes, rx_bytes; +    reg tx_error, rx_error; +    wire rx_state_flag, tx_state_flag; +    reg rx_proc_flag, tx_proc_flag; + +    //assign status +    wire [31:0] status; +    assign status[31] = rx_state_flag; +    assign status[30] = tx_state_flag; +    assign status[29] = rx_error; +    assign status[AWIDTH-1:0] = rx_bytes; + +   // Create some piplining to break timing paths. +   reg 		ctrl_addressed; +   always @(posedge clk_i) +     if (rst_i) +       ctrl_addressed <= 1'b0; +     else if(adr_i == CTRL_ADDR) +       ctrl_addressed <= 1'b1; +     else +       ctrl_addressed <= 1'b0; +        +    //assign control +    always @(posedge clk_i) begin +        if (rst_i) begin +            rx_proc_flag <= 0; +            tx_proc_flag <= 0; +            tx_error <= 0; +            tx_bytes <= 0; +        end +        else if (we_i && ack_o && ctrl_addressed) begin +            rx_proc_flag <= dat_i[31]; +            tx_proc_flag <= dat_i[30]; +            tx_error <= dat_i[29]; +            tx_bytes <= dat_i[AWIDTH-1:0]; +        end +    end + +    //------------------------------------------------------------------ +    //-- block ram interface between wb and input stream +    //------------------------------------------------------------------ +    reg [AWIDTH-4:0] rx_counter; +    wire [63:0] rx_bram_data64; +    ram_2port #(.DWIDTH(64), .AWIDTH(AWIDTH-3)) input_stream_bram +    ( +        .clka(clk_i), .ena(rx_tready), .wea(rx_tvalid), +        .addra(rx_counter), .dia(rx_tdata), .doa(), +        .clkb(clk_i), .enb(stb_i), .web(1'b0), +        .addrb(adr_i[AWIDTH-1:3]), .dib({64{1'b1}}), .dob(rx_bram_data64) +    ); + +    //select the data source, status, or upper/lower 32 from bram +    assign dat_o = ctrl_addressed ? status : ((!adr_i[2])? rx_bram_data64[63:32]: rx_bram_data64[31:0]); + +    //------------------------------------------------------------------ +    //-- block ram interface between wb and output stream +    //------------------------------------------------------------------ +    reg [AWIDTH-4:0] tx_counter; +    wire enb_out; +    wire [63:0] tx_bram_data64; +    ram_2port #(.DWIDTH(64), .AWIDTH(AWIDTH-3)) output_stream_bram +    ( +        .clka(clk_i), .ena(enb_out), .wea(1'b0), +        .addra(tx_counter), .dia({64{1'b1}}), .doa(tx_tdata), +        .clkb(clk_i), .enb(stb_i), .web(we_i && adr_i[2]), +        .addrb(adr_i[AWIDTH-1:3]), .dib(tx_bram_data64), .dob() +    ); + +    //write 64 bit chunks, so register the lower write +    reg [31:0] dat_i_reg; +    always @(posedge clk_i) begin +        if (we_i && stb_i && !adr_i[2]) dat_i_reg <= dat_i; +    end +    assign tx_bram_data64 = {dat_i_reg, dat_i}; + +    //------------------------------------------------------------------ +    //-- state machine to drive input stream +    //------------------------------------------------------------------ +    localparam RX_STATE_READY = 0; //waits for proc flag 0 +    localparam RX_STATE_WRITE = 1; //writes stream to bram +    localparam RX_STATE_RELEASE = 2; //waits for proc to flag 1 +    reg [1:0] rx_state; + +    always @(posedge clk_i) begin +        if (rst_i) begin +            rx_state <= RX_STATE_READY; +            rx_counter <= 0; +            rx_error <= 0; +            rx_bytes <= 0; +        end +        else case (rx_state) + +        RX_STATE_READY: begin +            if (!rx_proc_flag) rx_state <= RX_STATE_WRITE; +            rx_counter <= 0; +        end + +        RX_STATE_WRITE: begin +            if (rx_tready && rx_tvalid) begin +                rx_counter <= rx_counter + 1'b1; +                if (rx_tlast) begin +                    rx_state <= RX_STATE_RELEASE; +                    rx_bytes <= {rx_counter + 1'b1, rx_tuser[2:0]}; +                    rx_error <= rx_tuser[3]; +                end +            end +        end + +        RX_STATE_RELEASE: begin +            if (rx_proc_flag) rx_state <= RX_STATE_READY; +            rx_counter <= 0; +        end + +        default: rx_state <= RX_STATE_READY; +        endcase //rx_state +    end + +    //flag tells the processor when it can grab some input buffer +    assign rx_state_flag = (rx_state == RX_STATE_RELEASE); + +    //always ready to accept input data in the write state +    assign rx_tready = (rx_state == RX_STATE_WRITE); + +    //------------------------------------------------------------------ +    //-- state machine to drive output stream +    //------------------------------------------------------------------ +    localparam TX_STATE_READY = 0;  //waits for proc flag 0 +    localparam TX_STATE_WRITE = 1; //writes bram to stream +    localparam TX_STATE_RELEASE = 2; //waits for proc to flag 1 +    reg [1:0] tx_state; + +    always @(posedge clk_i) begin +        if (rst_i) begin +            tx_state <= TX_STATE_READY; +            tx_counter <= 0; +        end +        else case (tx_state) + +        TX_STATE_READY: begin +            if (tx_proc_flag) begin +                tx_state <= TX_STATE_WRITE; +                tx_counter <= 1; +            end +            else tx_counter <= 0; +        end + +        TX_STATE_WRITE: begin +            if (tx_tready && tx_tvalid) begin +                tx_counter <= tx_counter + 1'b1; +                if (tx_tlast) begin +                    tx_state <= TX_STATE_RELEASE; +                end +            end +        end + +        TX_STATE_RELEASE: begin +            if (!tx_proc_flag) tx_state <= TX_STATE_READY; +            tx_counter <= 0; +        end + +        default: tx_state <= TX_STATE_READY; +        endcase //tx_state +    end + +    //flag tells the processor when it can grab available out buffer +    assign tx_state_flag = (tx_state == TX_STATE_READY); + +    //the output user bus assignment (non-zero only at end) +    assign tx_tuser = (tx_tlast)? {tx_error, tx_bytes[2:0]} : 4'b0; + +    //end of frame signal +    assign tx_tlast = (tx_counter == tx_bytes[AWIDTH-1:3]); + +    //output is always valid in state write +    assign tx_tvalid = (tx_state == TX_STATE_WRITE); + +    //enable the read so we can pre-read due to read 1 cycle delay +    assign enb_out = (tx_state == TX_STATE_WRITE)? (tx_tvalid && tx_tready) : 1'b1; + +    assign debug_rx = { +        rx_state, rx_tlast, rx_tvalid, rx_tready, rx_tuser[2:0], //8 +        rx_proc_flag, rx_state_flag, rx_tdata[21:0] //24 +    }; +    assign debug_tx = { +        tx_state, tx_tlast, tx_tvalid, tx_tready, tx_tuser[2:0], //8 +        tx_proc_flag, tx_state_flag, tx_tdata[21:0] //24 +    }; + +endmodule //axi_stream_to_wb diff --git a/fpga/usrp3/lib/wishbone/i2c_master_bit_ctrl.v b/fpga/usrp3/lib/wishbone/i2c_master_bit_ctrl.v new file mode 100644 index 000000000..68ec27004 --- /dev/null +++ b/fpga/usrp3/lib/wishbone/i2c_master_bit_ctrl.v @@ -0,0 +1,538 @@ +///////////////////////////////////////////////////////////////////// +////                                                             //// +////  WISHBONE rev.B2 compliant I2C Master bit-controller        //// +////                                                             //// +////                                                             //// +////  Author: Richard Herveille                                  //// +////          richard@asics.ws                                   //// +////          www.asics.ws                                       //// +////                                                             //// +////  Downloaded from: http://www.opencores.org/projects/i2c/    //// +////                                                             //// +///////////////////////////////////////////////////////////////////// +////                                                             //// +//// Copyright (C) 2001 Richard Herveille                        //// +////                    richard@asics.ws                         //// +////                                                             //// +//// 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 SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY     //// +//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED   //// +//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS   //// +//// FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR      //// +//// OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,         //// +//// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES    //// +//// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE   //// +//// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR        //// +//// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF  //// +//// LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT  //// +//// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT  //// +//// OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE         //// +//// POSSIBILITY OF SUCH DAMAGE.                                 //// +////                                                             //// +///////////////////////////////////////////////////////////////////// + +//  CVS Log +// +//  $Id: i2c_master_bit_ctrl.v,v 1.12 2006/09/04 09:08:13 rherveille Exp $ +// +//  $Date: 2006/09/04 09:08:13 $ +//  $Revision: 1.12 $ +//  $Author: rherveille $ +//  $Locker:  $ +//  $State: Exp $ +// +// Change History: +//               $Log: i2c_master_bit_ctrl.v,v $ +//               Revision 1.12  2006/09/04 09:08:13  rherveille +//               fixed short scl high pulse after clock stretch +//               fixed slave model not returning correct '(n)ack' signal +// +//               Revision 1.11  2004/05/07 11:02:26  rherveille +//               Fixed a bug where the core would signal an arbitration lost (AL bit set), when another master controls the bus and the other master generates a STOP bit. +// +//               Revision 1.10  2003/08/09 07:01:33  rherveille +//               Fixed a bug in the Arbitration Lost generation caused by delay on the (external) sda line. +//               Fixed a potential bug in the byte controller's host-acknowledge generation. +// +//               Revision 1.9  2003/03/10 14:26:37  rherveille +//               Fixed cmd_ack generation item (no bug). +// +//               Revision 1.8  2003/02/05 00:06:10  rherveille +//               Fixed a bug where the core would trigger an erroneous 'arbitration lost' interrupt after being reset, when the reset pulse width < 3 clk cycles. +// +//               Revision 1.7  2002/12/26 16:05:12  rherveille +//               Small code simplifications +// +//               Revision 1.6  2002/12/26 15:02:32  rherveille +//               Core is now a Multimaster I2C controller +// +//               Revision 1.5  2002/11/30 22:24:40  rherveille +//               Cleaned up code +// +//               Revision 1.4  2002/10/30 18:10:07  rherveille +//               Fixed some reported minor start/stop generation timing issuess. +// +//               Revision 1.3  2002/06/15 07:37:03  rherveille +//               Fixed a small timing bug in the bit controller.\nAdded verilog simulation environment. +// +//               Revision 1.2  2001/11/05 11:59:25  rherveille +//               Fixed wb_ack_o generation bug. +//               Fixed bug in the byte_controller statemachine. +//               Added headers. +// + +// +///////////////////////////////////// +// Bit controller section +///////////////////////////////////// +// +// Translate simple commands into SCL/SDA transitions +// Each command has 5 states, A/B/C/D/idle +// +// start:	SCL	~~~~~~~~~~\____ +//	SDA	~~~~~~~~\______ +//		 x | A | B | C | D | i +// +// repstart	SCL	____/~~~~\___ +//	SDA	__/~~~\______ +//		 x | A | B | C | D | i +// +// stop	SCL	____/~~~~~~~~ +//	SDA	==\____/~~~~~ +//		 x | A | B | C | D | i +// +//- write	SCL	____/~~~~\____ +//	SDA	==X=========X= +//		 x | A | B | C | D | i +// +//- read	SCL	____/~~~~\____ +//	SDA	XXXX=====XXXX +//		 x | A | B | C | D | i +// + +// Timing:     Normal mode      Fast mode +/////////////////////////////////////////////////////////////////////// +// Fscl        100KHz           400KHz +// Th_scl      4.0us            0.6us   High period of SCL +// Tl_scl      4.7us            1.3us   Low period of SCL +// Tsu:sta     4.7us            0.6us   setup time for a repeated start condition +// Tsu:sto     4.0us            0.6us   setup time for a stop conditon +// Tbuf        4.7us            1.3us   Bus free time between a stop and start condition +// + +// synopsys translate_off +//`include "timescale.v" +// synopsys translate_on + +`include "i2c_master_defines.v" + +module i2c_master_bit_ctrl( +	clk, rst, nReset,  +	clk_cnt, ena, cmd, cmd_ack, busy, al, din, dout, +	scl_i, scl_o, scl_oen, sda_i, sda_o, sda_oen +	); + +	// +	// inputs & outputs +	// +	input clk; +	input rst; +	input nReset; +	input ena;            // core enable signal + +	input [15:0] clk_cnt; // clock prescale value + +	input  [3:0] cmd; +	output       cmd_ack; // command complete acknowledge +	reg cmd_ack; +	output       busy;    // i2c bus busy +	reg busy; +	output       al;      // i2c bus arbitration lost +	reg al; + +	input  din; +	output dout; +	reg dout; + +	// I2C lines +	input  scl_i;         // i2c clock line input +	output scl_o;         // i2c clock line output +	output scl_oen;       // i2c clock line output enable (active low) +	reg scl_oen; +	input  sda_i;         // i2c data line input +	output sda_o;         // i2c data line output +	output sda_oen;       // i2c data line output enable (active low) +	reg sda_oen; + + +	// +	// variable declarations +	// + +	reg sSCL, sSDA;             // synchronized SCL and SDA inputs +	reg dscl_oen;               // delayed scl_oen +	reg sda_chk;                // check SDA output (Multi-master arbitration) +	reg clk_en;                 // clock generation signals +	wire slave_wait; +//	reg [15:0] cnt = clk_cnt;   // clock divider counter (simulation) +	reg [15:0] cnt;             // clock divider counter (synthesis) + +	// state machine variable +	reg [16:0] c_state; // synopsys enum_state + +	// +	// module body +	// + +	// whenever the slave is not ready it can delay the cycle by pulling SCL low +	// delay scl_oen +	always @(posedge clk) +	  dscl_oen <= #1 scl_oen; + +	assign slave_wait = dscl_oen && !sSCL; + + +	// generate clk enable signal +	always @(posedge clk or negedge nReset) +	  if(~nReset) +	    begin +	        cnt    <= #1 16'h0; +	        clk_en <= #1 1'b1; +	    end +	  else if (rst) +	    begin +	        cnt    <= #1 16'h0; +	        clk_en <= #1 1'b1; +	    end +	  else if ( ~|cnt || !ena) +	    begin +	        cnt    <= #1 clk_cnt; +	        clk_en <= #1 1'b1; +	    end +	  else if (slave_wait) +	    begin +	        cnt    <= #1 cnt; +	        clk_en <= #1 1'b0;     +	    end +	  else +	    begin +	        cnt    <= #1 cnt - 16'h1; +	        clk_en <= #1 1'b0; +	    end + + +	// generate bus status controller +	reg dSCL, dSDA; +	reg sta_condition; +	reg sto_condition; + +	// synchronize SCL and SDA inputs +	// reduce metastability risc +	always @(posedge clk or negedge nReset) +	  if (~nReset) +	    begin +	        sSCL <= #1 1'b1; +	        sSDA <= #1 1'b1; + +	        dSCL <= #1 1'b1; +	        dSDA <= #1 1'b1; +	    end +	  else if (rst) +	    begin +	        sSCL <= #1 1'b1; +	        sSDA <= #1 1'b1; + +	        dSCL <= #1 1'b1; +	        dSDA <= #1 1'b1; +	    end +	  else +	    begin +	        sSCL <= #1 scl_i; +	        sSDA <= #1 sda_i; + +	        dSCL <= #1 sSCL; +	        dSDA <= #1 sSDA; +	    end + +	// detect start condition => detect falling edge on SDA while SCL is high +	// detect stop condition => detect rising edge on SDA while SCL is high +	always @(posedge clk or negedge nReset) +	  if (~nReset) +	    begin +	        sta_condition <= #1 1'b0; +	        sto_condition <= #1 1'b0; +	    end +	  else if (rst) +	    begin +	        sta_condition <= #1 1'b0; +	        sto_condition <= #1 1'b0; +	    end +	  else +	    begin +	        sta_condition <= #1 ~sSDA &  dSDA & sSCL; +	        sto_condition <= #1  sSDA & ~dSDA & sSCL; +	    end + +	// generate i2c bus busy signal +	always @(posedge clk or negedge nReset) +	  if(!nReset) +	    busy <= #1 1'b0; +	  else if (rst) +	    busy <= #1 1'b0; +	  else +	    busy <= #1 (sta_condition | busy) & ~sto_condition; + +	// generate arbitration lost signal +	// aribitration lost when: +	// 1) master drives SDA high, but the i2c bus is low +	// 2) stop detected while not requested +	reg cmd_stop; +	always @(posedge clk or negedge nReset) +	  if (~nReset) +	    cmd_stop <= #1 1'b0; +	  else if (rst) +	    cmd_stop <= #1 1'b0; +	  else if (clk_en) +	    cmd_stop <= #1 cmd == `I2C_CMD_STOP; + +	always @(posedge clk or negedge nReset) +	  if (~nReset) +	    al <= #1 1'b0; +	  else if (rst) +	    al <= #1 1'b0; +	  else +	    al <= #1 (sda_chk & ~sSDA & sda_oen) | (|c_state & sto_condition & ~cmd_stop); + + +	// generate dout signal (store SDA on rising edge of SCL) +	always @(posedge clk) +	  if(sSCL & ~dSCL) +	    dout <= #1 sSDA; + +	// generate statemachine + +	// nxt_state decoder +	parameter [16:0] idle    = 17'b0_0000_0000_0000_0000; +	parameter [16:0] start_a = 17'b0_0000_0000_0000_0001; +	parameter [16:0] start_b = 17'b0_0000_0000_0000_0010; +	parameter [16:0] start_c = 17'b0_0000_0000_0000_0100; +	parameter [16:0] start_d = 17'b0_0000_0000_0000_1000; +	parameter [16:0] start_e = 17'b0_0000_0000_0001_0000; +	parameter [16:0] stop_a  = 17'b0_0000_0000_0010_0000; +	parameter [16:0] stop_b  = 17'b0_0000_0000_0100_0000; +	parameter [16:0] stop_c  = 17'b0_0000_0000_1000_0000; +	parameter [16:0] stop_d  = 17'b0_0000_0001_0000_0000; +	parameter [16:0] rd_a    = 17'b0_0000_0010_0000_0000; +	parameter [16:0] rd_b    = 17'b0_0000_0100_0000_0000; +	parameter [16:0] rd_c    = 17'b0_0000_1000_0000_0000; +	parameter [16:0] rd_d    = 17'b0_0001_0000_0000_0000; +	parameter [16:0] wr_a    = 17'b0_0010_0000_0000_0000; +	parameter [16:0] wr_b    = 17'b0_0100_0000_0000_0000; +	parameter [16:0] wr_c    = 17'b0_1000_0000_0000_0000; +	parameter [16:0] wr_d    = 17'b1_0000_0000_0000_0000; + +	always @(posedge clk or negedge nReset) +	  if (!nReset) +	    begin +	        c_state <= #1 idle; +	        cmd_ack <= #1 1'b0; +	        scl_oen <= #1 1'b1; +	        sda_oen <= #1 1'b1; +	        sda_chk <= #1 1'b0; +	    end +	  else if (rst | al) +	    begin +	        c_state <= #1 idle; +	        cmd_ack <= #1 1'b0; +	        scl_oen <= #1 1'b1; +	        sda_oen <= #1 1'b1; +	        sda_chk <= #1 1'b0; +	    end +	  else +	    begin +	        cmd_ack   <= #1 1'b0; // default no command acknowledge + assert cmd_ack only 1clk cycle + +	        if (clk_en) +	          case (c_state) // synopsys full_case parallel_case +	            // idle state +	            idle: +	            begin +	                case (cmd) // synopsys full_case parallel_case +	                  `I2C_CMD_START: +	                     c_state <= #1 start_a; + +	                  `I2C_CMD_STOP: +	                     c_state <= #1 stop_a; + +	                  `I2C_CMD_WRITE: +	                     c_state <= #1 wr_a; + +	                  `I2C_CMD_READ: +	                     c_state <= #1 rd_a; + +	                  default: +	                    c_state <= #1 idle; +	                endcase + +	                scl_oen <= #1 scl_oen; // keep SCL in same state +	                sda_oen <= #1 sda_oen; // keep SDA in same state +	                sda_chk <= #1 1'b0;    // don't check SDA output +	            end + +	            // start +	            start_a: +	            begin +	                c_state <= #1 start_b; +	                scl_oen <= #1 scl_oen; // keep SCL in same state +	                sda_oen <= #1 1'b1;    // set SDA high +	                sda_chk <= #1 1'b0;    // don't check SDA output +	            end + +	            start_b: +	            begin +	                c_state <= #1 start_c; +	                scl_oen <= #1 1'b1; // set SCL high +	                sda_oen <= #1 1'b1; // keep SDA high +	                sda_chk <= #1 1'b0; // don't check SDA output +	            end + +	            start_c: +	            begin +	                c_state <= #1 start_d; +	                scl_oen <= #1 1'b1; // keep SCL high +	                sda_oen <= #1 1'b0; // set SDA low +	                sda_chk <= #1 1'b0; // don't check SDA output +	            end + +	            start_d: +	            begin +	                c_state <= #1 start_e; +	                scl_oen <= #1 1'b1; // keep SCL high +	                sda_oen <= #1 1'b0; // keep SDA low +	                sda_chk <= #1 1'b0; // don't check SDA output +	            end + +	            start_e: +	            begin +	                c_state <= #1 idle; +	                cmd_ack <= #1 1'b1; +	                scl_oen <= #1 1'b0; // set SCL low +	                sda_oen <= #1 1'b0; // keep SDA low +	                sda_chk <= #1 1'b0; // don't check SDA output +	            end + +	            // stop +	            stop_a: +	            begin +	                c_state <= #1 stop_b; +	                scl_oen <= #1 1'b0; // keep SCL low +	                sda_oen <= #1 1'b0; // set SDA low +	                sda_chk <= #1 1'b0; // don't check SDA output +	            end + +	            stop_b: +	            begin +	                c_state <= #1 stop_c; +	                scl_oen <= #1 1'b1; // set SCL high +	                sda_oen <= #1 1'b0; // keep SDA low +	                sda_chk <= #1 1'b0; // don't check SDA output +	            end + +	            stop_c: +	            begin +	                c_state <= #1 stop_d; +	                scl_oen <= #1 1'b1; // keep SCL high +	                sda_oen <= #1 1'b0; // keep SDA low +	                sda_chk <= #1 1'b0; // don't check SDA output +	            end + +	            stop_d: +	            begin +	                c_state <= #1 idle; +	                cmd_ack <= #1 1'b1; +	                scl_oen <= #1 1'b1; // keep SCL high +	                sda_oen <= #1 1'b1; // set SDA high +	                sda_chk <= #1 1'b0; // don't check SDA output +	            end + +	            // read +	            rd_a: +	            begin +	                c_state <= #1 rd_b; +	                scl_oen <= #1 1'b0; // keep SCL low +	                sda_oen <= #1 1'b1; // tri-state SDA +	                sda_chk <= #1 1'b0; // don't check SDA output +	            end + +	            rd_b: +	            begin +	                c_state <= #1 rd_c; +	                scl_oen <= #1 1'b1; // set SCL high +	                sda_oen <= #1 1'b1; // keep SDA tri-stated +	                sda_chk <= #1 1'b0; // don't check SDA output +	            end + +	            rd_c: +	            begin +	                c_state <= #1 rd_d; +	                scl_oen <= #1 1'b1; // keep SCL high +	                sda_oen <= #1 1'b1; // keep SDA tri-stated +	                sda_chk <= #1 1'b0; // don't check SDA output +	            end + +	            rd_d: +	            begin +	                c_state <= #1 idle; +	                cmd_ack <= #1 1'b1; +	                scl_oen <= #1 1'b0; // set SCL low +	                sda_oen <= #1 1'b1; // keep SDA tri-stated +	                sda_chk <= #1 1'b0; // don't check SDA output +	            end + +	            // write +	            wr_a: +	            begin +	                c_state <= #1 wr_b; +	                scl_oen <= #1 1'b0; // keep SCL low +	                sda_oen <= #1 din;  // set SDA +	                sda_chk <= #1 1'b0; // don't check SDA output (SCL low) +	            end + +	            wr_b: +	            begin +	                c_state <= #1 wr_c; +	                scl_oen <= #1 1'b1; // set SCL high +	                sda_oen <= #1 din;  // keep SDA +	                sda_chk <= #1 1'b1; // check SDA output +	            end + +	            wr_c: +	            begin +	                c_state <= #1 wr_d; +	                scl_oen <= #1 1'b1; // keep SCL high +	                sda_oen <= #1 din; +	                sda_chk <= #1 1'b1; // check SDA output +	            end + +	            wr_d: +	            begin +	                c_state <= #1 idle; +	                cmd_ack <= #1 1'b1; +	                scl_oen <= #1 1'b0; // set SCL low +	                sda_oen <= #1 din; +	                sda_chk <= #1 1'b0; // don't check SDA output (SCL low) +	            end + +	          endcase +	    end + + +	// assign scl and sda output (always gnd) +	assign scl_o = 1'b0; +	assign sda_o = 1'b0; + +endmodule diff --git a/fpga/usrp3/lib/wishbone/i2c_master_byte_ctrl.v b/fpga/usrp3/lib/wishbone/i2c_master_byte_ctrl.v new file mode 100644 index 000000000..784b58188 --- /dev/null +++ b/fpga/usrp3/lib/wishbone/i2c_master_byte_ctrl.v @@ -0,0 +1,344 @@ +///////////////////////////////////////////////////////////////////// +////                                                             //// +////  WISHBONE rev.B2 compliant I2C Master byte-controller       //// +////                                                             //// +////                                                             //// +////  Author: Richard Herveille                                  //// +////          richard@asics.ws                                   //// +////          www.asics.ws                                       //// +////                                                             //// +////  Downloaded from: http://www.opencores.org/projects/i2c/    //// +////                                                             //// +///////////////////////////////////////////////////////////////////// +////                                                             //// +//// Copyright (C) 2001 Richard Herveille                        //// +////                    richard@asics.ws                         //// +////                                                             //// +//// 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 SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY     //// +//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED   //// +//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS   //// +//// FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR      //// +//// OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,         //// +//// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES    //// +//// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE   //// +//// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR        //// +//// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF  //// +//// LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT  //// +//// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT  //// +//// OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE         //// +//// POSSIBILITY OF SUCH DAMAGE.                                 //// +////                                                             //// +///////////////////////////////////////////////////////////////////// + +//  CVS Log +// +//  $Id: i2c_master_byte_ctrl.v,v 1.7 2004/02/18 11:40:46 rherveille Exp $ +// +//  $Date: 2004/02/18 11:40:46 $ +//  $Revision: 1.7 $ +//  $Author: rherveille $ +//  $Locker:  $ +//  $State: Exp $ +// +// Change History: +//               $Log: i2c_master_byte_ctrl.v,v $ +//               Revision 1.7  2004/02/18 11:40:46  rherveille +//               Fixed a potential bug in the statemachine. During a 'stop' 2 cmd_ack signals were generated. Possibly canceling a new start command. +// +//               Revision 1.6  2003/08/09 07:01:33  rherveille +//               Fixed a bug in the Arbitration Lost generation caused by delay on the (external) sda line. +//               Fixed a potential bug in the byte controller's host-acknowledge generation. +// +//               Revision 1.5  2002/12/26 15:02:32  rherveille +//               Core is now a Multimaster I2C controller +// +//               Revision 1.4  2002/11/30 22:24:40  rherveille +//               Cleaned up code +// +//               Revision 1.3  2001/11/05 11:59:25  rherveille +//               Fixed wb_ack_o generation bug. +//               Fixed bug in the byte_controller statemachine. +//               Added headers. +// + +// synopsys translate_off +//`include "timescale.v" +// synopsys translate_on + +`include "i2c_master_defines.v" + +module i2c_master_byte_ctrl ( +	clk, rst, nReset, ena, clk_cnt, start, stop, read, write, ack_in, din, +	cmd_ack, ack_out, dout, i2c_busy, i2c_al, scl_i, scl_o, scl_oen, sda_i, sda_o, sda_oen ); + +	// +	// inputs & outputs +	// +	input clk;     // master clock +	input rst;     // synchronous active high reset +	input nReset;  // asynchronous active low reset +	input ena;     // core enable signal + +	input [15:0] clk_cnt; // 4x SCL + +	// control inputs +	input       start; +	input       stop; +	input       read; +	input       write; +	input       ack_in; +	input [7:0] din; + +	// status outputs +	output       cmd_ack; +	reg cmd_ack; +	output       ack_out; +	reg ack_out; +	output       i2c_busy; +	output       i2c_al; +	output [7:0] dout; + +	// I2C signals +	input  scl_i; +	output scl_o; +	output scl_oen; +	input  sda_i; +	output sda_o; +	output sda_oen; + + +	// +	// Variable declarations +	// + +	// statemachine +	parameter [4:0] ST_IDLE  = 5'b0_0000; +	parameter [4:0] ST_START = 5'b0_0001; +	parameter [4:0] ST_READ  = 5'b0_0010; +	parameter [4:0] ST_WRITE = 5'b0_0100; +	parameter [4:0] ST_ACK   = 5'b0_1000; +	parameter [4:0] ST_STOP  = 5'b1_0000; + +	// signals for bit_controller +	reg  [3:0] core_cmd; +	reg        core_txd; +	wire       core_ack, core_rxd; + +	// signals for shift register +	reg [7:0] sr; //8bit shift register +	reg       shift, ld; + +	// signals for state machine +	wire       go; +	reg  [2:0] dcnt; +	wire       cnt_done; + +	// +	// Module body +	// + +	// hookup bit_controller +	i2c_master_bit_ctrl bit_controller ( +		.clk     ( clk      ), +		.rst     ( rst      ), +		.nReset  ( nReset   ), +		.ena     ( ena      ), +		.clk_cnt ( clk_cnt  ), +		.cmd     ( core_cmd ), +		.cmd_ack ( core_ack ), +		.busy    ( i2c_busy ), +		.al      ( i2c_al   ), +		.din     ( core_txd ), +		.dout    ( core_rxd ), +		.scl_i   ( scl_i    ), +		.scl_o   ( scl_o    ), +		.scl_oen ( scl_oen  ), +		.sda_i   ( sda_i    ), +		.sda_o   ( sda_o    ), +		.sda_oen ( sda_oen  ) +	); + +	// generate go-signal +	assign go = (read | write | stop) & ~cmd_ack; + +	// assign dout output to shift-register +	assign dout = sr; + +	// generate shift register +	always @(posedge clk or negedge nReset) +	  if (!nReset) +	    sr <= #1 8'h0; +	  else if (rst) +	    sr <= #1 8'h0; +	  else if (ld) +	    sr <= #1 din; +	  else if (shift) +	    sr <= #1 {sr[6:0], core_rxd}; + +	// generate counter +	always @(posedge clk or negedge nReset) +	  if (!nReset) +	    dcnt <= #1 3'h0; +	  else if (rst) +	    dcnt <= #1 3'h0; +	  else if (ld) +	    dcnt <= #1 3'h7; +	  else if (shift) +	    dcnt <= #1 dcnt - 3'h1; + +	assign cnt_done = ~(|dcnt); + +	// +	// state machine +	// +	reg [4:0] c_state; // synopsis enum_state + +	always @(posedge clk or negedge nReset) +	  if (!nReset) +	    begin +	        core_cmd <= #1 `I2C_CMD_NOP; +	        core_txd <= #1 1'b0; +	        shift    <= #1 1'b0; +	        ld       <= #1 1'b0; +	        cmd_ack  <= #1 1'b0; +	        c_state  <= #1 ST_IDLE; +	        ack_out  <= #1 1'b0; +	    end +	  else if (rst | i2c_al) +	   begin +	       core_cmd <= #1 `I2C_CMD_NOP; +	       core_txd <= #1 1'b0; +	       shift    <= #1 1'b0; +	       ld       <= #1 1'b0; +	       cmd_ack  <= #1 1'b0; +	       c_state  <= #1 ST_IDLE; +	       ack_out  <= #1 1'b0; +	   end +	else +	  begin +	      // initially reset all signals +	      core_txd <= #1 sr[7]; +	      shift    <= #1 1'b0; +	      ld       <= #1 1'b0; +	      cmd_ack  <= #1 1'b0; + +	      case (c_state) // synopsys full_case parallel_case +	        ST_IDLE: +	          if (go) +	            begin +	                if (start) +	                  begin +	                      c_state  <= #1 ST_START; +	                      core_cmd <= #1 `I2C_CMD_START; +	                  end +	                else if (read) +	                  begin +	                      c_state  <= #1 ST_READ; +	                      core_cmd <= #1 `I2C_CMD_READ; +	                  end +	                else if (write) +	                  begin +	                      c_state  <= #1 ST_WRITE; +	                      core_cmd <= #1 `I2C_CMD_WRITE; +	                  end +	                else // stop +	                  begin +	                      c_state  <= #1 ST_STOP; +	                      core_cmd <= #1 `I2C_CMD_STOP; +	                  end + +	                ld <= #1 1'b1; +	            end + +	        ST_START: +	          if (core_ack) +	            begin +	                if (read) +	                  begin +	                      c_state  <= #1 ST_READ; +	                      core_cmd <= #1 `I2C_CMD_READ; +	                  end +	                else +	                  begin +	                      c_state  <= #1 ST_WRITE; +	                      core_cmd <= #1 `I2C_CMD_WRITE; +	                  end + +	                ld <= #1 1'b1; +	            end + +	        ST_WRITE: +	          if (core_ack) +	            if (cnt_done) +	              begin +	                  c_state  <= #1 ST_ACK; +	                  core_cmd <= #1 `I2C_CMD_READ; +	              end +	            else +	              begin +	                  c_state  <= #1 ST_WRITE;       // stay in same state +	                  core_cmd <= #1 `I2C_CMD_WRITE; // write next bit +	                  shift    <= #1 1'b1; +	              end + +	        ST_READ: +	          if (core_ack) +	            begin +	                if (cnt_done) +	                  begin +	                      c_state  <= #1 ST_ACK; +	                      core_cmd <= #1 `I2C_CMD_WRITE; +	                  end +	                else +	                  begin +	                      c_state  <= #1 ST_READ;       // stay in same state +	                      core_cmd <= #1 `I2C_CMD_READ; // read next bit +	                  end + +	                shift    <= #1 1'b1; +	                core_txd <= #1 ack_in; +	            end + +	        ST_ACK: +	          if (core_ack) +	            begin +	               if (stop) +	                 begin +	                     c_state  <= #1 ST_STOP; +	                     core_cmd <= #1 `I2C_CMD_STOP; +	                 end +	               else +	                 begin +	                     c_state  <= #1 ST_IDLE; +	                     core_cmd <= #1 `I2C_CMD_NOP; + +	                     // generate command acknowledge signal +	                     cmd_ack  <= #1 1'b1; +	                 end + +	                 // assign ack_out output to bit_controller_rxd (contains last received bit) +	                 ack_out <= #1 core_rxd; + +	                 core_txd <= #1 1'b1; +	             end +	           else +	             core_txd <= #1 ack_in; + +	        ST_STOP: +	          if (core_ack) +	            begin +	                c_state  <= #1 ST_IDLE; +	                core_cmd <= #1 `I2C_CMD_NOP; + +	                // generate command acknowledge signal +	                cmd_ack  <= #1 1'b1; +	            end + +	      endcase +	  end +endmodule diff --git a/fpga/usrp3/lib/wishbone/i2c_master_defines.v b/fpga/usrp3/lib/wishbone/i2c_master_defines.v new file mode 100644 index 000000000..ee3b694fa --- /dev/null +++ b/fpga/usrp3/lib/wishbone/i2c_master_defines.v @@ -0,0 +1,64 @@ +///////////////////////////////////////////////////////////////////// +////                                                             //// +////  WISHBONE rev.B2 compliant I2C Master controller defines    //// +////                                                             //// +////                                                             //// +////  Author: Richard Herveille                                  //// +////          richard@asics.ws                                   //// +////          www.asics.ws                                       //// +////                                                             //// +////  Downloaded from: http://www.opencores.org/projects/i2c/    //// +////                                                             //// +///////////////////////////////////////////////////////////////////// +////                                                             //// +//// Copyright (C) 2001 Richard Herveille                        //// +////                    richard@asics.ws                         //// +////                                                             //// +//// 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 SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY     //// +//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED   //// +//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS   //// +//// FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR      //// +//// OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,         //// +//// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES    //// +//// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE   //// +//// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR        //// +//// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF  //// +//// LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT  //// +//// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT  //// +//// OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE         //// +//// POSSIBILITY OF SUCH DAMAGE.                                 //// +////                                                             //// +///////////////////////////////////////////////////////////////////// + +//  CVS Log +// +//  $Id: i2c_master_defines.v,v 1.3 2001/11/05 11:59:25 rherveille Exp $ +// +//  $Date: 2001/11/05 11:59:25 $ +//  $Revision: 1.3 $ +//  $Author: rherveille $ +//  $Locker:  $ +//  $State: Exp $ +// +// Change History: +//               $Log: i2c_master_defines.v,v $ +//               Revision 1.3  2001/11/05 11:59:25  rherveille +//               Fixed wb_ack_o generation bug. +//               Fixed bug in the byte_controller statemachine. +//               Added headers. +// + + +// I2C registers wishbone addresses + +// bitcontroller states +`define I2C_CMD_NOP   4'b0000 +`define I2C_CMD_START 4'b0001 +`define I2C_CMD_STOP  4'b0010 +`define I2C_CMD_WRITE 4'b0100 +`define I2C_CMD_READ  4'b1000 diff --git a/fpga/usrp3/lib/wishbone/i2c_master_top.v b/fpga/usrp3/lib/wishbone/i2c_master_top.v new file mode 100644 index 000000000..be1fcfe55 --- /dev/null +++ b/fpga/usrp3/lib/wishbone/i2c_master_top.v @@ -0,0 +1,301 @@ +///////////////////////////////////////////////////////////////////// +////                                                             //// +////  WISHBONE revB.2 compliant I2C Master controller Top-level  //// +////                                                             //// +////                                                             //// +////  Author: Richard Herveille                                  //// +////          richard@asics.ws                                   //// +////          www.asics.ws                                       //// +////                                                             //// +////  Downloaded from: http://www.opencores.org/projects/i2c/    //// +////                                                             //// +///////////////////////////////////////////////////////////////////// +////                                                             //// +//// Copyright (C) 2001 Richard Herveille                        //// +////                    richard@asics.ws                         //// +////                                                             //// +//// 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 SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY     //// +//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED   //// +//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS   //// +//// FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR      //// +//// OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,         //// +//// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES    //// +//// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE   //// +//// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR        //// +//// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF  //// +//// LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT  //// +//// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT  //// +//// OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE         //// +//// POSSIBILITY OF SUCH DAMAGE.                                 //// +////                                                             //// +///////////////////////////////////////////////////////////////////// + +//  CVS Log +// +//  $Id: i2c_master_top.v,v 1.11 2005/02/27 09:26:24 rherveille Exp $ +// +//  $Date: 2005/02/27 09:26:24 $ +//  $Revision: 1.11 $ +//  $Author: rherveille $ +//  $Locker:  $ +//  $State: Exp $ +// +// Change History: +//               $Log: i2c_master_top.v,v $ +//               Revision 1.11  2005/02/27 09:26:24  rherveille +//               Fixed register overwrite issue. +//               Removed full_case pragma, replaced it by a default statement. +// +//               Revision 1.10  2003/09/01 10:34:38  rherveille +//               Fix a blocking vs. non-blocking error in the wb_dat output mux. +// +//               Revision 1.9  2003/01/09 16:44:45  rherveille +//               Fixed a bug in the Command Register declaration. +// +//               Revision 1.8  2002/12/26 16:05:12  rherveille +//               Small code simplifications +// +//               Revision 1.7  2002/12/26 15:02:32  rherveille +//               Core is now a Multimaster I2C controller +// +//               Revision 1.6  2002/11/30 22:24:40  rherveille +//               Cleaned up code +// +//               Revision 1.5  2001/11/10 10:52:55  rherveille +//               Changed PRER reset value from 0x0000 to 0xffff, conform specs. +// + +// synopsys translate_off +//`include "timescale.v" +// synopsys translate_on + +`include "i2c_master_defines.v" + +module i2c_master_top( +	wb_clk_i, wb_rst_i, arst_i, wb_adr_i, wb_dat_i, wb_dat_o, +	wb_we_i, wb_stb_i, wb_cyc_i, wb_ack_o, wb_inta_o, +	scl_pad_i, scl_pad_o, scl_padoen_o, sda_pad_i, sda_pad_o, sda_padoen_o ); + +	// parameters +	parameter ARST_LVL = 1'b0; // asynchronous reset level + +	// +	// inputs & outputs +	// + +	// wishbone signals +	input        wb_clk_i;     // master clock input +	input        wb_rst_i;     // synchronous active high reset +	input        arst_i;       // asynchronous reset +	input  [2:0] wb_adr_i;     // lower address bits +	input  [7:0] wb_dat_i;     // databus input +	output [7:0] wb_dat_o;     // databus output +	input        wb_we_i;      // write enable input +	input        wb_stb_i;     // stobe/core select signal +	input        wb_cyc_i;     // valid bus cycle input +	output       wb_ack_o;     // bus cycle acknowledge output +	output       wb_inta_o;    // interrupt request signal output + +	reg [7:0] wb_dat_o; +	reg wb_ack_o; +	reg wb_inta_o; + +	// I2C signals +	// i2c clock line +	input  scl_pad_i;       // SCL-line input +	output scl_pad_o;       // SCL-line output (always 1'b0) +	output scl_padoen_o;    // SCL-line output enable (active low) + +	// i2c data line +	input  sda_pad_i;       // SDA-line input +	output sda_pad_o;       // SDA-line output (always 1'b0) +	output sda_padoen_o;    // SDA-line output enable (active low) + + +	// +	// variable declarations +	// + +	// registers +	reg  [15:0] prer; // clock prescale register +	reg  [ 7:0] ctr;  // control register +	reg  [ 7:0] txr;  // transmit register +	wire [ 7:0] rxr;  // receive register +	reg  [ 7:0] cr;   // command register +	wire [ 7:0] sr;   // status register + +	// done signal: command completed, clear command register +	wire done; + +	// core enable signal +	wire core_en; +	wire ien; + +	// status register signals +	wire irxack; +	reg  rxack;       // received aknowledge from slave +	reg  tip;         // transfer in progress +	reg  irq_flag;    // interrupt pending flag +	wire i2c_busy;    // bus busy (start signal detected) +	wire i2c_al;      // i2c bus arbitration lost +	reg  al;          // status register arbitration lost bit + +	// +	// module body +	// + +	// generate internal reset +	wire rst_i = arst_i ^ ARST_LVL; + +	// generate wishbone signals +	wire wb_wacc = wb_cyc_i & wb_stb_i & wb_we_i; + +	// generate acknowledge output signal +	always @(posedge wb_clk_i) +	  wb_ack_o <= #1 wb_cyc_i & wb_stb_i & ~wb_ack_o; // because timing is always honored + +	// assign DAT_O +	always @(posedge wb_clk_i) +	begin +	  case (wb_adr_i) // synopsis parallel_case +	    3'b000: wb_dat_o <= #1 prer[ 7:0]; +	    3'b001: wb_dat_o <= #1 prer[15:8]; +	    3'b010: wb_dat_o <= #1 ctr; +	    3'b011: wb_dat_o <= #1 rxr; // write is transmit register (txr) +	    3'b100: wb_dat_o <= #1 sr;  // write is command register (cr) +	    3'b101: wb_dat_o <= #1 txr; +	    3'b110: wb_dat_o <= #1 cr; +	    3'b111: wb_dat_o <= #1 0;   // reserved +	  endcase +	end + +	// generate registers +	always @(posedge wb_clk_i or negedge rst_i) +	  if (!rst_i) +	    begin +	        prer <= #1 16'hffff; +	        ctr  <= #1  8'h0; +	        txr  <= #1  8'h0; +	    end +	  else if (wb_rst_i) +	    begin +	        prer <= #1 16'hffff; +	        ctr  <= #1  8'h0; +	        txr  <= #1  8'h0; +	    end +	  else +	    if (wb_wacc) +	      case (wb_adr_i) // synopsis parallel_case +	         3'b000 : prer [ 7:0] <= #1 wb_dat_i; +	         3'b001 : prer [15:8] <= #1 wb_dat_i; +	         3'b010 : ctr         <= #1 wb_dat_i; +	         3'b011 : txr         <= #1 wb_dat_i; +	         default: ; +	      endcase + +	// generate command register (special case) +	always @(posedge wb_clk_i or negedge rst_i) +	  if (~rst_i) +	    cr <= #1 8'h0; +	  else if (wb_rst_i) +	    cr <= #1 8'h0; +	  else if (wb_wacc) +	    begin +	        if (core_en & (wb_adr_i == 3'b100) ) +	          cr <= #1 wb_dat_i; +	    end +	  else +	    begin +	        if (done | i2c_al) +	          cr[7:4] <= #1 4'h0;           // clear command bits when done +	                                        // or when aribitration lost +	        cr[2:1] <= #1 2'b0;             // reserved bits +	        cr[0]   <= #1 2'b0;             // clear IRQ_ACK bit +	    end + + +	// decode command register +	wire sta  = cr[7]; +	wire sto  = cr[6]; +	wire rd   = cr[5]; +	wire wr   = cr[4]; +	wire ack  = cr[3]; +	wire iack = cr[0]; + +	// decode control register +	assign core_en = ctr[7]; +	assign ien = ctr[6]; + +	// hookup byte controller block +	i2c_master_byte_ctrl byte_controller ( +		.clk      ( wb_clk_i     ), +		.rst      ( wb_rst_i     ), +		.nReset   ( rst_i        ), +		.ena      ( core_en      ), +		.clk_cnt  ( prer         ), +		.start    ( sta          ), +		.stop     ( sto          ), +		.read     ( rd           ), +		.write    ( wr           ), +		.ack_in   ( ack          ), +		.din      ( txr          ), +		.cmd_ack  ( done         ), +		.ack_out  ( irxack       ), +		.dout     ( rxr          ), +		.i2c_busy ( i2c_busy     ), +		.i2c_al   ( i2c_al       ), +		.scl_i    ( scl_pad_i    ), +		.scl_o    ( scl_pad_o    ), +		.scl_oen  ( scl_padoen_o ), +		.sda_i    ( sda_pad_i    ), +		.sda_o    ( sda_pad_o    ), +		.sda_oen  ( sda_padoen_o ) +	); + +	// status register block + interrupt request signal +	always @(posedge wb_clk_i or negedge rst_i) +	  if (!rst_i) +	    begin +	        al       <= #1 1'b0; +	        rxack    <= #1 1'b0; +	        tip      <= #1 1'b0; +	        irq_flag <= #1 1'b0; +	    end +	  else if (wb_rst_i) +	    begin +	        al       <= #1 1'b0; +	        rxack    <= #1 1'b0; +	        tip      <= #1 1'b0; +	        irq_flag <= #1 1'b0; +	    end +	  else +	    begin +	        al       <= #1 i2c_al | (al & ~sta); +	        rxack    <= #1 irxack; +	        tip      <= #1 (rd | wr); +	        irq_flag <= #1 (done | i2c_al | irq_flag) & ~iack; // interrupt request flag is always generated +	    end + +	// generate interrupt request signals +	always @(posedge wb_clk_i or negedge rst_i) +	  if (!rst_i) +	    wb_inta_o <= #1 1'b0; +	  else if (wb_rst_i) +	    wb_inta_o <= #1 1'b0; +	  else +	    wb_inta_o <= #1 irq_flag && ien; // interrupt signal is only generated when IEN (interrupt enable bit is set) + +	// assign status register bits +	assign sr[7]   = rxack; +	assign sr[6]   = i2c_busy; +	assign sr[5]   = al; +	assign sr[4:2] = 3'h0; // reserved +	assign sr[1]   = tip; +	assign sr[0]   = irq_flag; + +endmodule diff --git a/fpga/usrp3/lib/wishbone/settings_bus.v b/fpga/usrp3/lib/wishbone/settings_bus.v new file mode 100644 index 000000000..39f148916 --- /dev/null +++ b/fpga/usrp3/lib/wishbone/settings_bus.v @@ -0,0 +1,46 @@ +// +// Copyright 2011-2012 Ettus Research LLC +// + + + +// Grab settings off the wishbone bus, send them out to our simpler bus on the fast clock + +module settings_bus +  #(parameter AWIDTH=16, parameter DWIDTH=32, parameter SWIDTH=8) +    (input wb_clk,  +     input wb_rst,  +     input [AWIDTH-1:0] wb_adr_i, +     input [DWIDTH-1:0] wb_dat_i, +     input wb_stb_i, +     input wb_we_i, +     output reg wb_ack_o, +     output reg strobe, +     output reg [SWIDTH-1:0] addr, +     output reg [31:0] data); + +   reg 	    stb_int, stb_int_d1; +    +   always @(posedge wb_clk) +     if(wb_rst) +       begin +	  strobe <= 1'b0; +	  addr <= {SWIDTH{1'b0}}; +	  data <= 32'd0; +       end +     else if(wb_we_i & wb_stb_i & ~wb_ack_o) +       begin +	  strobe <= 1'b1; +	  addr <= wb_adr_i[SWIDTH+1:2]; +	  data <= wb_dat_i; +       end +     else +       strobe <= 1'b0; + +   always @(posedge wb_clk) +     if(wb_rst) +       wb_ack_o <= 0; +     else +       wb_ack_o <= wb_stb_i & ~wb_ack_o; + +endmodule // settings_bus diff --git a/fpga/usrp3/lib/wishbone/settings_readback.v b/fpga/usrp3/lib/wishbone/settings_readback.v new file mode 100644 index 000000000..745571717 --- /dev/null +++ b/fpga/usrp3/lib/wishbone/settings_readback.v @@ -0,0 +1,40 @@ +// +// Copyright 2011-2012 Ettus Research LLC +// + + +// +// Use this module in conjunction with settings_bus.v to add stateful reads +// to the settings bis. This enables you to do things like have registers reset atomicly +// as they are read. It also pipelines the address path to ease timing. +// + +module settings_readback +  #(parameter AWIDTH=16, parameter DWIDTH=32, parameter RB_ADDRW=2) +   ( +    input wb_clk,  +    input wb_rst,  +    input [AWIDTH-1:0] wb_adr_i, +    input wb_stb_i, +    input wb_we_i, +    input [DWIDTH-1:0] rb_data, +    output reg [RB_ADDRW-1:0] rb_addr, +    output [DWIDTH-1:0] wb_dat_o, +    output reg rb_rd_stb +    ); + +   always @(posedge wb_clk) +     if (wb_stb_i && ~wb_we_i) begin +	rb_addr <= wb_adr_i[RB_ADDRW+1:2]; +	rb_rd_stb <= 1'b1;	 +     end else begin +	rb_rd_stb <= 1'b0;	 +     end +    +   assign wb_dat_o = rb_data; + +    + +endmodule // settings_readback + +  
\ No newline at end of file diff --git a/fpga/usrp3/lib/wishbone/simple_uart.v b/fpga/usrp3/lib/wishbone/simple_uart.v new file mode 100644 index 000000000..51dc23f16 --- /dev/null +++ b/fpga/usrp3/lib/wishbone/simple_uart.v @@ -0,0 +1,65 @@ +// +// Copyright 2011 Ettus Research LLC +// + + + +module simple_uart +  #(parameter CLKDIV_DEFAULT = 16'd0) +   (input clk_i, input rst_i, +    input we_i, input stb_i, input cyc_i, output reg ack_o, +    input [2:0] adr_i, input [31:0] dat_i, output reg [31:0] dat_o, +    output rx_int_o, output tx_int_o, output tx_o, input rx_i, output baud_o); +    +   // Register Map +   localparam SUART_CLKDIV = 0; +   localparam SUART_TXLEVEL = 1; +   localparam SUART_RXLEVEL = 2; +   localparam SUART_TXCHAR = 3; +   localparam SUART_RXCHAR = 4; +    +   wire       wb_acc = cyc_i & stb_i;            // WISHBONE access +   wire       wb_wr  = wb_acc & we_i;            // WISHBONE write access +    +   reg [15:0] clkdiv; +   wire [7:0] rx_char; +   wire       tx_fifo_full, rx_fifo_empty; +   wire [5:0] tx_fifo_level, rx_fifo_level; +    +   always @(posedge clk_i) +     if (rst_i) +       ack_o <= 1'b0; +     else +       ack_o <= wb_acc & ~ack_o; +    +   always @(posedge clk_i) +     if (rst_i) +       clkdiv <= CLKDIV_DEFAULT; +     else if (wb_wr) +       case(adr_i) +	 SUART_CLKDIV : clkdiv <= dat_i[15:0]; +       endcase // case(adr_i) +    +   always @(posedge clk_i) +     case (adr_i) +       SUART_TXLEVEL : dat_o <= tx_fifo_level; +       SUART_RXLEVEL : dat_o <= rx_fifo_level; +       SUART_RXCHAR : dat_o <= rx_char; +     endcase // case(adr_i) +    +   simple_uart_tx simple_uart_tx +     (.clk(clk_i),.rst(rst_i), +      .fifo_in(dat_i[7:0]),.fifo_write(ack_o && wb_wr && (adr_i == SUART_TXCHAR)), +      .fifo_level(tx_fifo_level),.fifo_full(tx_fifo_full), +      .clkdiv(clkdiv),.baudclk(baud_o),.tx(tx_o)); +    +   simple_uart_rx simple_uart_rx +     (.clk(clk_i),.rst(rst_i), +      .fifo_out(rx_char),.fifo_read(ack_o && ~wb_wr && (adr_i == SUART_RXCHAR)), +      .fifo_level(rx_fifo_level),.fifo_empty(rx_fifo_empty), +      .clkdiv(clkdiv),.rx(rx_i)); +    +   assign     tx_int_o = ~tx_fifo_full; +   assign     rx_int_o = ~rx_fifo_empty; +    +endmodule // simple_uart diff --git a/fpga/usrp3/lib/wishbone/simple_uart_rx.v b/fpga/usrp3/lib/wishbone/simple_uart_rx.v new file mode 100644 index 000000000..7790a0a87 --- /dev/null +++ b/fpga/usrp3/lib/wishbone/simple_uart_rx.v @@ -0,0 +1,71 @@ +// +// Copyright 2011-2013 Ettus Research LLC +// + + + + +module simple_uart_rx +    #(parameter SIZE=0) +    (input clk, input rst,  +     output [7:0] fifo_out, input fifo_read, output [5:0] fifo_level, output fifo_empty,  +     input [15:0] clkdiv, input rx); + +   reg 		  rx_d1, rx_d2; +   always @(posedge clk) +     if(rst) +       {rx_d2,rx_d1} <= 0; +     else +       {rx_d2,rx_d1} <= {rx_d1,rx}; +    +   reg [15:0] 	  baud_ctr; +   reg [3:0] 	  bit_ctr; +   reg [7:0] 	  sr; + +   wire 	  neg_trans = rx_d2 & ~rx_d1; +   wire 	  shift_now = baud_ctr == (clkdiv>>1); +   wire 	  stop_now = (bit_ctr == 10) && shift_now; +   wire 	  go_now = (bit_ctr == 0) && neg_trans; +    +   always @(posedge clk) +     if(rst) +       sr <= 0; +     else if(shift_now) +       sr <= {rx_d2,sr[7:1]}; +    +   always @(posedge clk) +     if(rst) +       baud_ctr <= 0; +     else +       if(go_now) +	 baud_ctr <= 1; +       else if(stop_now) +	 baud_ctr <= 0; +       else if(baud_ctr >= clkdiv) +	 baud_ctr <= 1; +       else if(baud_ctr != 0) +	 baud_ctr <= baud_ctr + 1; + +   always @(posedge clk) +     if(rst) +       bit_ctr <= 0; +     else  +       if(go_now) +	 bit_ctr <= 1; +       else if(stop_now) +	 bit_ctr <= 0; +       else if(baud_ctr == clkdiv) +	 bit_ctr <= bit_ctr + 1; + +   wire 	  i_tready, o_tvalid; +   wire 	  full = ~i_tready; +   wire 	  write = ~full & rx_d2 & stop_now; +   assign fifo_empty = ~o_tvalid; +    +   axi_fifo #(.WIDTH(8), .SIZE(SIZE)) fifo +     (.clk(clk),.reset(rst), .clear(1'b0), +      .i_tdata(sr),.i_tvalid(write),.i_tready(i_tready), +      .o_tdata(fifo_out),.o_tvalid(o_tvalid),.o_tready(fifo_read), +      .space(),.occupied(fifo_level) ); +    +endmodule // simple_uart_rx diff --git a/fpga/usrp3/lib/wishbone/simple_uart_tb.v b/fpga/usrp3/lib/wishbone/simple_uart_tb.v new file mode 100644 index 000000000..8b1427f99 --- /dev/null +++ b/fpga/usrp3/lib/wishbone/simple_uart_tb.v @@ -0,0 +1,127 @@ +module simple_uart_tb(); +    +   localparam SUART_CLKDIV = 0; +   localparam SUART_TXLEVEL = 1; +   localparam SUART_RXLEVEL = 2; +   localparam SUART_TXCHAR = 3; +   localparam SUART_RXCHAR = 4; +    +   reg           clk; +   reg 		 rst; + +   reg 		 we_i; +   reg 		 stb_i; +   reg 		 cyc_i; +   wire 	 ack_o; +   reg [2:0] 	 adr_i; +   reg [31:0] 	 dat_i; +   wire [31:0] 	 dat_o; +   wire 	 rx_int_o; +   wire 	 tx_int_o; +   wire 	 tx_o; +   reg 		 rx_i; +   wire 	 baud_o; + +   reg [31:0] 	 read_data; +    + +   initial  +     clk = 0; + +   // 200MHz clock +   always +     #2.5 clk = ~clk; + +   initial begin +      rst <= 0; +      we_i <= 0; +      stb_i <= 0; +      cyc_i <= 0; +      adr_i <= 0; +      dat_i <= 0; +      rx_i <= 0; +   end +    +    +   task write_wb; +      input [31:0] data_in; +      input [2:0]  addr_in; + +      begin +	 @(negedge clk);	  +	 dat_i <= data_in; +	 adr_i <= addr_in; +	 we_i <= 1; +	 stb_i <= 1; +	 cyc_i <= 1; +	 @(negedge clk); +	 while (ack_o == 0) begin +	    @(negedge clk); +	 end +	 dat_i <= 0; +	 adr_i <= 0; +	 we_i <= 0; +	 stb_i <= 0; +	 cyc_i <= 0; +      end +   endtask // write_wb + +    +   task read_wb; +      output [31:0] data_out; +      input [2:0]  addr_in; + +      begin +	 @(negedge clk);	  +	 adr_i <= addr_in; +	 we_i <= 0; +	 stb_i <= 1; +	 cyc_i <= 1; +	 @(negedge clk); +	 while (ack_o == 0) begin +	    @(negedge clk); +	 end +	 data_out <= dat_o; +	 adr_i <= 0; +	 stb_i <= 0; +	 cyc_i <= 0; +      end +   endtask // write_wb + +   initial begin +      @(negedge clk);     +      rst <= 1; +      repeat(10) @(negedge clk); +      rst <= 0; +      repeat(10) @(negedge clk); +      write_wb(4'h0620,SUART_CLKDIV); +      repeat(10) @(negedge clk); +      read_wb(read_data,SUART_TXLEVEL); +      repeat(10) @(negedge clk); +   end // initial begin +    +    +    +   simple_uart +     #(.CLKDIV_DEFAULT(16'd0)) +   simple_uart_i +     ( +      .clk_i(clk), +      .rst_i(rst), +      .we_i(we_i), +      .stb_i(stb_i), +      .cyc_i(cyc_i), +      .ack_o(ack_o), +      .adr_i(adr_i), +      .dat_i(dat_i), +      .dat_o(dat_o), +      .rx_int_o(rx_int_o), +      .tx_int_o(tx_int_o),  +      .tx_o(tx_o),  +      .rx_i(rx_i), +      .baud_o(baud_o) +      ); + +    + +endmodule // simple_uart_tb diff --git a/fpga/usrp3/lib/wishbone/simple_uart_tx.v b/fpga/usrp3/lib/wishbone/simple_uart_tx.v new file mode 100644 index 000000000..3eb1a1ecd --- /dev/null +++ b/fpga/usrp3/lib/wishbone/simple_uart_tx.v @@ -0,0 +1,69 @@ +// +// Copyright 2011-2013 Ettus Research LLC +// + + + +module simple_uart_tx +    #(parameter SIZE=0) +    (input clk, input rst,  +     input [7:0] fifo_in, input fifo_write, output [5:0] fifo_level, output fifo_full,  +     input [15:0] clkdiv, output baudclk, output reg tx); +    +   reg [15:0] 	  baud_ctr; +   reg [3:0] 	  bit_ctr; +    +   wire 	  read, empty; +   wire [7:0] 	  char_to_send; +   wire 	  i_tready, o_tvalid; +    +   assign fifo_full = ~i_tready; +   assign empty = ~o_tvalid; +    +   axi_fifo #(.WIDTH(8), .SIZE(SIZE)) fifo +     (.clk(clk),.reset(rst), .clear(1'b0), +      .i_tdata(fifo_in), .i_tvalid(fifo_write), .i_tready(i_tready), +      .o_tdata(char_to_send),.o_tvalid(o_tvalid),.o_tready(read), +      .space(fifo_level),.occupied() ); +    +   always @(posedge clk) +     if(rst) +       baud_ctr <= 0; +     else if (baud_ctr >= clkdiv) +       baud_ctr <= 0; +     else +       baud_ctr <= baud_ctr + 1; + +   always @(posedge clk) +     if(rst) +       bit_ctr <= 0; +     else if(baud_ctr == clkdiv) +       if(bit_ctr == 10) +	 bit_ctr <= 0; +       else if(bit_ctr != 0) +	 bit_ctr <= bit_ctr + 1; +       else if(~empty) +	 bit_ctr <= 1; +    +   always @(posedge clk) +     if(rst) +       tx <= 1; +     else +       case(bit_ctr) +	 0 : tx <= 1; +	 1 : tx <= 0; +	 2 : tx <= char_to_send[0]; +	 3 : tx <= char_to_send[1]; +	 4 : tx <= char_to_send[2]; +	 5 : tx <= char_to_send[3]; +	 6 : tx <= char_to_send[4]; +	 7 : tx <= char_to_send[5]; +	 8 : tx <= char_to_send[6]; +	 9 : tx <= char_to_send[7]; +	 default : tx <= 1; +       endcase // case(bit_ctr) + +   assign 	  read = (bit_ctr == 9) && (baud_ctr == clkdiv); +   assign 	  baudclk = (baud_ctr == 1);  // Only for debug purposes +    +endmodule // simple_uart_tx diff --git a/fpga/usrp3/lib/wishbone/wb_1master.v b/fpga/usrp3/lib/wishbone/wb_1master.v new file mode 100644 index 000000000..fb313efae --- /dev/null +++ b/fpga/usrp3/lib/wishbone/wb_1master.v @@ -0,0 +1,464 @@ +///////////////////////////////////////////////////////////////////// +////                                                             //// +////  WISHBONE Connection Bus Top Level		                 //// +////                                                             //// +////                                                             //// +////  Original Author: Johny Chi		                 //// +////                   chisuhua@yahoo.com.cn                     //// +////  Modified By Matt Ettus, matt@ettus.com                     //// +////                                                             //// +////                                                             //// +///////////////////////////////////////////////////////////////////// +////                                                              //// +//// Copyright (C) 2000, 2007 Authors and OPENCORES.ORG           //// +////                                                              //// +//// 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                     //// +////                                                              //// +////////////////////////////////////////////////////////////////////// +// +//   Up to 8 slaves share a Wishbone Bus connection to 1 master + +  module wb_1master +    #(parameter	decode_w = 8,			// address decode width +      parameter	s0_addr = 8'h0,			// slave 0 address +      parameter	s0_mask = 8'h0,			// slave 0 don't cares +      parameter	s1_addr = 8'h0,			// slave 1 address +      parameter	s1_mask = 8'h0,			// slave 1 don't cares +      parameter	s2_addr = 8'h0,			// slave 2 address +      parameter	s2_mask = 8'h0,			// slave 2 don't cares +      parameter	s3_addr = 8'h0,			// slave 3 address +      parameter	s3_mask = 8'h0,			// slave 3 don't cares +      parameter	s4_addr = 8'h0,			// slave 4 address +      parameter	s4_mask = 8'h0,			// slave 4 don't cares +      parameter	s5_addr = 8'h0,			// slave 5 address +      parameter	s5_mask = 8'h0,			// slave 5 don't cares +      parameter	s6_addr = 8'h0,			// slave 6 address +      parameter	s6_mask = 8'h0,			// slave 6 don't cares +      parameter	s7_addr = 8'h0,			// slave 7 address +      parameter	s7_mask = 8'h0,			// slave 7 don't cares +      parameter	s8_addr = 8'h0,			// slave 8 address +      parameter	s8_mask = 8'h0,			// slave 8 don't cares +      parameter	s9_addr = 8'h0,			// slave 9 address +      parameter	s9_mask = 8'h0,			// slave 9 don't cares +      parameter	sa_addr = 8'h0,			// slave a address +      parameter	sa_mask = 8'h0,			// slave a don't cares +      parameter	sb_addr = 8'h0,			// slave b address +      parameter	sb_mask = 8'h0,			// slave b don't cares +      parameter	sc_addr = 8'h0,			// slave c address +      parameter	sc_mask = 8'h0,			// slave c don't cares +      parameter	sd_addr = 8'h0,			// slave d address +      parameter	sd_mask = 8'h0,			// slave d don't cares +      parameter	se_addr = 8'h0,			// slave e address +      parameter	se_mask = 8'h0,			// slave e don't cares +      parameter	sf_addr = 8'h0,			// slave f address +      parameter	sf_mask = 8'h0,			// slave f don't cares +             +      parameter	dw = 32,		// Data bus Width +      parameter	aw = 32,		// Address bus Width +      parameter	sw = 4)                 // Number of Select Lines +       +      (input clk_i,  +       input rst_i, +        +       // Master  Interface +       input [dw-1:0]   m0_dat_i, +       output [dw-1:0] 	m0_dat_o, +       input [aw-1:0] 	m0_adr_i, +       input [sw-1:0] 	m0_sel_i, +       input 		m0_we_i, +       input 		m0_cyc_i, +       input 		m0_stb_i, +       output 		m0_ack_o, +       output 		m0_err_o, +       output 		m0_rty_o, +        +       // Slave Interfaces +       input [dw-1:0] 	s0_dat_i, +       output [dw-1:0] 	s0_dat_o, +       output [aw-1:0] 	s0_adr_o, +       output [sw-1:0] 	s0_sel_o, +       output 		s0_we_o, +       output 		s0_cyc_o, +       output 		s0_stb_o, +       input 		s0_ack_i, +       input 		s0_err_i, +       input 		s0_rty_i, +        +       input [dw-1:0] 	s1_dat_i, +       output [dw-1:0] 	s1_dat_o, +       output [aw-1:0] 	s1_adr_o, +       output [sw-1:0] 	s1_sel_o, +       output 		s1_we_o, +       output 		s1_cyc_o, +       output 		s1_stb_o, +       input 		s1_ack_i, +       input 		s1_err_i, +       input 		s1_rty_i, +        +       input [dw-1:0] 	s2_dat_i, +       output [dw-1:0] 	s2_dat_o, +       output [aw-1:0] 	s2_adr_o, +       output [sw-1:0] 	s2_sel_o, +       output 		s2_we_o, +       output 		s2_cyc_o, +       output 		s2_stb_o, +       input 		s2_ack_i, +       input 		s2_err_i, +       input 		s2_rty_i, +        +       input [dw-1:0] 	s3_dat_i, +       output [dw-1:0] 	s3_dat_o, +       output [aw-1:0] 	s3_adr_o, +       output [sw-1:0] 	s3_sel_o, +       output 		s3_we_o, +       output 		s3_cyc_o, +       output 		s3_stb_o, +       input 		s3_ack_i, +       input 		s3_err_i, +       input 		s3_rty_i, +        +       input [dw-1:0] 	s4_dat_i, +       output [dw-1:0] 	s4_dat_o, +       output [aw-1:0] 	s4_adr_o, +       output [sw-1:0] 	s4_sel_o, +       output 		s4_we_o, +       output 		s4_cyc_o, +       output 		s4_stb_o, +       input 		s4_ack_i, +       input 		s4_err_i, +       input 		s4_rty_i, +        +       input [dw-1:0] 	s5_dat_i, +       output [dw-1:0] 	s5_dat_o, +       output [aw-1:0] 	s5_adr_o, +       output [sw-1:0] 	s5_sel_o, +       output 		s5_we_o, +       output 		s5_cyc_o, +       output 		s5_stb_o, +       input 		s5_ack_i, +       input 		s5_err_i, +       input 		s5_rty_i, +        +       input [dw-1:0] 	s6_dat_i, +       output [dw-1:0] 	s6_dat_o, +       output [aw-1:0] 	s6_adr_o, +       output [sw-1:0] 	s6_sel_o, +       output 		s6_we_o, +       output 		s6_cyc_o, +       output 		s6_stb_o, +       input 		s6_ack_i, +       input 		s6_err_i, +       input 		s6_rty_i, +        +       input [dw-1:0] 	s7_dat_i, +       output [dw-1:0] 	s7_dat_o, +       output [aw-1:0] 	s7_adr_o, +       output [sw-1:0] 	s7_sel_o, +       output 		s7_we_o, +       output 		s7_cyc_o, +       output 		s7_stb_o, +       input 		s7_ack_i, +       input 		s7_err_i, +       input 		s7_rty_i, + +       input [dw-1:0] 	s8_dat_i, +       output [dw-1:0] 	s8_dat_o, +       output [aw-1:0] 	s8_adr_o, +       output [sw-1:0] 	s8_sel_o, +       output 		s8_we_o, +       output 		s8_cyc_o, +       output 		s8_stb_o, +       input 		s8_ack_i, +       input 		s8_err_i, +       input 		s8_rty_i, +        +       input [dw-1:0] 	s9_dat_i, +       output [dw-1:0] 	s9_dat_o, +       output [aw-1:0] 	s9_adr_o, +       output [sw-1:0] 	s9_sel_o, +       output 		s9_we_o, +       output 		s9_cyc_o, +       output 		s9_stb_o, +       input 		s9_ack_i, +       input 		s9_err_i, +       input 		s9_rty_i, +        +       input [dw-1:0] 	sa_dat_i, +       output [dw-1:0] 	sa_dat_o, +       output [aw-1:0] 	sa_adr_o, +       output [sw-1:0] 	sa_sel_o, +       output 		sa_we_o, +       output 		sa_cyc_o, +       output 		sa_stb_o, +       input 		sa_ack_i, +       input 		sa_err_i, +       input 		sa_rty_i, +        +       input [dw-1:0] 	sb_dat_i, +       output [dw-1:0] 	sb_dat_o, +       output [aw-1:0] 	sb_adr_o, +       output [sw-1:0] 	sb_sel_o, +       output 		sb_we_o, +       output 		sb_cyc_o, +       output 		sb_stb_o, +       input 		sb_ack_i, +       input 		sb_err_i, +       input 		sb_rty_i, +        +       input [dw-1:0] 	sc_dat_i, +       output [dw-1:0] 	sc_dat_o, +       output [aw-1:0] 	sc_adr_o, +       output [sw-1:0] 	sc_sel_o, +       output 		sc_we_o, +       output 		sc_cyc_o, +       output 		sc_stb_o, +       input 		sc_ack_i, +       input 		sc_err_i, +       input 		sc_rty_i, +        +       input [dw-1:0] 	sd_dat_i, +       output [dw-1:0] 	sd_dat_o, +       output [aw-1:0] 	sd_adr_o, +       output [sw-1:0] 	sd_sel_o, +       output 		sd_we_o, +       output 		sd_cyc_o, +       output 		sd_stb_o, +       input 		sd_ack_i, +       input 		sd_err_i, +       input 		sd_rty_i, +        +       input [dw-1:0] 	se_dat_i, +       output [dw-1:0] 	se_dat_o, +       output [aw-1:0] 	se_adr_o, +       output [sw-1:0] 	se_sel_o, +       output 		se_we_o, +       output 		se_cyc_o, +       output 		se_stb_o, +       input 		se_ack_i, +       input 		se_err_i, +       input 		se_rty_i, +        +       input [dw-1:0] 	sf_dat_i, +       output [dw-1:0] 	sf_dat_o, +       output [aw-1:0] 	sf_adr_o, +       output [sw-1:0] 	sf_sel_o, +       output 		sf_we_o, +       output 		sf_cyc_o, +       output 		sf_stb_o, +       input 		sf_ack_i, +       input 		sf_err_i, +       input 		sf_rty_i +       ); +    +   // //////////////////////////////////////////////////////////////// +   // +   // Local wires +   // +    +   wire [15:0] 		ssel_dec; +   reg [dw-1:0] 	i_dat_s;	// internal share bus , slave data to master +    +   // Master output Interface +   assign 		m0_dat_o = i_dat_s; +    +   always @* +     case(ssel_dec) +       1   : i_dat_s <= s0_dat_i; +       2   : i_dat_s <= s1_dat_i; +       4   : i_dat_s <= s2_dat_i; +       8   : i_dat_s <= s3_dat_i; +       16  : i_dat_s <= s4_dat_i; +       32  : i_dat_s <= s5_dat_i; +       64  : i_dat_s <= s6_dat_i; +       128 : i_dat_s <= s7_dat_i; +       256 : i_dat_s <= s8_dat_i; +       512 : i_dat_s <= s9_dat_i; +       1024 : i_dat_s <= sa_dat_i; +       2048 : i_dat_s <= sb_dat_i; +       4096 : i_dat_s <= sc_dat_i; +       8192 : i_dat_s <= sd_dat_i; +       16384 : i_dat_s <= se_dat_i; +       32768 : i_dat_s <= sf_dat_i; +       default : i_dat_s <= s0_dat_i; +     endcase // case(ssel_dec) +    +   assign 		{m0_ack_o, m0_err_o, m0_rty_o}  +     =  {s0_ack_i | s1_ack_i | s2_ack_i | s3_ack_i | s4_ack_i | s5_ack_i | s6_ack_i | s7_ack_i | +	 s8_ack_i | s9_ack_i | sa_ack_i | sb_ack_i | sc_ack_i | sd_ack_i | se_ack_i | sf_ack_i , +	 s0_err_i | s1_err_i | s2_err_i | s3_err_i | s4_err_i | s5_err_i | s6_err_i | s7_err_i | +	 s8_err_i | s9_err_i | sa_err_i | sb_err_i | sc_err_i | sd_err_i | se_err_i | sf_err_i , +	 s0_rty_i | s1_rty_i | s2_rty_i | s3_rty_i | s4_rty_i | s5_rty_i | s6_rty_i | s7_rty_i | +	 s8_rty_i | s9_rty_i | sa_rty_i | sb_rty_i | sc_rty_i | sd_rty_i | se_rty_i | sf_rty_i }; + +   // Slave output interfaces +   assign 		s0_adr_o = m0_adr_i; +   assign 		s0_sel_o = m0_sel_i; +   assign 		s0_dat_o = m0_dat_i; +   assign 		s0_we_o = m0_we_i; +   assign 		s0_cyc_o = m0_cyc_i; +   assign 		s0_stb_o = m0_cyc_i & m0_stb_i & ssel_dec[0];    +    +   assign 		s1_adr_o = m0_adr_i; +   assign 		s1_sel_o = m0_sel_i; +   assign 		s1_dat_o = m0_dat_i; +   assign 		s1_we_o = m0_we_i; +   assign 		s1_cyc_o = m0_cyc_i; +   assign 		s1_stb_o = m0_cyc_i & m0_stb_i & ssel_dec[1];    +    +   assign 		s2_adr_o = m0_adr_i; +   assign 		s2_sel_o = m0_sel_i; +   assign 		s2_dat_o = m0_dat_i; +   assign 		s2_we_o = m0_we_i; +   assign 		s2_cyc_o = m0_cyc_i; +   assign 		s2_stb_o = m0_cyc_i & m0_stb_i & ssel_dec[2];    +    +   assign 		s3_adr_o = m0_adr_i; +   assign 		s3_sel_o = m0_sel_i; +   assign 		s3_dat_o = m0_dat_i; +   assign 		s3_we_o = m0_we_i; +   assign 		s3_cyc_o = m0_cyc_i; +   assign 		s3_stb_o = m0_cyc_i & m0_stb_i & ssel_dec[3];    +    +   assign 		s4_adr_o = m0_adr_i; +   assign 		s4_sel_o = m0_sel_i; +   assign 		s4_dat_o = m0_dat_i; +   assign 		s4_we_o = m0_we_i; +   assign 		s4_cyc_o = m0_cyc_i; +   assign 		s4_stb_o = m0_cyc_i & m0_stb_i & ssel_dec[4];    +    +   assign 		s5_adr_o = m0_adr_i; +   assign 		s5_sel_o = m0_sel_i; +   assign 		s5_dat_o = m0_dat_i; +   assign 		s5_we_o = m0_we_i; +   assign 		s5_cyc_o = m0_cyc_i; +   assign 		s5_stb_o = m0_cyc_i & m0_stb_i & ssel_dec[5];    +    +   assign 		s6_adr_o = m0_adr_i; +   assign 		s6_sel_o = m0_sel_i; +   assign 		s6_dat_o = m0_dat_i; +   assign 		s6_we_o = m0_we_i; +   assign 		s6_cyc_o = m0_cyc_i; +   assign 		s6_stb_o = m0_cyc_i & m0_stb_i & ssel_dec[6];    +    +   assign 		s7_adr_o = m0_adr_i; +   assign 		s7_sel_o = m0_sel_i; +   assign 		s7_dat_o = m0_dat_i; +   assign 		s7_we_o = m0_we_i; +   assign 		s7_cyc_o = m0_cyc_i; +   assign 		s7_stb_o = m0_cyc_i & m0_stb_i & ssel_dec[7];    +    +   assign 		s8_adr_o = m0_adr_i; +   assign 		s8_sel_o = m0_sel_i; +   assign 		s8_dat_o = m0_dat_i; +   assign 		s8_we_o = m0_we_i; +   assign 		s8_cyc_o = m0_cyc_i; +   assign 		s8_stb_o = m0_cyc_i & m0_stb_i & ssel_dec[8];    +    +   assign 		s9_adr_o = m0_adr_i; +   assign 		s9_sel_o = m0_sel_i; +   assign 		s9_dat_o = m0_dat_i; +   assign 		s9_we_o = m0_we_i; +   assign 		s9_cyc_o = m0_cyc_i; +   assign 		s9_stb_o = m0_cyc_i & m0_stb_i & ssel_dec[9];    +    +   assign 		sa_adr_o = m0_adr_i; +   assign 		sa_sel_o = m0_sel_i; +   assign 		sa_dat_o = m0_dat_i; +   assign 		sa_we_o = m0_we_i; +   assign 		sa_cyc_o = m0_cyc_i; +   assign 		sa_stb_o = m0_cyc_i & m0_stb_i & ssel_dec[10];    +    +   assign 		sb_adr_o = m0_adr_i; +   assign 		sb_sel_o = m0_sel_i; +   assign 		sb_dat_o = m0_dat_i; +   assign 		sb_we_o = m0_we_i; +   assign 		sb_cyc_o = m0_cyc_i; +   assign 		sb_stb_o = m0_cyc_i & m0_stb_i & ssel_dec[11];    +    +   assign 		sc_adr_o = m0_adr_i; +   assign 		sc_sel_o = m0_sel_i; +   assign 		sc_dat_o = m0_dat_i; +   assign 		sc_we_o = m0_we_i; +   assign 		sc_cyc_o = m0_cyc_i; +   assign 		sc_stb_o = m0_cyc_i & m0_stb_i & ssel_dec[12];    +    +   assign 		sd_adr_o = m0_adr_i; +   assign 		sd_sel_o = m0_sel_i; +   assign 		sd_dat_o = m0_dat_i; +   assign 		sd_we_o = m0_we_i; +   assign 		sd_cyc_o = m0_cyc_i; +   assign 		sd_stb_o = m0_cyc_i & m0_stb_i & ssel_dec[13];    +    +   assign 		se_adr_o = m0_adr_i; +   assign 		se_sel_o = m0_sel_i; +   assign 		se_dat_o = m0_dat_i; +   assign 		se_we_o = m0_we_i; +   assign 		se_cyc_o = m0_cyc_i; +   assign 		se_stb_o = m0_cyc_i & m0_stb_i & ssel_dec[14];    +    +   assign 		sf_adr_o = m0_adr_i; +   assign 		sf_sel_o = m0_sel_i; +   assign 		sf_dat_o = m0_dat_i; +   assign 		sf_we_o = m0_we_i; +   assign 		sf_cyc_o = m0_cyc_i; +   assign 		sf_stb_o = m0_cyc_i & m0_stb_i & ssel_dec[15];    +    +   // Address decode logic +   // WARNING -- must make sure these are mutually exclusive! + + +   assign 		ssel_dec[0] = ~|((m0_adr_i[aw-1:aw-decode_w] ^ s0_addr) & s0_mask); +   assign 		ssel_dec[1] = ~|((m0_adr_i[aw-1:aw-decode_w] ^ s1_addr) & s1_mask); +   assign 		ssel_dec[2] = ~|((m0_adr_i[aw-1:aw-decode_w] ^ s2_addr) & s2_mask); +   assign 		ssel_dec[3] = ~|((m0_adr_i[aw-1:aw-decode_w] ^ s3_addr) & s3_mask); +   assign 		ssel_dec[4] = ~|((m0_adr_i[aw-1:aw-decode_w] ^ s4_addr) & s4_mask); +   assign 		ssel_dec[5] = ~|((m0_adr_i[aw-1:aw-decode_w] ^ s5_addr) & s5_mask); +   assign 		ssel_dec[6] = ~|((m0_adr_i[aw-1:aw-decode_w] ^ s6_addr) & s6_mask); +   assign 		ssel_dec[7] = ~|((m0_adr_i[aw-1:aw-decode_w] ^ s7_addr) & s7_mask); +   assign 		ssel_dec[8] = ~|((m0_adr_i[aw-1:aw-decode_w] ^ s8_addr) & s8_mask); +   assign 		ssel_dec[9] = ~|((m0_adr_i[aw-1:aw-decode_w] ^ s9_addr) & s9_mask); +   assign 		ssel_dec[10] = ~|((m0_adr_i[aw-1:aw-decode_w] ^ sa_addr) & sa_mask); +   assign 		ssel_dec[11] = ~|((m0_adr_i[aw-1:aw-decode_w] ^ sb_addr) & sb_mask); +   assign 		ssel_dec[12] = ~|((m0_adr_i[aw-1:aw-decode_w] ^ sc_addr) & sc_mask); +   assign 		ssel_dec[13] = ~|((m0_adr_i[aw-1:aw-decode_w] ^ sd_addr) & sd_mask); +   assign 		ssel_dec[14] = ~|((m0_adr_i[aw-1:aw-decode_w] ^ se_addr) & se_mask); +   assign 		ssel_dec[15] = ~|((m0_adr_i[aw-1:aw-decode_w] ^ sf_addr) & sf_mask); + +/* +   assign 		ssel_dec[0] = (m0_adr_i[aw -1 : aw - decode_w ] == s0_addr); +   assign 		ssel_dec[1] = (m0_adr_i[aw -1 : aw - decode_w ] == s1_addr); +   assign 		ssel_dec[2] = (m0_adr_i[aw -1 : aw - decode_w ] == s2_addr); +   assign 		ssel_dec[3] = (m0_adr_i[aw -1 : aw - decode_w ] == s3_addr); +   assign 		ssel_dec[4] = (m0_adr_i[aw -1 : aw - decode_w ] == s4_addr); +   assign 		ssel_dec[5] = (m0_adr_i[aw -1 : aw - decode_w ] == s5_addr); +   assign 		ssel_dec[6] = (m0_adr_i[aw -1 : aw - decode_w ] == s6_addr); +   assign 		ssel_dec[7] = (m0_adr_i[aw -1 : aw - decode_w ] == s7_addr); +   assign 		ssel_dec[8] = (m0_adr_i[aw -1 : aw - decode_w ] == s8_addr); +   assign 		ssel_dec[9] = (m0_adr_i[aw -1 : aw - decode_w ] == s9_addr); +   assign 		ssel_dec[10] = (m0_adr_i[aw -1 : aw - decode_w ] == sa_addr); +   assign 		ssel_dec[11] = (m0_adr_i[aw -1 : aw - decode_w ] == sb_addr); +   assign 		ssel_dec[12] = (m0_adr_i[aw -1 : aw - decode_w ] == sc_addr); +   assign 		ssel_dec[13] = (m0_adr_i[aw -1 : aw - decode_w ] == sd_addr); +   assign 		ssel_dec[14] = (m0_adr_i[aw -1 : aw - decode_w ] == se_addr); +   assign 		ssel_dec[15] = (m0_adr_i[aw -1 : aw - decode_w ] == sf_addr); + */  +endmodule // wb_1master  | 
