`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: nope
// Engineer: Jose
// 
// Create Date: 02/20/2026 09:21:52 AM
// Design Name: RISCV AC Processor Simulation
// Module Name: tb_riscv
// Project Name: riscv-ac
// Target Devices: Artix 7
// Tool Versions: 2025.2
// Description: Testbench for simulation + MMIO
// 
// Dependencies: 
// 
// Revision: 2.0 - MMIO
// Revision: 1.0 - Basic structure
// Revision: 0.01 - File Created
// Additional Comments:
// 
//////////////////////////////////////////////////////////////////////////////////


`timescale 1ns / 1ps

module tb_riscv();
    reg clk;
    reg rst;
    
    wire [1:0] leds;
    wire [7:0] uart_tx_data;
    wire uart_tx_en;
    reg rx;
    wire tx;

    riscv uut (
        .clk(clk),
        .rst(rst),
        .rx(rx),
        .tx(tx),
        .leds(leds),
        .uart_tx_data(uart_tx_data),
        .uart_tx_en(uart_tx_en)
    );
    
    // T_CLK = 10ns
    always #5 clk = ~clk;
    
    task send_uart_byte;
        input [7:0] data;
        integer i;
        begin
            // 1. Bit de Start (bajamos a 0)
            rx = 0;
            #(868 * 10); // Esperamos los ciclos de 1 bit (104 ciclos * 10ns)
            
            // 2. Mandamos los 8 bits de datos (LSB primero, de derecha a izquierda)
            for (i = 0; i < 8; i = i + 1) begin
                rx = data[i];
                #(868 * 10);
            end
            
            // 3. Bit de Stop (subimos a 1)
            rx = 1;
            #(868 * 10);
        end
    endtask

    initial begin
        // inicializamos señales
        clk = 0;
        rst = 1;
        rx = 1;

        // (SOLO SIMULACION) cargamos programa
        //$readmemh("/home/jomaa/git/riscv-ac/riscv-ac.srcs/sim_1/new/program.mem", uut.u_imem.memory);

        // activamos reset 20ns
        #20;
        rst = 0;

        // mandamos instrucciones
        #100;
        
        // 1. addi x5, x0, 65 (04100293) -> cargamos 'A' (65) en x5
        send_uart_byte(8'h93); send_uart_byte(8'h02); send_uart_byte(8'h10); send_uart_byte(8'h04);

        // 2. addi x6, x0, -4 (ffc00313) -> cargamos la dirección de la UART mapeada (0xFFFFFFFC) en x6
        send_uart_byte(8'h13); send_uart_byte(8'h03); send_uart_byte(8'hC0); send_uart_byte(8'hFF);

        // 3. sw x5, 0(x6) (00532023) -> alla que va pa la UART
        send_uart_byte(8'h23); send_uart_byte(8'h20); send_uart_byte(8'h53); send_uart_byte(8'h00);

        // 4. jal x0, 0 (0000006f) -> fin
        send_uart_byte(8'h6F); send_uart_byte(8'h00); send_uart_byte(8'h00); send_uart_byte(8'h00);
        
        #(55000 * 10)
        
        #2000;

        $finish;
    end
endmodule