Embedded Systems Spring 2024
HW 6 VGA

Name: Mason Brady
Email: mrbrady1@fortlewis.edu

HW 6

Introduction: This homework is an introduction to VGA ports

Materials: gvim, vivado

Methods:

Part 1) I started by copying down the code to the following:

module USB_keyboard(ps2data, ps2clk, data, ready);
    input ps2data;
    input ps2clk;
    output reg [7:0] data;
    output reg ready = 0;
    parameter RDY = 2'b00, RECEIVE = 2'b01, PARITY = 2'b10, STOP = 2'b11;
    reg [2:0] state = RDY;
    reg [7:0] received;
    reg prty;
    integer index = 0;
    always @ (negedge ps2clk)
    case (state)
        RDY:
            if(ps2data == 1'b0) begin
                state <= RECEIVE;
                ready <= 1'b0;
                index <= 0;
            end    
        RECEIVE:
            begin
            if(index == 7) state <= PARITY;
            received[index] <= ps2data;
            index <= index + 1;
            end
        PARITY:
            begin
            prty <= ps2data;
            state <= STOP;
            end
        STOP:
            if(ps2data == 1'b1) begin
                state <= RDY;
                ready <= 1'b1;
                if(prty != ~(^received)) data <= 8'hEE;
                else data <= received;
            end
    endcase
endmodule

module UART_tx_ctrl (ready, uart_tx, clk, send, data);
    input send, clk;
    input [7:0] data;
    output ready, uart_tx;
    parameter baud = 9600;
    parameter bit_index_max = 10;
    localparam [31:0] baud_timer = 100000000/baud;
    localparam RDY = 2'b00, LOAD_BIT = 1'b01, SEND_BIT = 2'b10;
    reg [1:0] state = RDY;
    reg [31:0] timer = 0;
    reg [9:0] txData;
    reg [3:0] bitIndex;
    reg txBit = 1'b1;
  
    always @(posedge clk)
        case(state)
            RDY: begin
                bitIndex <= 1'b0;
                timer <= 14'b0;
                txBit <= 1'b1;
                if(send == 1'b1) begin
                    txData <= {1'b1, data, 1'b0};
                    state <= LOAD_BIT;
                end
            end
            LOAD_BIT: begin
                if(timer == baud_timer) begin
                    timer <= 14'b0;
                    state <= SEND_BIT;
                    txBit <= txData[bitIndex];
                    bitIndex <= bitIndex + 1'b1;
                end else timer <= timer + 1'b1;
            end
            SEND_BIT: begin
                if(bitIndex == bit_index_max) state <= RDY;
                else state <= LOAD_BIT;
            end
            default: state <= RDY;
        endcase
      
        assign uart_tx = txBit;
        assign ready = (state == RDY);
endmodule

module USB_keyboard_app(clk, PS2Clk, PS2Data, led, RsTx);
input clk;
input PS2Clk;
input PS2Data;
output [15:0] led;

output RsTx;
reg [7:0] initStr = 8'h41;
localparam btnWait = 2'b00, btnSend = 2'b01, btnSendWait = 2'b10;
reg btnC_prev;
reg [7:0] uartData;
reg uartState = 1'b0;
wire btnC_clr;
wire uartSend;
wire uartRdy;

localparam PRESS = 2'b00, EXTEND = 2'b01, RLS = 2'b10, CHECK = 2'b11;
reg [1:0] state = PRESS;
reg [23:0] received;
wire [7:0] data;
reg [7:0] ledreg = 0;
wire ready;
reg ready_prev;
USB_keyboard kb1(.ps2data(PS2Data), .ps2clk(PS2Clk), .data(data), .ready(ready));
UART_tx_ctrl #(19200) uart(.clk(clk), .send(uartSend), .data(uartData), .uart_tx(RsTx), .ready(uartRdy));
always @ (posedge clk) begin
    ready_prev <= ready;
    case(state)
        PRESS:
            if (ready_prev == 0 && ready == 1) begin
                received[23:16] <= data;
                state <= EXTEND;
            end
        EXTEND:
            if (ready_prev == 0 && ready == 1) begin
                received[15:8] <= data;
                state <= RLS;
            end
        RLS:
            if (received[15:8] != 8'hF0) state <= EXTEND;
            else if (ready_prev == 0 && ready == 1) begin
                received[7:0] <= data;
                state <= CHECK;
            end
        CHECK:
            begin
            uartState <= 1'b0;
            case(received[7:0])
            8'h16: ledreg[0] <= ~ledreg[0];
            8'h1E: ledreg[1] <= ~ledreg[1];
            8'h26: ledreg[2] <= ~ledreg[2];
            8'h25: ledreg[3] <= ~ledreg[3];
            8'h2E: ledreg[4] <= ~ledreg[4];
            8'h36: ledreg[5] <= ~ledreg[5];
            8'h3D: ledreg[6] <= ~ledreg[6];
            8'h3E: ledreg[7] <= ~ledreg[7];
            endcase
            state <= PRESS;
        end
    endcase
end
assign led = {received[7:0], ledreg};
assign uartSend = {state == CHECK};
endmodule

This ended up working fine as soon as I switched my keyboard. The demo can be seen below.

Part 2)

I then added my module for tx to the serial monitor and switched the ledreg values of the check statement to simply set the UART data to the corresponding ASCII code for the number. Other than some slight modifications this way pretty much copy and paste from one of the previous homeworks.

module UART_tx_ctrl (ready, uart_tx, clk, send, data);
    input send, clk;
    input [7:0] data;
    output ready, uart_tx;
    parameter baud = 9600;
    parameter bit_index_max = 10;
    localparam [31:0] baud_timer = 100000000/baud;
    localparam RDY = 2'b00, LOAD_BIT = 1'b01, SEND_BIT = 2'b10;
    reg [1:0] state = RDY;
    reg [31:0] timer = 0;
    reg [9:0] txData;
    reg [3:0] bitIndex;
    reg txBit = 1'b1;
  
    always @(posedge clk)
        case(state)
            RDY: begin
                bitIndex <= 1'b0;
                timer <= 14'b0;
                txBit <= 1'b1;
                if(send == 1'b1) begin
                    txData <= {1'b1, data, 1'b0};
                    state <= LOAD_BIT;
                end
            end
            LOAD_BIT: begin
                if(timer == baud_timer) begin
                    timer <= 14'b0;
                    state <= SEND_BIT;
                    txBit <= txData[bitIndex];
                    bitIndex <= bitIndex + 1'b1;
                end else timer <= timer + 1'b1;
            end
            SEND_BIT: begin
                if(bitIndex == bit_index_max) state <= RDY;
                else state <= LOAD_BIT;
            end
            default: state <= RDY;
        endcase
      
        assign uart_tx = txBit;
        assign ready = (state == RDY);
endmodule

module USB_keyboard_app(clk, PS2Clk, PS2Data, led, RsTx);
input clk;
input PS2Clk;
input PS2Data;
output [15:0] led;

output RsTx;
reg [7:0] initStr = 8'h41;
localparam btnWait = 2'b00, btnSend = 2'b01, btnSendWait = 2'b10;
reg btnC_prev;
reg [7:0] uartData;
reg uartState = 1'b0;
wire btnC_clr;
wire uartSend;
wire uartRdy;

localparam PRESS = 2'b00, EXTEND = 2'b01, RLS = 2'b10, CHECK = 2'b11;
reg [1:0] state = PRESS;
reg [23:0] received;
wire [7:0] data;
reg [7:0] ledreg = 0;
wire ready;
reg ready_prev;
USB_keyboard kb1(.ps2data(PS2Data), .ps2clk(PS2Clk), .data(data), .ready(ready));
UART_tx_ctrl #(19200) uart(.clk(clk), .send(uartSend), .data(uartData), .uart_tx(RsTx), .ready(uartRdy));
always @ (posedge clk) begin
    ready_prev <= ready;
    case(state)
        PRESS:
            if (ready_prev == 0 && ready == 1) begin
                received[23:16] <= data;
                state <= EXTEND;
            end
        EXTEND:
            if (ready_prev == 0 && ready == 1) begin
                received[15:8] <= data;
                state <= RLS;
            end
        RLS:
            if (received[15:8] != 8'hF0) state <= EXTEND;
            else if (ready_prev == 0 && ready == 1) begin
                received[7:0] <= data;
                state <= CHECK;
            end
        CHECK:
            begin
            uartState <= 1'b0;
            case(received[7:0])
            8'h16: uartData <= 49;
            8'h1E: uartData <= 50;
            8'h26: uartData <= 51;
            8'h25: uartData <= 52;
            8'h2E: uartData <= 53;
            8'h36: uartData <= 54;
            8'h3D: uartData <= 55;
            8'h3E: uartData <= 56;
            endcase
            state <= PRESS;
        end
    endcase
end
assign led = {received[7:0], ledreg};
assign uartSend = {state == CHECK};
endmodule

Discussion:
Easy peasy. I have a programmable RGB mechanical keyboard which caused the busy light on the board to flash very fast and the LEDs to not light up. When I switched to a cheaper membrane keyboard everything worked fine. Very odd but kind of makes sense if the keyboard is trying to send unwanted data.