Estoy diseñando un puerto de receptor MIDI (utilizando Altera CLPD MAX 7000S). El dispositivo muestrea el segundo byte que recibe y emite el valor binario en un LED. El dispositivo funciona bien cada vez que ingreso notas MIDI (usando el software MIDI-OX) a una velocidad normal. Sin embargo, siempre que ingrese notas demasiado rápido, o ingrese dos notas al mismo tiempo, no funciona correctamente (sale a LEDs incorrectos cada vez que ingrese cualquier nota).
Este es mi código Verilog. Muestreo el bit MIDI en el medio.
//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
begin
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
end
else
timer <= 11'b00000000000; // if enable is low, set the timer to 0
end
endmodule
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
if(!reset)
begin
LEDs <= 8'b0;
LED <= 8'b0;
timer_en <= 1'b0;
state <= IDLE;
byteNo <= 3'b000;
end
else begin
if(state == IDLE && in == LOW) // if IDLE and detect a LOW on the input line, start bit has arrived
begin
state <= BYTE_CUR; //change state to BYTE_CUR
byteNo <= byteNo + 3'b001; // increment byteNo
timer_en <= 1'b1; // enable the timer
end
if(state == BYTE_CUR) //currently a byte
begin
case(timer_wire)
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;
end
endcase
end
if(state == BYTE_END) //if byte has ended
begin
if(byteNo == 3'b010) // if byte number is 2, output the lights
begin
LED <= LEDs;
end
if(byteNo == 3'b101) // if byte number is 5, clear the output
begin
LED <= 3'b000;
end
if(byteNo == 3'b110) // if byte number is 6, reset byte counter to 0
begin
byteNo <= 3'b000;
end
state <= IDLE; //set state back to IDLE
end
end
end
endmodule