I'm designing a MIDI receiver port (using Altera CLPD MAX 7000S). The device samples the second byte it receives and outputs the binary value on an LEDs. The device works fine whenever I input MIDI notes (using MIDI-OX software) at a normal speed. However, whenever I input notes too fast, or input two notes at the same time), it doesn't work correctly (outputs to incorrect LEDs whenever I input any note).

This is my Verilog code. I sample the MIDI bit at the middle.

//using a 4MHz clock using a 31250bit/s baud rate (1 bit -> 32 us; all 10 bits -> 320us  -> 10.3 bits -> 11 bits)
module timer(input clk, input reset, input enable, output [10:0] out);
reg [10:0] timer;
initial timer = 11'b0;
assign out = timer;

always @(posedge clk) begin
    if(!reset)  //if reset is pressed, set timer back to 0
        timer <= 11'b00000000000;
    else if(enable == 1'b1) //if enable is high
                timer <= timer + 11'b00000000001; //increment counter every time
                if(timer == 11'b11111111111)     //if counter reaches max value (should never reach it)
                    timer <= 11'b00000000000; //set it back to 0
        timer <= 11'b00000000000; // if enable is low, set the timer to 0

module rx(input clk, input reset, input in, output [7:0] out);

parameter IDLE = 2'b01;
parameter BYTE_CUR = 2'b10;
parameter BYTE_END = 2'b11;
parameter HIGH = 1'b1;
parameter LOW = 1'b0;

reg [7:0] LEDs;
initial LEDs = 8'b0;

reg [7:0] LED;
initial LED = 8'b0;
assign out = LED;

reg [1:0] state;
initial state = IDLE;

reg [2:0] byteNo; 
initial byteNo = 3'b000;

reg timer_en;
initial timer_en = 1'b0;

wire timer_en_wire;
assign timer_en_wire = timer_en;

wire [10:0] timer_wire;

timer t(.clk(clk), .reset(reset), .enable(timer_en_wire), .out(timer_wire)); 

always @(posedge clk) begin
        LEDs <= 8'b0;
        LED <= 8'b0;
        timer_en <= 1'b0;
        state <= IDLE;
        byteNo <= 3'b000;
    else begin
    if(state == IDLE && in == LOW) // if IDLE and detect a LOW on the input line, start bit has arrived
        state <= BYTE_CUR;  //change state to BYTE_CUR
        byteNo <= byteNo + 3'b001; // increment byteNo
        timer_en <= 1'b1; // enable the timer
    if(state == BYTE_CUR) //currently a byte
            11'b00011000000: LEDs[7] <= in; // 1.5 BT
            11'b00101000000: LEDs[6] <= in; // 2.5 BT
            11'b00111000000: LEDs[5] <= in; // 3.5 BT
            11'b01001000000: LEDs[4] <= in; // 4.5 BT
            11'b01011000000: LEDs[3] <= in; // 5.5 BT
            11'b01101000000: LEDs[2] <= in; // 6.5 BT
            11'b01111000000: LEDs[1] <= in; // 7.5 BT
            11'b10001000000: LEDs[0] <= in; // 8.5 BT
            11'b10100000000: begin   // 10 BT
                state <= BYTE_END;
                timer_en <= 1'b0;
    if(state == BYTE_END) //if byte has ended
        if(byteNo == 3'b010) // if byte number is 2, output the lights
            LED <= LEDs;
        if(byteNo == 3'b101) // if byte number is 5, clear the output
            LED <= 3'b000;
        if(byteNo == 3'b110) // if byte number is 6, reset byte counter to 0
            byteNo <= 3'b000;
        state <= IDLE; //set state back to IDLE


I see two potential issues.

First of all, your in input is asynchronous to your internal clock, so you must synchronize is before using it in your state machine. The specific problem involves the transition from IDLE (encoded 2'b01) to BYTE_CUR (encoded 2'b10) — this requires both state variables to change, and the asynchronous input could cause them to be evaluated differently, resulting in a transition to state 2'b00 or 2'b11, which is not what you intend.

Second, you have this three-bit counter called byteNo. (BTW, this is also adversely affected by the asynchronous input.) You seem to be assuming that every message is 6 bytes long, and that the note number is the second byte of the message. I'm not sure where you get this — it isn't in any MIDI specification that I've seen.

In general, channel messages are 3 bytes long, comprising a status byte (e.g., "note on") and two data bytes (e.g., note number and velocity). Most MIDI devices will omit the second and subsequent status bytes when sending multiple "note on" messages in rapid succession, which means that you could be looking at a stream of bytes like:

Note On | Note # | Vel. | Note # | Vel. | Note # | Vel. | ...

In other words, you need a much more sophisticated state machine that keeps track of the most recent status byte and then parses the subsequent data bytes accordingly.

| improve this answer | |

Not the answer you're looking for? Browse other questions tagged or ask your own question.