diff options
Diffstat (limited to 'usrp2/gpmc')
| -rw-r--r-- | usrp2/gpmc/.gitignore | 2 | ||||
| -rw-r--r-- | usrp2/gpmc/burst_data_write.txt | 16 | ||||
| -rw-r--r-- | usrp2/gpmc/dbsm.v | 80 | ||||
| -rw-r--r-- | usrp2/gpmc/edge_sync.v | 22 | ||||
| -rw-r--r-- | usrp2/gpmc/fifo_to_gpmc_async.v | 38 | ||||
| -rw-r--r-- | usrp2/gpmc/fifo_to_gpmc_sync.v | 26 | ||||
| -rw-r--r-- | usrp2/gpmc/fifo_watcher.v | 54 | ||||
| -rw-r--r-- | usrp2/gpmc/gpmc_async.v | 127 | ||||
| -rw-r--r-- | usrp2/gpmc/gpmc_sync.v | 108 | ||||
| -rw-r--r-- | usrp2/gpmc/gpmc_to_fifo_async.v | 68 | ||||
| -rw-r--r-- | usrp2/gpmc/gpmc_to_fifo_sync.v | 57 | ||||
| -rw-r--r-- | usrp2/gpmc/gpmc_wb.v | 57 | ||||
| -rwxr-xr-x | usrp2/gpmc/make_timing_diag | 6 | ||||
| -rw-r--r-- | usrp2/gpmc/ram_to_fifo.v | 46 | ||||
| -rw-r--r-- | usrp2/gpmc/single_data_read.txt | 12 | ||||
| -rw-r--r-- | usrp2/gpmc/single_data_write.txt | 10 | 
16 files changed, 729 insertions, 0 deletions
| diff --git a/usrp2/gpmc/.gitignore b/usrp2/gpmc/.gitignore new file mode 100644 index 000000000..3e14fa4f7 --- /dev/null +++ b/usrp2/gpmc/.gitignore @@ -0,0 +1,2 @@ +*.gif + diff --git a/usrp2/gpmc/burst_data_write.txt b/usrp2/gpmc/burst_data_write.txt new file mode 100644 index 000000000..3b5dfc785 --- /dev/null +++ b/usrp2/gpmc/burst_data_write.txt @@ -0,0 +1,16 @@ +# OMAP burst writes to FPGA + +CLK=0,nWE=1,nCS=1,nOE=1,DATA=Z. +CLK=1. +CLK=0,nWE=0,nCS=0,DATA=WR_DATA1. +CLK=1. +CLK=0,nWE=0,nCS=0,DATA=WR_DATA2. +CLK=1. +CLK=0,nWE=0,nCS=0,DATA=WR_DATA3. +CLK=1. +CLK=0,nWE=0,nCS=0,DATA=WR_DATA4. +CLK=1. +CLK=0,nWE=1,nCS=1,DATA=Z. +CLK=1. + + diff --git a/usrp2/gpmc/dbsm.v b/usrp2/gpmc/dbsm.v new file mode 100644 index 000000000..530af7205 --- /dev/null +++ b/usrp2/gpmc/dbsm.v @@ -0,0 +1,80 @@ + +module bsm +  (input clk, input reset, input clear, +   input write_done, +   input read_done, +   output readable, +   output writeable); + +   reg 	  state; +   localparam ST_WRITEABLE = 0; +   localparam ST_READABLE = 1; +    +   always @(posedge clk) +     if(reset | clear) +       state <= ST_WRITEABLE; +     else +       case(state) +	 ST_WRITEABLE : +	   if(write_done) +	     state <= ST_READABLE; +	 ST_READABLE : +	   if(read_done) +	     state <= ST_WRITEABLE; +       endcase // case (state) + +   assign readable = (state == ST_READABLE); +   assign writeable = (state == ST_WRITEABLE); +    +endmodule // bsm + +module dbsm +  (input clk, input reset, input clear, +   output reg read_sel, output read_ready, input read_done, +   output reg write_sel, output write_ready, input write_done); + +   localparam NUM_BUFS = 2; + +   wire       [NUM_BUFS-1:0] readable, writeable, read_done_buf, write_done_buf; +    +   // Two of these buffer state machines +   genvar     i; +   generate +      for(i=0;i<NUM_BUFS;i=i+1) +	begin : BSMS +	   bsm bsm(.clk(clk), .reset(reset), .clear(clear), +		   .write_done((write_sel == i) & write_done), +		   .read_done((read_sel == i) & read_done), +		   .readable(readable[i]), .writeable(writeable[i])); +	end +   endgenerate +    +   reg 	 full; +    +   always @(posedge clk) +     if(reset | clear) +       begin +	  write_sel <= 0; +	  full <= 0; +       end +     else +       if(write_done & writeable[write_sel]) +	 if(write_sel ==(NUM_BUFS-1)) +	   write_sel <= 0; +	 else +	   write_sel <= write_sel + 1; +    +   always @(posedge clk) +     if(reset | clear) +       read_sel <= 0; +     else +       if(read_done & readable[read_sel]) +	 if(read_sel==(NUM_BUFS-1)) +	   read_sel <= 0; +	 else +	   read_sel <= read_sel + 1; +           +   assign write_ready = writeable[write_sel]; +   assign read_ready = readable[read_sel]; + +endmodule // dbsm diff --git a/usrp2/gpmc/edge_sync.v b/usrp2/gpmc/edge_sync.v new file mode 100644 index 000000000..5d9417c08 --- /dev/null +++ b/usrp2/gpmc/edge_sync.v @@ -0,0 +1,22 @@ + + +module edge_sync +  #(parameter POSEDGE = 1) +   (input clk, +    input rst, +    input sig, +    output trig); +    +   reg [1:0] delay; +    +   always @(posedge clk) +     if(rst) +       delay <= 2'b00; +     else +       delay <= {delay[0],sig}; +    +   assign trig = POSEDGE ? (delay==2'b01) : (delay==2'b10); +    +endmodule // edge_sync + + diff --git a/usrp2/gpmc/fifo_to_gpmc_async.v b/usrp2/gpmc/fifo_to_gpmc_async.v new file mode 100644 index 000000000..5ac8b19bd --- /dev/null +++ b/usrp2/gpmc/fifo_to_gpmc_async.v @@ -0,0 +1,38 @@ + +// Assumes an asynchronous GPMC cycle +//   If a packet bigger or smaller than we are told is sent, behavior is undefined. +//   If dst_rdy_i is low when we get data, behavior is undefined and we signal bus error. +//   If there is a bus error, we should be reset + +module fifo_to_gpmc_async +  (input clk, input reset, input clear, +   input [17:0] data_i, input src_rdy_i, output dst_rdy_o, +   output [15:0] EM_D, input EM_NCS, input EM_NOE, +   input [15:0] frame_len); + +   // Synchronize the async control signals +   reg [1:0] 	cs_del, oe_del; +   reg [15:0] 	counter; +    +   always @(posedge clk) +     if(reset) +       begin +	  cs_del <= 2'b11; +	  oe_del <= 2'b11; +       end +     else +       begin +	  cs_del <= { cs_del[0], EM_NCS }; +	  oe_del <= { oe_del[0], EM_NOE }; +       end + +   //wire do_read = (~cs_del[0] & (oe_del == 2'b10)); +   wire do_read = (~cs_del[1] & (oe_del == 2'b01));  // change output on trailing edge +   wire first_read = (counter == 0); +   wire last_read = ((counter+1) == frame_len); + +   assign EM_D = data_i[15:0]; + +   assign dst_rdy_o = do_read; + +endmodule // fifo_to_gpmc_async diff --git a/usrp2/gpmc/fifo_to_gpmc_sync.v b/usrp2/gpmc/fifo_to_gpmc_sync.v new file mode 100644 index 000000000..ef59d7137 --- /dev/null +++ b/usrp2/gpmc/fifo_to_gpmc_sync.v @@ -0,0 +1,26 @@ + +// Assumes a GPMC cycle with GPMC clock, as in the timing diagrams +//   If a packet bigger or smaller than we are told is sent, behavior is undefined. +//   If dst_rdy_i is low when we get data, behavior is undefined and we signal bus error. +//   If there is a bus error, we should be reset + +module fifo_to_gpmc_sync +  (input arst, +   input [17:0] data_i, input src_rdy_i, output dst_rdy_o, +   input EM_CLK, output [15:0] EM_D, input EM_NCS, input EM_NOE, +   output fifo_ready,  +   output reg bus_error); + +   assign EM_D = data_i[15:0]; +   wire       read_access = ~EM_NCS & ~EM_NOE; + +   assign dst_rdy_o = read_access; + +   always @(posedge EM_CLK or posedge arst) +     if(arst) +       bus_error <= 0; +     else if(dst_rdy_o & ~src_rdy_i) +       bus_error <= 1; +    + +endmodule // fifo_to_gpmc_sync diff --git a/usrp2/gpmc/fifo_watcher.v b/usrp2/gpmc/fifo_watcher.v new file mode 100644 index 000000000..4bba142b0 --- /dev/null +++ b/usrp2/gpmc/fifo_watcher.v @@ -0,0 +1,54 @@ + + +module fifo_watcher +  (input clk, input reset, input clear, +   input src_rdy1, input dst_rdy1, input sof1, input eof1, +   input src_rdy2, input dst_rdy2, input sof2, input eof2, +   output reg have_packet, output [15:0] length, output reg bus_error); + +   wire   write = src_rdy1 & dst_rdy1 & eof1; +   wire   read = src_rdy2 & dst_rdy2 & eof2; +   wire   have_packet_int; +   reg [15:0] counter; +   wire [4:0] pkt_count; +    +   fifo_short #(.WIDTH(16)) frame_lengths +     (.clk(clk), .reset(reset), .clear(clear), +      .datain(counter), .src_rdy_i(write), .dst_rdy_o(), +      .dataout(length), .src_rdy_o(have_packet_int), .dst_rdy_i(read), +      .occupied(pkt_count), .space()); + +   always @(posedge clk) +     if(reset | clear) +       counter <= 1;   // Start at 1 +     else if(src_rdy1 & dst_rdy1) +       if(eof1) +	 counter <= 1; +       else +	 counter <= counter + 1; + +   always @(posedge clk) +     if(reset | clear) +       bus_error <= 0; +     else if(dst_rdy2 & ~src_rdy2) +       bus_error <= 1; +     else if(read & ~have_packet_int) +       bus_error <= 1; + +   reg 	      in_packet; +   always @(posedge clk) +     if(reset | clear) +       have_packet <= 0; +     else  +       have_packet <= (have_packet_int & ~in_packet) | (pkt_count>1) ; +    +   always @(posedge clk) +     if(reset | clear) +       in_packet <= 0; +     else if(src_rdy2 & dst_rdy2) +       if(eof2) +	 in_packet <= 0; +       else +	 in_packet <= 1; +    +endmodule // fifo_watcher diff --git a/usrp2/gpmc/gpmc_async.v b/usrp2/gpmc/gpmc_async.v new file mode 100644 index 000000000..1050cef7d --- /dev/null +++ b/usrp2/gpmc/gpmc_async.v @@ -0,0 +1,127 @@ +////////////////////////////////////////////////////////////////////////////////// + +module gpmc_async +  #(parameter TXFIFOSIZE = 11, parameter RXFIFOSIZE = 11) +   (// GPMC signals +    input arst, +    input EM_CLK, inout [15:0] EM_D, input [10:1] EM_A, input [1:0] EM_NBE, +    input EM_WAIT0, input EM_NCS4, input EM_NCS6, input EM_NWE, input EM_NOE, +     +    // GPIOs for FIFO signalling +    output rx_have_data, output tx_have_space, output reg bus_error, input bus_reset, +     +    // Wishbone signals +    input wb_clk, input wb_rst, +    output [10:0] wb_adr_o, output [15:0] wb_dat_mosi, input [15:0] wb_dat_miso, +    output [1:0] wb_sel_o, output wb_cyc_o, output wb_stb_o, output wb_we_o, input wb_ack_i, +     +    // FIFO interface +    input fifo_clk, input fifo_rst, +    output [35:0] tx_data_o, output tx_src_rdy_o, input tx_dst_rdy_i, +    input [35:0] rx_data_i, input rx_src_rdy_i, output rx_dst_rdy_o, +     +    input [15:0] tx_frame_len, output [15:0] rx_frame_len, +     +    output [31:0] debug +    ); + +   wire 	  EM_output_enable = (~EM_NOE & (~EM_NCS4 | ~EM_NCS6)); +   wire [15:0] 	  EM_D_fifo; +   wire [15:0] 	  EM_D_wb; +    +   assign EM_D = ~EM_output_enable ? 16'bz : ~EM_NCS4 ? EM_D_fifo : EM_D_wb; +    +   wire 	  bus_error_tx, bus_error_rx; +    +   always @(posedge fifo_clk) +     if(fifo_rst) +       bus_error <= 0; +     else +       bus_error <= bus_error_tx | bus_error_rx; +    +   // CS4 is RAM_2PORT for DATA PATH (high-speed data) +   //    Writes go into one RAM, reads come from the other +   // CS6 is for CONTROL PATH (wishbone) + +   // //////////////////////////////////////////// +   // TX Data Path + +   wire [17:0] 	  tx18_data, tx18b_data; +   wire 	  tx18_src_rdy, tx18_dst_rdy, tx18b_src_rdy, tx18b_dst_rdy; +   wire [15:0] 	  tx_fifo_space; +   wire [35:0] 	  tx36_data; +   wire 	  tx36_src_rdy, tx36_dst_rdy; +    +   gpmc_to_fifo_async gpmc_to_fifo_async +     (.EM_D(EM_D), .EM_NBE(EM_NBE), .EM_NCS(EM_NCS4), .EM_NWE(EM_NWE), +      .fifo_clk(fifo_clk), .fifo_rst(fifo_rst), +      .data_o(tx18_data), .src_rdy_o(tx18_src_rdy), .dst_rdy_i(tx18_dst_rdy), +      .frame_len(tx_frame_len), .fifo_space(tx_fifo_space), .fifo_ready(tx_have_space), +      .bus_error(bus_error_tx) ); +    +   fifo_cascade #(.WIDTH(18), .SIZE(10)) tx_fifo +     (.clk(fifo_clk), .reset(fifo_rst), .clear(0), +      .datain(tx18_data), .src_rdy_i(tx18_src_rdy), .dst_rdy_o(tx18_dst_rdy), .space(tx_fifo_space), +      .dataout(tx18b_data), .src_rdy_o(tx18b_src_rdy), .dst_rdy_i(tx18b_dst_rdy), .occupied()); + +   fifo19_to_fifo36 #(.LE(1)) f19_to_f36   // Little endian because ARM is LE +     (.clk(fifo_clk), .reset(fifo_rst), .clear(0), +      .f19_datain({1'b0,tx18b_data}), .f19_src_rdy_i(tx18b_src_rdy), .f19_dst_rdy_o(tx18b_dst_rdy), +      .f36_dataout(tx36_data), .f36_src_rdy_o(tx36_src_rdy), .f36_dst_rdy_i(tx36_dst_rdy)); +    +   fifo_cascade #(.WIDTH(36), .SIZE(TXFIFOSIZE)) tx_fifo36 +     (.clk(wb_clk), .reset(wb_rst), .clear(0), +      .datain(tx36_data), .src_rdy_i(tx36_src_rdy), .dst_rdy_o(tx36_dst_rdy), +      .dataout(tx_data_o), .src_rdy_o(tx_src_rdy_o), .dst_rdy_i(tx_dst_rdy_i)); + +   // //////////////////////////////////////////// +   // RX Data Path +    +   wire [17:0] 	  rx18_data, rx18b_data; +   wire 	  rx18_src_rdy, rx18_dst_rdy, rx18b_src_rdy, rx18b_dst_rdy; +   wire [15:0] 	  rx_fifo_space; +   wire [35:0] 	  rx36_data; +   wire 	  rx36_src_rdy, rx36_dst_rdy; +   wire 	  dummy; +    +   fifo_cascade #(.WIDTH(36), .SIZE(RXFIFOSIZE)) rx_fifo36 +     (.clk(wb_clk), .reset(wb_rst), .clear(0), +      .datain(rx_data_i), .src_rdy_i(rx_src_rdy_i), .dst_rdy_o(rx_dst_rdy_o), +      .dataout(rx36_data), .src_rdy_o(rx36_src_rdy), .dst_rdy_i(rx36_dst_rdy)); + +   fifo36_to_fifo19 #(.LE(1)) f36_to_f19   // Little endian because ARM is LE +     (.clk(fifo_clk), .reset(fifo_rst), .clear(0), +      .f36_datain(rx36_data), .f36_src_rdy_i(rx36_src_rdy), .f36_dst_rdy_o(rx36_dst_rdy), +      .f19_dataout({dummy,rx18_data}), .f19_src_rdy_o(rx18_src_rdy), .f19_dst_rdy_i(rx18_dst_rdy) ); + +   fifo_cascade #(.WIDTH(18), .SIZE(12)) rx_fifo +     (.clk(fifo_clk), .reset(fifo_rst), .clear(0), +      .datain(rx18_data), .src_rdy_i(rx18_src_rdy), .dst_rdy_o(rx18_dst_rdy), .space(rx_fifo_space), +      .dataout(rx18b_data), .src_rdy_o(rx18b_src_rdy), .dst_rdy_i(rx18b_dst_rdy), .occupied()); + +   fifo_to_gpmc_async fifo_to_gpmc_async +     (.clk(fifo_clk), .reset(fifo_rst), .clear(0), +      .data_i(rx18b_data), .src_rdy_i(rx18b_src_rdy), .dst_rdy_o(rx18b_dst_rdy), +      .EM_D(EM_D_fifo), .EM_NCS(EM_NCS4), .EM_NOE(EM_NOE), +      .frame_len(rx_frame_len) ); + +   fifo_watcher fifo_watcher +     (.clk(fifo_clk), .reset(fifo_rst), .clear(0), +      .src_rdy1(rx18_src_rdy), .dst_rdy1(rx18_dst_rdy), .sof1(rx18_data[16]), .eof1(rx18_data[17]), +      .src_rdy2(rx18b_src_rdy), .dst_rdy2(rx18b_dst_rdy), .sof2(rx18b_data[16]), .eof2(rx18b_data[17]), +      .have_packet(rx_have_data), .length(rx_frame_len), .bus_error(bus_error_rx) ); + +   // //////////////////////////////////////////// +   // Control path on CS6 +    +   gpmc_wb gpmc_wb +     (.EM_CLK(EM_CLK), .EM_D_in(EM_D), .EM_D_out(EM_D_wb), .EM_A(EM_A), .EM_NBE(EM_NBE), +      .EM_NCS(EM_NCS6), .EM_NWE(EM_NWE), .EM_NOE(EM_NOE), +      .wb_clk(wb_clk), .wb_rst(wb_rst), +      .wb_adr_o(wb_adr_o), .wb_dat_mosi(wb_dat_mosi), .wb_dat_miso(wb_dat_miso), +      .wb_sel_o(wb_sel_o), .wb_cyc_o(wb_cyc_o), .wb_stb_o(wb_stb_o), .wb_we_o(wb_we_o), +      .wb_ack_i(wb_ack_i) ); +    +   assign debug = 0; +    +endmodule // gpmc_async diff --git a/usrp2/gpmc/gpmc_sync.v b/usrp2/gpmc/gpmc_sync.v new file mode 100644 index 000000000..61c54a793 --- /dev/null +++ b/usrp2/gpmc/gpmc_sync.v @@ -0,0 +1,108 @@ +////////////////////////////////////////////////////////////////////////////////// + +module gpmc_sync +  (// GPMC signals +   input arst, +   input EM_CLK, inout [15:0] EM_D, input [10:1] EM_A, input [1:0] EM_NBE, +   input EM_WAIT0, input EM_NCS4, input EM_NCS6, input EM_NWE, input EM_NOE, +    +   // GPIOs for FIFO signalling +   output rx_have_data, output tx_have_space, output bus_error, input bus_reset, +    +   // Wishbone signals +   input wb_clk, input wb_rst, +   output [10:0] wb_adr_o, output [15:0] wb_dat_mosi, input [15:0] wb_dat_miso, +   output [1:0] wb_sel_o, output wb_cyc_o, output wb_stb_o, output wb_we_o, input wb_ack_i, + +   // FIFO interface +   input fifo_clk, input fifo_rst, +   output [35:0] tx_data_o, output tx_src_rdy_o, input tx_dst_rdy_i, +   input [35:0] rx_data_i, input rx_src_rdy_i, output rx_dst_rdy_o, + +   output [31:0] debug +   ); + +   wire 	EM_output_enable = (~EM_NOE & (~EM_NCS4 | ~EM_NCS6)); +   wire [15:0] 	EM_D_fifo; +   wire [15:0] 	EM_D_wb; + +   assign EM_D = ~EM_output_enable ? 16'bz : ~EM_NCS4 ? EM_D_fifo : EM_D_wb; + +   wire 	bus_error_tx, bus_error_rx; +   assign bus_error = bus_error_tx | bus_error_rx; +    +   // CS4 is RAM_2PORT for DATA PATH (high-speed data) +   //    Writes go into one RAM, reads come from the other +   // CS6 is for CONTROL PATH (wishbone) + +   // //////////////////////////////////////////// +   // TX Data Path + +   wire [17:0] 	tx18_data, tx18b_data; +   wire 	tx18_src_rdy, tx18_dst_rdy, tx18b_src_rdy, tx18b_dst_rdy; +   wire [15:0] 	tx_fifo_space, tx_frame_len; +    +   assign tx_frame_len = 10; +    +   gpmc_to_fifo_sync gpmc_to_fifo_sync +     (.arst(arst), +      .EM_CLK(EM_CLK), .EM_D(EM_D), .EM_NBE(EM_NBE), .EM_NCS(EM_NCS4), .EM_NWE(EM_NWE), +      .data_o(tx18_data), .src_rdy_o(tx18_src_rdy), .dst_rdy_i(tx18_dst_rdy), +      .frame_len(tx_frame_len), .fifo_space(tx_fifo_space), .fifo_ready(tx_have_space), +      .bus_error(bus_error_tx) ); +    +   fifo_2clock_cascade #(.WIDTH(18), .SIZE(4)) tx_fifo +     (.wclk(EM_CLK), .datain(tx18_data),  +      .src_rdy_i(tx18_src_rdy), .dst_rdy_o(tx18_dst_rdy), .space(tx_fifo_space), +      .rclk(fifo_clk), .dataout(tx18b_data),  +      .src_rdy_o(tx18b_src_rdy), .dst_rdy_i(tx18b_dst_rdy), .occupied(), .arst(arst)); + +   fifo19_to_fifo36 #(.LE(1)) f19_to_f36   // Little endian because ARM is LE +     (.clk(fifo_clk), .reset(fifo_rst), .clear(0), +      .f19_datain({1'b0,tx18b_data}), .f19_src_rdy_i(tx18b_src_rdy), .f19_dst_rdy_o(tx18b_dst_rdy), +      .f36_dataout(tx_data_o), .f36_src_rdy_o(tx_src_rdy_o), .f36_dst_rdy_i(tx_dst_rdy_i)); +    +   // //////////////////////////////////////////// +   // RX Data Path + +   wire [17:0] 	rx18_data, rx18b_data; +   wire 	rx18_src_rdy, rx18_dst_rdy, rx18b_src_rdy, rx18b_dst_rdy; +   wire [15:0] 	rx_fifo_space, rx_frame_len; +   wire 	dummy; +    +   fifo36_to_fifo19 #(.LE(1)) f36_to_f19   // Little endian because ARM is LE +     (.clk(fifo_clk), .reset(fifo_rst), .clear(0), +      .f36_datain(rx_data_i), .f36_src_rdy_i(rx_src_rdy_i), .f36_dst_rdy_o(rx_dst_rdy_o), +      .f19_dataout({dummy,rx18_data}), .f19_src_rdy_o(rx18_src_rdy), .f19_dst_rdy_i(rx18_dst_rdy) ); + +   fifo_2clock_cascade #(.WIDTH(18), .SIZE(10)) rx_fifo +     (.wclk(fifo_clk), .datain(rx18_data),  +      .src_rdy_i(rx18_src_rdy), .dst_rdy_o(rx18_dst_rdy), .space(rx_fifo_space), +      .rclk(EM_CLK), .dataout(rx18b_data),  +      .src_rdy_o(rx18b_src_rdy), .dst_rdy_i(rx18b_dst_rdy), .occupied(), .arst(arst)); + +   fifo_to_gpmc_sync fifo_to_gpmc_sync +     (.arst(arst), +      .data_i(rx18b_data), .src_rdy_i(rx18b_src_rdy), .dst_rdy_o(rx18b_dst_rdy), +      .EM_CLK(EM_CLK), .EM_D(EM_D_fifo), .EM_NCS(EM_NCS4), .EM_NOE(EM_NOE), +      .fifo_ready(rx_have_data) ); + +   fifo_watcher fifo_watcher +     (.clk(fifo_clk), .reset(fifo_rst), .clear(0), +      .src_rdy(rx18_src_rdy), .dst_rdy(rx18_dst_rdy), .sof(rx18_data[16]), .eof(rx18_data[17]), +      .have_packet(), .length(), .next() ); +    +   // //////////////////////////////////////////// +   // Control path on CS6 +    +   gpmc_wb gpmc_wb +     (.EM_CLK(EM_CLK), .EM_D_in(EM_D), .EM_D_out(EM_D_wb), .EM_A(EM_A), .EM_NBE(EM_NBE), +      .EM_NCS(EM_NCS6), .EM_NWE(EM_NWE), .EM_NOE(EM_NOE), +      .wb_clk(wb_clk), .wb_rst(wb_rst), +      .wb_adr_o(wb_adr_o), .wb_dat_mosi(wb_dat_mosi), .wb_dat_miso(wb_dat_miso), +      .wb_sel_o(wb_sel_o), .wb_cyc_o(wb_cyc_o), .wb_stb_o(wb_stb_o), .wb_we_o(wb_we_o), +      .wb_ack_i(wb_ack_i) ); +    +      assign debug = 0; +    +endmodule // gpmc_sync diff --git a/usrp2/gpmc/gpmc_to_fifo_async.v b/usrp2/gpmc/gpmc_to_fifo_async.v new file mode 100644 index 000000000..3d29745a2 --- /dev/null +++ b/usrp2/gpmc/gpmc_to_fifo_async.v @@ -0,0 +1,68 @@ + +module gpmc_to_fifo_async +  (input [15:0] EM_D, input [1:0] EM_NBE, input EM_NCS, input EM_NWE, + +   input fifo_clk, input fifo_rst, +   output reg [17:0] data_o, output reg src_rdy_o, input dst_rdy_i, + +   input [15:0] frame_len, input [15:0] fifo_space, output reg fifo_ready, +   output reg bus_error ); + +   reg [15:0] counter; +   // Synchronize the async control signals +   reg [1:0] 	cs_del, we_del; +   always @(posedge fifo_clk) +     if(fifo_rst) +       begin +	  cs_del <= 2'b11; +	  we_del <= 2'b11; +       end +     else +       begin +	  cs_del <= { cs_del[0], EM_NCS }; +	  we_del <= { we_del[0], EM_NWE }; +       end + +   wire do_write = (~cs_del[0] & (we_del == 2'b10)); +   wire first_write = (counter == 0); +   wire last_write = ((counter+1) == frame_len); + +   always @(posedge fifo_clk) +     if(do_write) +       begin +	  data_o[15:0] <= EM_D; +	  data_o[16] <= first_write; +	  data_o[17] <= last_write; +	  //  no byte writes data_o[18] <= |EM_NBE;  // mark half full if either is not enabled  FIXME +       end + +   always @(posedge fifo_clk) +     if(fifo_rst) +       src_rdy_o <= 0; +     else if(do_write) +       src_rdy_o <= 1; +     else +       src_rdy_o <= 0;    // Assume it was taken + +   always @(posedge fifo_clk) +     if(fifo_rst) +       counter <= 0; +     else if(do_write) +       if(last_write) +	 counter <= 0; +       else +	 counter <= counter + 1; + +   always @(posedge fifo_clk) +     if(fifo_rst) +       fifo_ready <= 0; +     else +       fifo_ready <= /* first_write & */ (fifo_space > 16'd1023); + +   always @(posedge fifo_clk) +     if(fifo_rst) +       bus_error <= 0; +     else if(src_rdy_o & ~dst_rdy_i) +       bus_error <= 1; +    +endmodule // gpmc_to_fifo_async diff --git a/usrp2/gpmc/gpmc_to_fifo_sync.v b/usrp2/gpmc/gpmc_to_fifo_sync.v new file mode 100644 index 000000000..688de0e17 --- /dev/null +++ b/usrp2/gpmc/gpmc_to_fifo_sync.v @@ -0,0 +1,57 @@ + +// Assumes a GPMC cycle with GPMC clock, as in the timing diagrams +//   If a packet bigger or smaller than we are told is sent, behavior is undefined. +//   If dst_rdy_i is low when we get data, behavior is undefined and we signal bus error. +//   If there is a bus error, we should be reset + +module gpmc_to_fifo_sync +  (input arst, +   input EM_CLK, input [15:0] EM_D, input [1:0] EM_NBE, +   input EM_NCS, input EM_NWE, +   output reg [17:0] data_o, output reg src_rdy_o, input dst_rdy_i, +   input [15:0] frame_len, input [15:0] fifo_space, output fifo_ready,  +   output reg bus_error); +    +   reg [10:0] 	counter; +   wire 	first_write = (counter == 0); +   wire 	last_write = ((counter+1) == frame_len); +   wire 	do_write = ~EM_NCS & ~EM_NWE; +    +   always @(posedge EM_CLK or posedge arst) +     if(arst) +       data_o <= 0; +     else if(do_write) +       begin +	  data_o[15:0] <= EM_D; +	  data_o[16] <= first_write; +	  data_o[17] <= last_write; +	  //  no byte writes data_o[18] <= |EM_NBE;  // mark half full if either is not enabled  FIXME +       end + +   always @(posedge EM_CLK or posedge arst) +     if(arst) +       src_rdy_o <= 0; +     else if(do_write & ~bus_error)  // Don't put junk in if there is a bus error +       src_rdy_o <= 1; +     else +       src_rdy_o <= 0;    // Assume it was taken, ignore dst_rdy_i + +   always @(posedge EM_CLK or posedge arst) +     if(arst) +       counter <= 0; +     else if(do_write) +       if(last_write) +	 counter <= 0; +       else +	 counter <= counter + 1; + +   assign fifo_ready = first_write & (fifo_space > frame_len); +    +   always @(posedge EM_CLK or posedge arst) +     if(arst) +       bus_error <= 0; +     else if(src_rdy_o & ~dst_rdy_i) +       bus_error <= 1; +   // must be reset to make the error go away + +endmodule // gpmc_to_fifo_sync diff --git a/usrp2/gpmc/gpmc_wb.v b/usrp2/gpmc/gpmc_wb.v new file mode 100644 index 000000000..db6fbc6e9 --- /dev/null +++ b/usrp2/gpmc/gpmc_wb.v @@ -0,0 +1,57 @@ + + +module gpmc_wb +  (input EM_CLK, input [15:0] EM_D_in, output [15:0] EM_D_out, input [10:1] EM_A, input [1:0] EM_NBE, +   input EM_NCS, input EM_NWE, input EM_NOE, + +   input wb_clk, input wb_rst, +   output reg [10:0] wb_adr_o, output reg [15:0] wb_dat_mosi, input [15:0] wb_dat_miso, +   output reg [1:0] wb_sel_o, output wb_cyc_o, output reg wb_stb_o, output reg wb_we_o, input wb_ack_i); +    +   // //////////////////////////////////////////// +   // Control Path, Wishbone bus bridge (wb master) +   reg [1:0] 	cs_del, we_del, oe_del; + +   // Synchronize the async control signals +   always @(posedge wb_clk) +     begin +	cs_del <= { cs_del[0], EM_NCS }; +	we_del <= { we_del[0], EM_NWE }; +	oe_del <= { oe_del[0], EM_NOE }; +     end + +   always @(posedge wb_clk) +     if(cs_del == 2'b10)  // Falling Edge +       wb_adr_o <= { EM_A, 1'b0 }; + +   always @(posedge wb_clk) +     if(we_del == 2'b10)  // Falling Edge +       begin +	  wb_dat_mosi <= EM_D_in; +	  wb_sel_o <= ~EM_NBE; +       end + +   reg [15:0] EM_D_hold; +    +   always @(posedge wb_clk) +     if(wb_ack_i) +       EM_D_hold <= wb_dat_miso; + +   assign EM_D_out = wb_ack_i ? wb_dat_miso : EM_D_hold; +    +   assign wb_cyc_o = wb_stb_o; + +   always @(posedge wb_clk) +     if(~cs_del[0] & (we_del == 2'b10) ) +       wb_we_o <= 1; +     else if(wb_ack_i)  // Turn off we when done.  Could also use we_del[0], others... +       wb_we_o <= 0; + +   // FIXME should this look at cs_del[1]? +   always @(posedge wb_clk) +     if(~cs_del[0] & ((we_del == 2'b10) | (oe_del == 2'b10))) +       wb_stb_o <= 1; +     else if(wb_ack_i) +       wb_stb_o <= 0; +    +endmodule // gpmc_wb diff --git a/usrp2/gpmc/make_timing_diag b/usrp2/gpmc/make_timing_diag new file mode 100755 index 000000000..03166ad35 --- /dev/null +++ b/usrp2/gpmc/make_timing_diag @@ -0,0 +1,6 @@ +#!/bin/sh +drawtiming -o single_data_write.gif single_data_write.txt +drawtiming -o single_data_read.gif single_data_read.txt +drawtiming -o burst_data_write.gif burst_data_write.txt +#drawtiming -o burst_data_read.gif burst_data_read.txt + diff --git a/usrp2/gpmc/ram_to_fifo.v b/usrp2/gpmc/ram_to_fifo.v new file mode 100644 index 000000000..8549dcc35 --- /dev/null +++ b/usrp2/gpmc/ram_to_fifo.v @@ -0,0 +1,46 @@ + + +module ram_to_fifo +  (input clk, input reset, +   input [10:0] read_length,  // From the dbsm (?) +   output read_en, output reg [8:0] read_addr, input [31:0] read_data, input read_ready, output read_done, +   output [35:0] data_o, output src_rdy_o, input dst_rdy_i); + +   // read_length/2 = number of 32 bit lines, numbered 0 through read_length/2-1 +   wire [8:0] 	 last_line = (read_length[10:1]-1);  + +   reg 		 read_phase, sop; + +   assign read_en = (read_phase == 0) | dst_rdy_i; +   assign src_rdy_o = (read_phase == 1); +    +   always @(posedge clk) +     if(reset) +       begin +	  read_addr <= 0; +	  read_phase <= 0; +	  sop <= 1; +       end +     else +       if(read_phase == 0) +	 begin +	    read_addr <= read_ready; +	    read_phase <= read_ready; +	 end +       else if(dst_rdy_i) +	 begin +	    sop <= 0; +	    if(read_addr == last_line) +	      begin +		 read_addr <= 0; +		 read_phase <= 0; +	      end +	    else +	      read_addr <= read_addr + 1; +	 end +    +   assign read_done = (read_phase == 1) & (read_addr == last_line) & dst_rdy_i; +   wire eop = (read_addr == last_line); +   assign data_o = { 2'b00, eop, sop, read_data }; +    +endmodule // ram_to_fifo diff --git a/usrp2/gpmc/single_data_read.txt b/usrp2/gpmc/single_data_read.txt new file mode 100644 index 000000000..1dc0e3a78 --- /dev/null +++ b/usrp2/gpmc/single_data_read.txt @@ -0,0 +1,12 @@ +# OMAP writes to FPGA +# initialize the signals +CLK=0,nWE=1,nCS=1,nOE=1,DATA=Z. +CLK=1. +CLK=0,nOE=0,nCS=0,DATA=RD_DATA. +CLK=1. +CLK=0. +CLK=1. +CLK=0,nOE=1,nCS=1,DATA=Z. +CLK=1. + + diff --git a/usrp2/gpmc/single_data_write.txt b/usrp2/gpmc/single_data_write.txt new file mode 100644 index 000000000..287e3e2c1 --- /dev/null +++ b/usrp2/gpmc/single_data_write.txt @@ -0,0 +1,10 @@ +# OMAP writes to FPGA +# initialize the signals +CLK=0,nWE=1,nCS=1,nOE=1,DATA=Z. +CLK=1. +CLK=0,nWE=0,nCS=0,DATA=WR_DATA. +CLK=1. +CLK=0,nWE=1,nCS=1,DATA=Z. +CLK=1. + + | 
