`timescale 1ns / 1ps ////////////////////////////////////////////////////////////////////////////////// // Company: techtravels.org/amiga/amigablog // Engineer: Keith Monahan. keith@techtravels.org // // Create Date: 15:07:15 04/24/2010 // Design Name: // Module Name: drivexmitter // Project Name: // Target Devices: // Tool versions: // Description: // // Dependencies: // // Revision: // Revision 0.01 - File Created // Additional Comments: // ////////////////////////////////////////////////////////////////////////////////// module drivexmitter( input clk, input usbtx, input usbres, input floppy_data, input l14switch, input l13switch, input h18switch, output floppy_motor, output floppy_select, output reg floppy_side, output floppy_wgate, output reg floppy_dir, output reg floppy_step, output usbrx, output [7:0] leds, output cout ); wire gotabyte; wire [7:0] eightbits; reg [7:0] character = 0; wire busy; reg valid; reg [7:0] latchchar; reg [15:0] counter = 0; reg [7:0] latch_dout; assign floppy_motor = l13switch; assign floppy_select = l14switch; assign floppy_wgate = 1; //assign floppy_side = 0; // Instantiate the UART receiver module keithrecv recvinstance ( .clk(clk), .rxpin(usbtx), .ByteReady(gotabyte), .data(eightbits) ); // Instantiate the UART transmitter module keithxmit txinstance ( .clk(clk), .data(latch_dout), //was character .valid(valid), .busy(busy), .txpin(usbrx) ); //FIFO declarations reg [7:0] din; reg wr_en; reg rd_en; wire [7:0] dout; wire full; wire almost_full; wire wr_ack; wire overflow; wire empty; wire almost_empty; wire fifo_valid; wire underflow; wire [14:0] data_count; //assign leds[7:1] = data_count[14:9]; // fifo_input_mux declarations reg select = 0; reg [7:0] din0; //din0 and wr_en0 used for FIFO connection to test pattern generator reg wr_en0; reg [7:0] din1; //din1 and wr_en1 used for FIFO connection to floppy reader reg wr_en1; wire [7:0] q_din; wire q_wr_en; // Instantiate the mux for input to FIFO module mymux fifo_input_mux ( .select(select), .din0(din0), .wr_en0(wr_en0), .din1(din1), .wr_en1(wr_en1), .q_din(q_din), .q_wr_en(q_wr_en) ); // we want the output from the mux connected to the input of the fifo xmit_fifo fifo_instance ( .clk(clk), /*.rst(rst),*/ .din(q_din), // Bus [7 : 0] .wr_en(q_wr_en), .rd_en(rd_en), .dout(dout), // Bus [7 : 0] .full(full), .almost_full(almost_full), .wr_ack(wr_ack), .overflow(overflow), .empty(empty), .almost_empty(almost_empty), .valid(fifo_valid), .underflow(underflow), .data_count(data_count)); // Bus [14 : 0] parameter READ_IDLE = 4'b0001; parameter READ_FIFO = 4'b0010; parameter READ_LATCH_DATA = 4'b0100; parameter READ_DROP_VALID = 4'b1000; parameter READ_WAIT_STATE = 4'b1001; reg [3:0] READ_state = READ_IDLE; always@(posedge clk) case (READ_state) READ_IDLE : begin if (!busy && !empty /*&& usbres*/) READ_state <= READ_FIFO; rd_en <= 0; valid <= 0; end READ_FIFO : begin READ_state <= READ_LATCH_DATA; rd_en <= 1; valid <= 0; end READ_LATCH_DATA : begin READ_state <= READ_DROP_VALID; latch_dout <= dout; rd_en <= 0; valid <= 1; end READ_DROP_VALID : begin READ_state <= READ_WAIT_STATE; rd_en <= 0; valid <= 0; end READ_WAIT_STATE : begin READ_state <= READ_IDLE; end default: begin // Fault Recovery READ_state <= READ_IDLE; rd_en <= 0; valid <= 0; end endcase reg [23:0] big_counter = 0; reg [10:0] edge_counter; // was 8:0 reg [7:0] store_value; reg resetme; reg IN_D1, IN_D2; reg go_signal = 0; reg [15:0] count_edges = 0; //assign leds = data_count[14:7]; parameter floppy_idle = 3'b000; parameter floppy_wait_second = 3'b001; parameter floppy_store_value = 3'b010; parameter floppy_stop_store = 3'b011; parameter floppy_wait_for_go = 3'b100; parameter floppy_write_EOB = 3'b101; parameter floppy_wait_EOB = 3'b110; reg [2:0] floppy_state = floppy_idle; // this combines the flops to give a negative transition out // so this is high when current value of floppy_data is low // and the previous cycle was high wire out_negedge = ~IN_D1 & IN_D2; // read floppy state machine // this measures the time between two edges // and stores the result in the fifo // we can read up to 10.24us between edges // counter block // big counter runs until 225ms after the first received edge // edge counter runs between edges // also edge detection flops here too always@ (posedge clk) begin if ((floppy_state == floppy_idle) || (resetme)) edge_counter <= 0; else begin edge_counter <= edge_counter + 1; big_counter <= big_counter + 1; end if (floppy_state == floppy_idle) big_counter <= 0; // edge detection flops IN_D1 <= floppy_data; IN_D2 <= IN_D1; end // this is the state machine for receiving data // from the floppy. When go_signal is high, it records // 225ms of data into the fifo // the times between edges is stored as an 8-bit integer // take this stored int * 40 and that gives original // times in ns between edges always@(posedge clk) case (floppy_state) floppy_wait_for_go : begin if (go_signal) floppy_state <= floppy_idle; wr_en1 <= 0; end floppy_idle : begin if (out_negedge) floppy_state <= floppy_wait_second; wr_en1 <= 0; resetme <= 0; count_edges <= 0; //leds[7:0] <= 0; end floppy_wait_second : begin if (out_negedge) floppy_state <= floppy_store_value; wr_en1 <= 0; resetme <= 0; end floppy_store_value : begin //added next two lines recently //if (almost_full) leds[0] <= 1; //count_edges <= count_edges + 1; //leds[7:1] <= count_edges[15:9]; floppy_state <= floppy_stop_store; if (edge_counter < 512) din1 <= edge_counter / 2; else din1 <= 255; wr_en1 <= 1; resetme <= 0; end floppy_stop_store : begin if (big_counter < 11000000) begin floppy_state <= floppy_wait_second; wr_en1 <= 0; // terminate write unless this is EOB end else begin floppy_state <= floppy_wait_EOB; din1 <= 253; // this special 253 character tells usb->ttl converter and java client that transfer is over wr_en1 <= 1; // so still one from writing the last real data byte into the fifo end resetme <= 1; end floppy_wait_EOB : begin floppy_state <= floppy_write_EOB; din1 <= 253; //write one more 253. wr_en1 <= 1; end floppy_write_EOB : begin wr_en1 <= 0; // terminate write into fifo floppy_state <= floppy_wait_for_go; end default : begin // Fault Recovery floppy_state <= floppy_wait_for_go; wr_en1 <= 0; resetme <= 0; end endcase // state machine follows for the receiving character // logic and transmitting a test pattern parameter wait_for_command = 3'b000; parameter echo_and_check = 3'b001; parameter sendchar = 3'b010; parameter sent_64k = 3'b011; parameter wait_for_echo_finish = 3'b100; parameter wait_one_clk = 3'b101; parameter trigger_read = 3'b110; parameter step_head = 3'b111; reg [2:0] state = wait_for_command; always@(posedge clk) case (state) wait_for_command : begin if (gotabyte) begin //used to be gotabyte state <= echo_and_check; latchchar <= eightbits; end else begin state <= wait_for_command; latchchar <= 0; wr_en0 <= 0; go_signal <= 0; floppy_step <= 1; end end echo_and_check : begin case (latchchar) 66 : begin //B for step backward floppy_dir <= 1; // we want to go backwards counter <= 0; state <= step_head; end 70 : begin //F for step forward floppy_dir <= 0; // we want to go forwards counter <= 0; state <= step_head; end 76 : begin //L for side lower floppy_side <= 1; state <= wait_for_command; end 82 : state <= trigger_read; //R for read 84 : state <= wait_for_echo_finish; //T for test pattern 85 : begin //U for upper head floppy_side <= 0; state <= wait_for_command; end default : begin state <= wait_for_command; end endcase select <= 0; din0 <= latchchar; //wr_en0 <= 1; //echo the character end trigger_read : begin select <= 1; go_signal <= 1; state <= wait_one_clk; end wait_one_clk : begin select <= 1; go_signal <= 1; state <= wait_for_command; end wait_for_echo_finish : begin state <= sendchar; select <= 0; din0 <= 0; counter <= 0; // this clock cycle we are putting a zero into the fifo wr_en0 <= 1; //still a '1' end sendchar : begin if (almost_full) begin wr_en0 <= 0; // stop writing into the fifo end else begin din0 <= din0 + 1; counter <= counter + 1; wr_en0 <= 1; if (counter == 32767) state <= wait_for_command; else state <= sendchar; end end step_head : begin floppy_step <= 0; counter <= counter + 1; if (counter == 100) state <= wait_for_command; else state <= step_head; end default : begin // Fault Recovery state <= wait_for_command; wr_en0 <= 0; end endcase endmodule