// LLRF support for low speed serial devices // Ming Choy and Larry Doolittle, LBNL, September 2002 - January 2003 // Address map: // host_addr Device // 000 MAX1202 // 001 MAX5742 // 010 unused // 011 ADF4001 // 100 TCN75 // 101 unused // 110 unused // 111 unused `timescale 1ns / 1ns module altsport( clk, host_addr, host_write, write_bus, read_bus, SCLK, SDIN, DOUT1202, SDA75, CS1202, CS5742, PLL_CLK, PLL_DATA, PLL_LE, PLL_MUXOUT, PLL_CE, reset); input clk, host_write, DOUT1202, reset; input [2:0] host_addr; wire [2:0] host_addr; input [15:0] write_bus; input PLL_MUXOUT; wire PLL_MUXOUT; inout SDA75; output PLL_DATA, PLL_LE, SCLK, SDIN, CS1202, CS5742, PLL_CE, PLL_CLK; output [15:0] read_bus; wire [15:0] read_bus; reg [8:0] clock_cnt; reg [5:0] cke_cnt; reg [1:0] mode; reg running; reg CS1202; reg CS5742; reg ldin; reg PLL_LE; reg muxout_sample; reg [15:0] tcn_data; reg [7:0] adf_data; reg [15:0] data; reg PLL_CE; reg [2:0] my_host_addr; reg ack_ok; assign read_bus[15:2] = data[15:2]; //for all devices, last bit is for running //for tcn, second last bit is for acknowledgement assign read_bus[1] = ack_ok; assign read_bus[0] = ~running; //assign read_bus[0] = (~my_host_addr[2])? ~running : data[0]; reg [1:0] tcn_sinout_sel; reg start; reg done; reg disable_tcn; reg disable_max; wire clk, host_write, DOUT1202; //... more to come wire reset; //wire MAX_sclk; assign MAX_sclk = (clock_cnt[3:0] == 15); wire SDIN; assign SDIN = data[15]; wire SDA75; wire cke; assign cke = (clock_cnt[3:0] == 15); wire tcn_cke; assign tcn_cke = (clock_cnt == 255); wire slow_tcn_cke; assign slow_tcn_cke = (clock_cnt == 300); wire slow; assign slow=cke&(clock_cnt[8:4]==8); wire max_slow; assign max_slow = cke & ((my_host_addr==0)? (clock_cnt[8:4]==23) : (clock_cnt[8:4]==14)); wire max_stop; assign max_stop = cke & ((my_host_addr==0)? (clock_cnt[8:4]==24) : (clock_cnt[8:4]==15)); //wire max_stop; assign max_stop=cke&(clock_cnt[8:4]==9); wire tcn_stop; assign tcn_stop=slow_tcn_cke & (cke_cnt==10) & (my_host_addr == 4); //wire tcn_sclk; assign tcn_sclk=(~running) | (cke_cnt == 0) | (clock_cnt[3]) | (addr != 4); wire stop; assign stop=cke & (cke_cnt[2:0]== 7); wire PLL_CLK; assign PLL_CLK=(clock_cnt[3] & running & my_host_addr[0] & my_host_addr[1] & ~my_host_addr[2]); wire PLL_DATA; assign PLL_DATA = (my_host_addr[1] & my_host_addr[0]) ? adf_data[7] : 1'bz; wire SCLK; //assign SCLK = (~disable_tcn & ~((cke_cnt==0) & ~mode[0]) & ((~running) | ((cke_cnt==0) & mode[0]) | (cke_cnt[2:0]==4))) | (~disable_max & (clock_cnt[3:0] == 15)); assign SCLK = disable_tcn? ((disable_max |( (my_host_addr==0)? clock_cnt[3] : ~clock_cnt[3])) & (start|done)) : ~disable_tcn & ~((cke_cnt==0) & ~mode[0] ) & running & ~clock_cnt[8] ; //tcn_sinout_sel: 0 => 0, 1 => data[15], 2 => Z //assign SDA75 = (tcn_sinout_sel == 2) ? 1'bz : ((tcn_sinout_sel == 1) ? tcn_data[15] : ((tcn_sinout_sel == 3)? 1'b1 : 1'b0)); // assign SDA75 = (tcn_sinout_sel == 2) ? 1'bz : ((tcn_sinout_sel == 1) ? tcn_data[15] : ((tcn_sinout_sel == 3)? 1'b1 : 1'b0)); wire sda75_level = (tcn_sinout_sel == 2) ? 1'b1 : ((tcn_sinout_sel == 1) ? tcn_data[15] : ((tcn_sinout_sel == 3)? 1'b1 : 1'b0)); assign SDA75 = sda75_level ? 1'bz : 1'b0 ; always @ (posedge clk or posedge reset) begin if (reset == 1) begin cke_cnt <= 0; clock_cnt <= 0; running <= 0; CS1202 <= 1; CS5742 <= 1; tcn_sinout_sel <= 3; PLL_LE <= 1; muxout_sample <= 0; disable_tcn <= 1; disable_max <= 1; done <= 0; start <= 0; ack_ok <= 1; end else begin if (((running & (mode[0] | mode[1])) | (~mode[0] & ~mode[1])) & my_host_addr[2]) clock_cnt <= clock_cnt + 1; if (host_write) begin my_host_addr <= host_addr; clock_cnt <= 0; cke_cnt <= 0; end if ((cke_cnt == 10) && slow && ~mode[0] & ~mode[1]) done <= 1; if (mode[0] | mode[1]) done <= 0; if (host_write | (stop & (my_host_addr==3)) | (max_stop & (~my_host_addr[2] & (~my_host_addr[1] | ~my_host_addr[0]))) | (tcn_stop & my_host_addr[2])) begin running <= host_write; tcn_data <= write_bus; //latch in data when write is 1 adf_data <= write_bus[15:8]; data <= write_bus; mode <= write_bus[2:1]; //start <= host_write & write_bus[0] & ~write_bus[1]; start <= host_write & write_bus[1] & ~write_bus[2]; //PLL_LE <= (host_addr !=3) | (~write_bus[0] & write_bus[1] & stop & (my_host_addr==3)); PLL_LE <= (host_addr !=3) | (~write_bus[1] & write_bus[2] & stop & (my_host_addr==3)); PLL_CE <= 1; CS1202 <= (host_addr != 0) | (max_stop & (my_host_addr==0)); CS5742 <= (host_addr != 1) | (max_stop & (my_host_addr==1)); disable_max <= (host_write & (~host_addr[0] | ~host_addr[1]))? 0 : (max_stop & (~my_host_addr[0] | ~my_host_addr[1])); //condition for updating running: //stop & ~my_host_addr[2] //tcn_stop & my_host_addr[2] end //this is for three chips: adf (addr 3), max1202 (addr 0) and max5742 (addr 1) //assume ce is from write_bus[9] if (my_host_addr[2] == 0) begin start <= 1; done <= 1; //addr[1] = 0: cs0 slows at 24 //addr[1] = 1: cs1 slows at 16 tcn_sinout_sel <= 3; muxout_sample <= PLL_MUXOUT; //if (host_write | stop) //begin //running <= host_write; //disable_max <= host_write & my_host_addr[0] & my_host_addr[1]; //end if (clock_cnt[3:0]==7) ldin<=DOUT1202; if (running & cke) begin if (my_host_addr[0] && my_host_addr[1]) adf_data <= {adf_data[6:0], muxout_sample}; else data <= {data[14:0], ldin}; cke_cnt <= cke_cnt + 1; end if (stop & (my_host_addr==3)) begin data[15:8] <= adf_data; data[0] <= 1; end //else if (~running & host_write) //data <= write_bus; //mode <= write_bus[1:0]; if (running) clock_cnt <= ((max_stop & (~my_host_addr[0] | ~my_host_addr[1])) | (stop & (my_host_addr==3))) ? 0 : clock_cnt+1; end else begin if (my_host_addr[2]) // tcn //operation: //write mode 1 (mode = 1) first 8 bits //cnt = 0: output = 0 //cnt = 1 - 8: output = data[15] //cnt = 8: output = Z //cnt = 9: listen to the ack //write mode 2 (mode = 3) second 8 bits //cnt = 0: don't do anything, but disable tcn clk. //the rest is the same as mode 1. //if ack = 0, data(15) <= 1 to acknowledge successful transaction //read mode: (mode = 0) //cnt = 0 - 7: output = Z //cnt = 8: output = 0 //cnt = 9: set data(15) <= 1 to acknowledge successful transaction //clk = 1 (turnoff) when ~(running) //clk = sclk when running //tcn_stop = '1' when cke_cnt = 9 //tcn_sinout_sel: 0 => 0, 1 => data[15], 2 => Z, 3=> 1 begin //if (host_write | tcn_stop) //begin //running <= host_write; //end //if (cke_cnt == 0) tcn_sinout_sel <= mode[0] ? 0: 2; disable_max <= 1; if (~running) begin if (~mode[0] && ~mode[1]) tcn_sinout_sel <= 0; else tcn_sinout_sel <= 3; end if ((cke_cnt == 10) && tcn_cke && (mode[0] | mode[1])) disable_tcn <= 1; if (tcn_cke & (cke_cnt==1) & (mode==1)) disable_tcn <= 0; if ((cke_cnt == 11) && (slow_tcn_cke)) begin cke_cnt <= 0; done <= 1; disable_tcn <= 1; end if (running & slow_tcn_cke) begin if (cke_cnt == 0) begin tcn_sinout_sel <= mode[0] ? 0 : 2; ack_ok <= 0; end //if (cke_cnt == 9) tcn_sinout_sel <= mode[0] ? 2 : 0; if (cke_cnt == 10) begin ack_ok <= ((~SDA75 && mode[0]) || ~mode[0]) ? 1 : 0; data[15:8] <= tcn_data[8:1]; if (~mode[0] & ~mode[1]) cke_cnt <= cke_cnt + 1; else cke_cnt <= 0; end else begin ack_ok <= 0; if (cke_cnt != 0) begin tcn_sinout_sel <=(cke_cnt ==9) ? (mode[0]? 2 : (mode[1]? 0 : 3)) : (mode[0]? 1 : 2); tcn_data <= mode[0] ? {tcn_data[14:0], 1'b1} : {tcn_data[14:0], SDA75}; disable_tcn <= 0; cke_cnt <= 0; end cke_cnt <= cke_cnt + 1; end end //else if (~running & host_write) //begin //tcn_data <= write_bus; //latch in data when write is 1 //mode <= write_bus[1:0]; //data[0] <= 0; //end end end end end endmodule