`include "ncr5380_defines.v" module ncr5380_top( // host interface nrst, clk, addr, data_in, data_out, nsmemr, nsmemw, drq, ndack, // SCSI interface scsi_db, scsi_dbp, scsi_io, scsi_req, scsi_cd, scsi_sel, scsi_msg, scsi_rst, scsi_ack, scsi_bsy, scsi_atn ); input nrst; input clk; input [2:0] addr; input [7:0] data_in; output reg [7:0] data_out; input nsmemr; input nsmemw; output reg drq; input ndack; inout [7:0] scsi_db; inout scsi_dbp; inout scsi_io; inout scsi_req; inout scsi_cd; inout scsi_sel; inout scsi_msg; inout scsi_rst; inout scsi_ack; inout scsi_bsy; inout scsi_atn; //reg db_assert; //reg parity; reg parity_gen; //reg parity_chk; // NCR registers reg [7:0] output_data_reg; reg [7:0] initiator_command_reg; reg [7:0] mode_reg; reg [3:0] target_command_reg; reg [7:0] input_data_reg; reg bus_phase_cmp; // SELECT State Machine registers reg aip; reg la; reg [1:0] arb_state; reg [6:0] bus_free_cnt; // DMA State Machine registers reg [2:0] dma_state; reg dma_req; reg dma_ack; // CPU write always @(posedge clk or negedge nrst) begin if (!nrst) begin output_data_reg <= 0; initiator_command_reg <= 0; mode_reg <= 0; target_command_reg <= 0; end else begin if (!nsmemw) begin if (!ndack == 1) output_data_reg <= data_in; else begin case (addr[2:0]) `OUTPUT_DATA_REG: output_data_reg <= data_in; `INITIATOR_COMMAND_REG: initiator_command_reg <= data_in; `MODE_REG: mode_reg <= data_in; `TARGET_COMMAND_REG: target_command_reg <= data_in[3:0]; endcase end end end end // CPU read always @(posedge clk) begin if (!nsmemr) begin if (!ndack == 1) data_out <= input_data_reg; else begin case (addr[2:0]) `CURRENT_SCSI_DATA_REG: data_out <= ~scsi_db; `INITIATOR_COMMAND_REG: data_out <= {initiator_command_reg[7], aip, la, initiator_command_reg[4:0]}; `MODE_REG: data_out <= mode_reg; `TARGET_COMMAND_REG: data_out <= {4'b0000, target_command_reg}; `STATUS_REG: data_out <= {~scsi_rst, ~scsi_bsy, ~scsi_req, ~scsi_msg, ~scsi_cd, ~scsi_io, ~scsi_sel, ~scsi_dbp}; `BUS_AND_STATUS_REG: data_out <= {6'b000000, ~scsi_atn, scsi_ack}; `INPUT_DATA_REG: data_out <= input_data_reg; endcase end end end // Parity check //always @(posedge clk) //begin //end // SELECT state machine always @(posedge clk) begin if (mode_reg[`MR_ARBITRATE]) begin case (arb_state) 2'd0: if (scsi_sel && scsi_bsy) begin bus_free_cnt <= 0; arb_state <= arb_state + 1'b1; end 2'd1: if (!bus_free_cnt[6]) bus_free_cnt <= bus_free_cnt + 1'b1; else begin if (scsi_sel && scsi_bsy) aip <= 1'b1; else la <= 1'b1; arb_state <= arb_state + 1'b1; end endcase end else begin arb_state <= 0; aip <= 0; la <= 0; end end // DMA State Machine always @(posedge clk) begin if (mode_reg[`MR_DMA_MODE] == 1) begin if (mode_reg[`MR_BLOCK_DMA_MODE] == 0) begin if (mode_reg[`MR_TARGET] == 0) begin // NON-BLOCK MODE INITIATOR case (dma_state) 3'd0: if (!scsi_req && bus_phase_cmp) begin drq <= 1; // raise DRQ dma_state <= dma_state + 1'b1; end 3'd1: begin input_data_reg <= ~scsi_db; dma_state <= dma_state + 1'b1; end 3'd2: if (!ndack) begin drq <= 0; // lower DRQ dma_state <= dma_state + 1'b1; end 3'd3: if (ndack) begin dma_ack <= 1; // rasie nACK dma_state <= dma_state + 1'b1; end 3'd4: if (scsi_req) begin dma_ack <= 0; // lower nACK dma_state <= 0; end endcase end else begin // NON-BLOCK MODE TARGET // ToDo: not implemented end end else begin if (mode_reg[`MR_TARGET] == 0) begin // BLOCK MODE INITIATOR // ToDo: not implemented end else begin // BLOCK MODE TARGET // ToDo: not implemented end end end else begin dma_state = 0; drq <= 0; dma_ack <= 0; dma_req <= 0; end end always @(*) begin // parity parity_gen <= ~(((~output_data_reg[0] ^ ~output_data_reg[1]) ^ (~output_data_reg[2] ^ ~output_data_reg[3])) ^ ((~output_data_reg[4] ^ ~output_data_reg[5]) ^ (~output_data_reg[6] ^ ~output_data_reg[7]))); // bus phase comparsion bus_phase_cmp <= (target_command_reg[`TCR_ASSERT_IO] == ~scsi_io) && (target_command_reg[`TCR_ASSERT_CD] == ~scsi_cd) && (target_command_reg[`TCR_ASSERT_MSG] == ~scsi_msg); end assign scsi_db[0] = (output_data_reg[0] && (initiator_command_reg[`ICR_ASSERT_DATA] || aip)) ? 1'b0 : 1'bZ; assign scsi_db[1] = (output_data_reg[1] && (initiator_command_reg[`ICR_ASSERT_DATA] || aip)) ? 1'b0 : 1'bZ; assign scsi_db[2] = (output_data_reg[2] && (initiator_command_reg[`ICR_ASSERT_DATA] || aip)) ? 1'b0 : 1'bZ; assign scsi_db[3] = (output_data_reg[3] && (initiator_command_reg[`ICR_ASSERT_DATA] || aip)) ? 1'b0 : 1'bZ; assign scsi_db[4] = (output_data_reg[4] && (initiator_command_reg[`ICR_ASSERT_DATA] || aip)) ? 1'b0 : 1'bZ; assign scsi_db[5] = (output_data_reg[5] && (initiator_command_reg[`ICR_ASSERT_DATA] || aip)) ? 1'b0 : 1'bZ; assign scsi_db[6] = (output_data_reg[6] && (initiator_command_reg[`ICR_ASSERT_DATA] || aip)) ? 1'b0 : 1'bZ; assign scsi_db[7] = (output_data_reg[7] && (initiator_command_reg[`ICR_ASSERT_DATA] || aip)) ? 1'b0 : 1'bZ; assign scsi_dbp = (parity_gen && (initiator_command_reg[`ICR_ASSERT_DATA] || aip)) ? 1'b0: 1'bZ; assign scsi_atn = (initiator_command_reg[`ICR_ASSERT_ATN] && !mode_reg[`MR_TARGET]) ? 1'b0 : 1'bZ; assign scsi_sel = (initiator_command_reg[`ICR_ASSERT_SEL]) ? 1'b0 : 1'bZ; assign scsi_bsy = (initiator_command_reg[`ICR_ASSERT_BSY] || aip) ? 1'b0 : 1'bZ; assign scsi_ack = (dma_ack || (initiator_command_reg[`ICR_ASSERT_ACK] && !mode_reg[`MR_TARGET])) ? 1'b0 : 1'bZ; assign scsi_rst = (initiator_command_reg[`ICR_ASSERT_RST]) ? 1'b0 : 1'bZ; assign scsi_io = (target_command_reg[`TCR_ASSERT_IO] && mode_reg[`MR_TARGET]) ? 1'b0 : 1'bZ; assign scsi_cd = (target_command_reg[`TCR_ASSERT_CD] && mode_reg[`MR_TARGET]) ? 1'b0 : 1'bZ; assign scsi_msg = (target_command_reg[`TCR_ASSERT_MSG] && mode_reg[`MR_TARGET]) ? 1'b0 : 1'bZ; assign scsi_req = (dma_req || (target_command_reg[`TCR_ASSERT_REQ] && mode_reg[`MR_TARGET])) ? 1'b0 : 1'bZ; endmodule