diff --git a/verilog/rtl/housekeeping_spi.v b/verilog/rtl/housekeeping_spi.v index 09336a25..ff416308 100644 --- a/verilog/rtl/housekeeping_spi.v +++ b/verilog/rtl/housekeeping_spi.v @@ -82,175 +82,280 @@ module housekeeping_spi(reset, SCK, SDI, CSB, SDO, input SCK; input SDI; input CSB; - output SDO; - output sdoenb; + output wire SDO; + output reg sdoenb; input [7:0] idata; - output [7:0] odata; - output [7:0] oaddr; - output rdstb; - output wrstb; - output pass_thru_mgmt; - output pass_thru_mgmt_delay; - output pass_thru_user; - output pass_thru_user_delay; - output pass_thru_mgmt_reset; - output pass_thru_user_reset; + output wire [7:0] odata; + output wire [7:0] oaddr; + output reg rdstb; + output reg wrstb; + output reg pass_thru_mgmt; + output reg pass_thru_mgmt_delay; + output reg pass_thru_user; + output reg pass_thru_user_delay; + output wire pass_thru_mgmt_reset; + output wire pass_thru_user_reset; + + wire hk_spi_csb; + wire hk_spi_sck; + wire hk_spi_sdi; + wire rst; reg [7:0] addr; - reg wrstb; - reg rdstb; - reg sdoenb; reg [2:0] state; reg [2:0] count; reg writemode; reg readmode; reg [2:0] fixed; - wire [7:0] odata; reg [6:0] predata; - wire [7:0] oaddr; - reg [7:0] ldata; - reg pass_thru_mgmt; - reg pass_thru_mgmt_delay; + reg [7:0] ldata; reg pre_pass_thru_mgmt; - reg pass_thru_user; - reg pass_thru_user_delay; reg pre_pass_thru_user; - wire csb_reset; + wire csb_reset; + assign hk_spi_csb = CSB; + assign hk_spi_sck = SCK; + assign hk_spi_sdi = SDI; + assign rst = reset; - assign odata = {predata, SDI}; - assign oaddr = (state == `ADDRESS) ? {addr[6:0], SDI} : addr; + assign odata = {predata, SDI}; + assign oaddr = (state == `ADDRESS) ? {addr[6:0], SDI} : addr; assign SDO = ldata[7]; assign csb_reset = CSB | reset; assign pass_thru_mgmt_reset = pass_thru_mgmt_delay | pre_pass_thru_mgmt; assign pass_thru_user_reset = pass_thru_user_delay | pre_pass_thru_user; - // Readback data is captured on the falling edge of SCK so that - // it is guaranteed valid at the next rising edge. - always @(negedge SCK or posedge csb_reset) begin + + reg [2:0] nstate; + reg [2:0] byte_cnt; + reg cmd_rd, cmd_wr, cmd_pt, cmd_pt_usr; + reg [2:0] cmd_bytes; + always @(*) begin + case(state) + `COMMAND : begin + if(count == 3'd7) begin + case({pre_pass_thru_mgmt,pre_pass_thru_user}) + 2'b00 : nstate = `ADDRESS; + 2'b10 : nstate = `MGMTPASS; + 2'b01 : nstate = `USERPASS; + default: nstate = `ADDRESS; + endcase + end + else begin + nstate = `COMMAND; + end + end + `ADDRESS : begin + if(count == 3'd7) + nstate = `DATA; + else + nstate = `ADDRESS; + end + `DATA : begin + if(count == 3'd7) + if(byte_cnt == 3'd1) //////// + nstate = `COMMAND; + else + nstate = `DATA; + end + `MGMTPASS : begin + nstate = `MGMTPASS; + end + `USERPASS : begin + nstate = `USERPASS; + end + default : begin + nstate = `DATA; + end + endcase + end + + + always @(posedge SCK or posedge csb_reset) begin if (csb_reset == 1'b1) begin - wrstb <= 1'b0; - ldata <= 8'b00000000; - sdoenb <= 1'b1; - end else begin + state <= `COMMAND; + end + else + state <= nstate; + end - // After CSB low, 1st SCK starts command - if (state == `DATA) begin - if (readmode == 1'b1) begin - sdoenb <= 1'b0; - if (count == 3'b000) begin - ldata <= idata; - end else begin - ldata <= {ldata[6:0], 1'b0}; // Shift out - end - end else begin - sdoenb <= 1'b1; - end + /*always @(posedge csb_reset)begin + if (csb_reset == 1'b1) begin + count <= 3'b000; + end + end */ + + //wire [2:0] next_count = count +1; + // incrementing bits counter at every positive edge of SCK + always @(posedge SCK or posedge csb_reset) begin // + if (csb_reset == 1'b1) begin + count <= 3'b000; + end + else if (state != `USERPASS && state != `MGMTPASS) begin + count <= count + 3'h1; + end + end + + // Getting command from SDI and storing it in a register + always @(posedge SCK or posedge csb_reset) begin + if (csb_reset == 1'b1) begin + cmd_wr <= 1'b0; + cmd_rd <= 1'b0; + cmd_bytes <= 3'b0; + pre_pass_thru_mgmt <= 1'b0; + pre_pass_thru_user <= 1'b0; + pass_thru_mgmt_delay <= 1'b0; + pass_thru_user_delay <= 1'b0; + end + else begin + if(state == `COMMAND) begin + case (count) + 0: cmd_wr <= SDI; + 1: cmd_rd <= SDI; + 2: cmd_bytes[2] <= SDI; + 3: cmd_bytes[1] <= SDI; + 4: cmd_bytes[0] <= SDI; + 5: pre_pass_thru_mgmt <= SDI; + 6: begin pre_pass_thru_user <= SDI; pass_thru_mgmt_delay <= pre_pass_thru_mgmt; end + 7: pass_thru_user_delay <= pre_pass_thru_user; + default: cmd_wr <= SDI; + endcase + end + end + end - // Apply write strobe on SCK negative edge on the next-to-last - // data bit so that it updates data on the rising edge of SCK - // on the last data bit. - - if (count == 3'b111) begin - if (writemode == 1'b1) begin + // Getting address from SDI and storing it in a register and incrementing it. + always @(posedge SCK or posedge csb_reset) begin + if (csb_reset == 1'b1) + addr <= 8'h00; // + else begin + if(state == `ADDRESS) + addr <= {addr[6:0], SDI}; + else + if(state == `DATA) + if(count == 3'd7) + addr <= addr + 1'd1; + end + end + + // Getting data to write from SDI and storing it in a register + always @(posedge SCK or posedge csb_reset) begin + if (csb_reset == 1'b1) + predata <= 7'b0000000; // + else + if(state == `DATA) predata <= {predata[5:0], SDI}; + end + + // Getting bytes count from SDI and decremnting it. + always @(posedge SCK or posedge csb_reset) begin + if (csb_reset == 1'b1) + byte_cnt <= 3'b0; + else begin + if(nstate == `ADDRESS) + byte_cnt <= cmd_bytes; + else + if(state == `DATA) begin + if(count == 3'd7) + if(byte_cnt != 0) //// + byte_cnt <= byte_cnt - 1'b1; + end + end + end + + + // Storing read data from hk in a reg and shifting it out on SDO + always @(negedge SCK or posedge csb_reset) begin //// + if (csb_reset == 1'b1) + ldata <= 8'b00000000; + else begin + if(state == `DATA) + if(cmd_rd == 1'b1) + if(count == 3'd0) + ldata <= idata; + if(count != 3'd0) + ldata <= {ldata[6:0], 1'b0}; // Shift out + end + end + + + // read strobe + always @(posedge SCK or posedge csb_reset) begin //// + if (csb_reset == 1'b1) + rdstb <= 1'b0; + else begin + if(state == `ADDRESS || state == `DATA) + if(cmd_rd == 1'b1) + rdstb <= 1'b1; + else + rdstb <= 1'b0; + end + end + + // write strobe + always @(negedge SCK or posedge csb_reset) begin //// + + if (csb_reset == 1'b1 )begin + wrstb <= 1'b0; + end else begin + if(state == `DATA) begin + if(count == 3'd7) begin + if(cmd_wr) wrstb <= 1'b1; - end - end else begin - wrstb <= 1'b0; - end + else + wrstb <= 1'b0; + end + else + wrstb <= 1'b0; - end else if (state == `MGMTPASS || state == `USERPASS) begin - wrstb <= 1'b0; - sdoenb <= 1'b0; end else begin - wrstb <= 1'b0; + wrstb <= 1'b0; + end + end + end + + // sdo enable + always @(negedge SCK or posedge csb_reset) begin //// + if (csb_reset == 1'b1) + sdoenb <= 1'b1; + else + if(state == `MGMTPASS || state == `USERPASS) begin + sdoenb <= 1'b0; + end + else if(state == `DATA) begin + if(cmd_rd == 1'b1) + sdoenb <= 1'b0; + else + sdoenb <= 1'b1; + end + else begin sdoenb <= 1'b1; - end // ! state `DATA - end // ! csb_reset - end // always @ ~SCK + end + end - always @(posedge SCK or posedge csb_reset) begin - if (csb_reset == 1'b1) begin - // Default state on reset - addr <= 8'h00; - rdstb <= 1'b0; - predata <= 7'b0000000; - state <= `COMMAND; - count <= 3'b000; - readmode <= 1'b0; - writemode <= 1'b0; - fixed <= 3'b000; - pass_thru_mgmt <= 1'b0; - pass_thru_mgmt_delay <= 1'b0; - pre_pass_thru_mgmt <= 1'b0; - pass_thru_user <= 1'b0; - pass_thru_user_delay <= 1'b0; - pre_pass_thru_user <= 1'b0; - end else begin - // After csb_reset low, 1st SCK starts command - if (state == `COMMAND) begin - rdstb <= 1'b0; - count <= count + 1; - if (count == 3'b000) begin - writemode <= SDI; - end else if (count == 3'b001) begin - readmode <= SDI; - end else if (count < 3'b101) begin - fixed <= {fixed[1:0], SDI}; - end else if (count == 3'b101) begin - pre_pass_thru_mgmt <= SDI; - end else if (count == 3'b110) begin - pre_pass_thru_user <= SDI; - pass_thru_mgmt_delay <= pre_pass_thru_mgmt; - end else if (count == 3'b111) begin - pass_thru_user_delay <= pre_pass_thru_user; - if (pre_pass_thru_mgmt == 1'b1) begin - state <= `MGMTPASS; - pre_pass_thru_mgmt <= 1'b0; - end else if (pre_pass_thru_user == 1'b1) begin - state <= `USERPASS; - pre_pass_thru_user <= 1'b0; - end else begin - state <= `ADDRESS; - end - end - end else if (state == `ADDRESS) begin - count <= count + 1; - addr <= {addr[6:0], SDI}; - if (count == 3'b111) begin - state <= `DATA; - if (readmode == 1'b1) begin - rdstb <= 1'b1; - end - end else begin - rdstb <= 1'b0; - end + always @(posedge SCK or posedge csb_reset) begin + if(csb_reset == 1'b1) begin + pass_thru_mgmt <= 1'b0; + end + else + if(state == `MGMTPASS) + pass_thru_mgmt <= 1'b1; + end + + always @(posedge SCK or posedge csb_reset) begin + if (csb_reset == 1'b1) begin + pass_thru_user <= 1'b0; + end + else + if(state == `USERPASS) + pass_thru_user <= 1'b1; + end - end else if (state == `DATA) begin - predata <= {predata[6:0], SDI}; - count <= count + 1; - if (count == 3'b111) begin - if (fixed == 3'b001) begin - state <= `COMMAND; - end else if (fixed != 3'b000) begin - fixed <= fixed - 1; - addr <= addr + 1; // Auto increment address (fixed) - end else begin - addr <= addr + 1; // Auto increment address (streaming) - end - if (readmode == 1'b1) begin - rdstb <= 1'b1; - end - end else begin - rdstb <= 1'b0; - end - end else if (state == `MGMTPASS) begin - pass_thru_mgmt <= 1'b1; - end else if (state == `USERPASS) begin - pass_thru_user <= 1'b1; - end // ! state `DATA | `MGMTPASS | `USERPASS - end // ! csb_reset - end // always @ SCK + /*always @(posedge SCK) begin //// + if (state ==`ADDRESS) + oaddr<= {addr[6:0], SDI}; + else + oaddr = addr; + end */ endmodule // housekeeping_spi `default_nettype wire