My first approach is to start small and just get speed control. My objective is to pass a string through the serial port and use it to either slow down or speed up. The motor controller I want to interface with is the big easy driver. It needs a step pulse, at least 1 microsecond long and direction pulse, either high or low. I'll worry about the direction pulse later. It should be easy compared to the step.
I originally started by using a using a 10 bit long counter. At a certain point it would send a pulse and then go low. When the counter reached the end, it would start over and send another pulse. I attempted to set up a state machine that would start this counter over a little earlier if the string "w" was detected. It didn't work, probably for a number of reasons. I tested it with a scope and it looked almost, um, AC like. And it was giving me 5 volts which was interesting to say the least. Did I mention this is my first fpga project?
After talking with some people it seams like my approach is the wrong way to go. I was probably messing up the timing. It was suggested I set up a state machine that uses an "and" gate to join pulse sequences together.
I'll post my code even though it doesn't work. I based it off some of the examples. Let me know if you have any ideas or tips. Thanks
Code: Select all
------------Top module--------------------------------- module mojo_top( input clk, input rst_n, input cclk, output[7:0]led, output spi_miso, input spi_ss, input spi_mosi, input spi_sck, output [3:0] spi_channel, input avr_tx, output avr_rx, input avr_rx_busy, output motor_step, output motor_dir ); wire rst = ~rst_n; assign spi_miso = 1'bz; assign avr_rx = 1'bz; assign spi_channel = 4'bzzzz; assign led = 8'b1; assign led = 8'b0; assign led = 8'b1; assign led = 8'b0; assign led = 8'b1; assign led = 8'b0; assign led = 8'b1; assign led = 8'b0; wire [7:0] tx_data; wire new_tx_data; wire tx_busy; wire [7:0] rx_data; wire new_rx_data; stepper stepper_1 ( .clk(clk), .rst(rst), .period(period), .motor_step(motor_step) ); stepper_fsm stepper_serial_controll( .clk(clk), .rst(rst), .tx_busy(tx_busy), .rx_data(rx_data), .new_rx_data(new_rx_data), .period(period) ); avr_interface avr_serial ( .clk(clk), .rst(rst), .cclk(cclk), .spi_miso(spi_miso), .spi_mosi(spi_mosi), .spi_sck(spi_sck), .spi_ss(spi_ss), .spi_channel(spi_channel), .tx(avr_rx), // FPGA tx goes to AVR rx .rx(avr_tx), .channel(4'd15), // invalid channel disables the ADC .new_sample(), .sample(), .sample_channel(), .tx_data(tx_data), .new_tx_data(new_tx_data), .tx_busy(tx_busy), .tx_block(avr_rx_busy), .rx_data(rx_data), .new_rx_data(new_rx_data) ); endmodule --------------Step Pulse Module------------------------- module stepper ( input clk, input rst, input period, output motor_step ); reg pwm_d, pwm_q; reg [10:0] ctr_d, ctr_q; assign motor_step = pwm_q; always @(*) begin ctr_d = ctr_q + 1'b1; if (ctr_q > 3'd8 & ctr_q < 6'd60 ) pwm_d = 1'b1; else pwm_d = 1'b0; end always @(posedge clk) begin if (rst) begin ctr_q <= 1'b0; end if (ctr_q > period) begin ctr_q <= 1'b0; end else begin ctr_q <= ctr_d; end pwm_q <= pwm_d; end endmodule ----------------State machine module------------- module stepper_fsm( input clk, input rst, output [7:0] tx_data, output reg new_tx_data, input tx_busy, input [7:0] rx_data, input new_rx_data, output reg [9:0]period ); localparam STATE_SIZE = 1; localparam IDLE = 0, INCREASE_SPEED = 1, DECREASE_SPEED = 2; reg [STATE_SIZE-1:0] state_d, state_q; reg [3:0] addr_d, addr_q; period = 9'd512; always @(*) begin state_d = state_q; // default values addr_d = addr_q; // needed to prevent latches new_tx_data = 1'b0; case (state_q) //look for the value of state q IDLE: begin addr_d = 4'd0; if (new_rx_data && rx_data == "w") state_d = INCREASE_SPEED; if (new_rx_data && rx_data == "s") state_d = DECREASE_SPEED; end INCREASE_SPEED: begin period = period - 9'd256; end DECREASE_SPEED: begin period = period +9'd256; end default: state_d = IDLE; endcase end always @(posedge clk) begin if (rst) begin state_q <= IDLE; end else begin state_q <= state_d; end addr_q <= addr_d; end endmodule