`timescale 1ns / 1ps

module DataMemory (
    input clk,
    input reset,
    input [31:0] address,
    input write_enable,
    input [31:0] write_data,
    output [31:0] read_data,
    output [31:0] bcd_hardwire
);
    parameter integer MEM_SIZE_IN_WORD = 64;
    parameter integer START_ADDRESS = 32'h00000000;

    localparam integer StartAddressInWord = START_ADDRESS / 4;

    reg [31:0] memory_data[MEM_SIZE_IN_WORD + StartAddressInWord - 1 : StartAddressInWord];

    assign bcd_hardwire = memory_data[StartAddressInWord+4];

    assign read_data = memory_data[address[31:2]];

    integer i;

    initial begin
        for (i = StartAddressInWord; i < 24 + StartAddressInWord; i = i + 1) begin
            memory_data[i] <= 32'h00000000;
        end
        for (
            i = 45 + StartAddressInWord; i < MEM_SIZE_IN_WORD + StartAddressInWord; i = i + 1
        ) begin
            memory_data[i] <= 32'h00000000;
        end
        memory_data[StartAddressInWord+24] <= 32'h00000014;
        memory_data[StartAddressInWord+25] <= 32'h000041A8;
        memory_data[StartAddressInWord+26] <= 32'h00003AF2;
        memory_data[StartAddressInWord+27] <= 32'h0000ACDA;
        memory_data[StartAddressInWord+28] <= 32'h0000C0B2;
        memory_data[StartAddressInWord+29] <= 32'h0000B783;
        memory_data[StartAddressInWord+30] <= 32'h0000DAC9;
        memory_data[StartAddressInWord+31] <= 32'h00008ED9;
        memory_data[StartAddressInWord+32] <= 32'h000009FF;
        memory_data[StartAddressInWord+33] <= 32'h00002F44;
        memory_data[StartAddressInWord+34] <= 32'h0000044E;
        memory_data[StartAddressInWord+35] <= 32'h00009899;
        memory_data[StartAddressInWord+36] <= 32'h00003C56;
        memory_data[StartAddressInWord+37] <= 32'h0000128D;
        memory_data[StartAddressInWord+38] <= 32'h0000DBE3;
        memory_data[StartAddressInWord+39] <= 32'h0000D4B4;
        memory_data[StartAddressInWord+40] <= 32'h00003748;
        memory_data[StartAddressInWord+41] <= 32'h00003918;
        memory_data[StartAddressInWord+42] <= 32'h00004112;
        memory_data[StartAddressInWord+43] <= 32'h0000C399;
        memory_data[StartAddressInWord+44] <= 32'h00004955;
    end

    always @(posedge clk) begin
        if (reset) begin
            for (i = StartAddressInWord; i < 24 + StartAddressInWord; i = i + 1) begin
                memory_data[i] <= 32'h00000000;
            end
            for (
                i = 45 + StartAddressInWord; i < MEM_SIZE_IN_WORD + StartAddressInWord; i = i + 1
            ) begin
                memory_data[i] <= 32'h00000000;
            end
            memory_data[StartAddressInWord+24] <= 32'h00000014;
            memory_data[StartAddressInWord+25] <= 32'h000041A8;
            memory_data[StartAddressInWord+26] <= 32'h00003AF2;
            memory_data[StartAddressInWord+27] <= 32'h0000ACDA;
            memory_data[StartAddressInWord+28] <= 32'h0000C0B2;
            memory_data[StartAddressInWord+29] <= 32'h0000B783;
            memory_data[StartAddressInWord+30] <= 32'h0000DAC9;
            memory_data[StartAddressInWord+31] <= 32'h00008ED9;
            memory_data[StartAddressInWord+32] <= 32'h000009FF;
            memory_data[StartAddressInWord+33] <= 32'h00002F44;
            memory_data[StartAddressInWord+34] <= 32'h0000044E;
            memory_data[StartAddressInWord+35] <= 32'h00009899;
            memory_data[StartAddressInWord+36] <= 32'h00003C56;
            memory_data[StartAddressInWord+37] <= 32'h0000128D;
            memory_data[StartAddressInWord+38] <= 32'h0000DBE3;
            memory_data[StartAddressInWord+39] <= 32'h0000D4B4;
            memory_data[StartAddressInWord+40] <= 32'h00003748;
            memory_data[StartAddressInWord+41] <= 32'h00003918;
            memory_data[StartAddressInWord+42] <= 32'h00004112;
            memory_data[StartAddressInWord+43] <= 32'h0000C399;
            memory_data[StartAddressInWord+44] <= 32'h00004955;
        end else begin
            if (write_enable) begin
                memory_data[address[31:2]] <= write_data;
            end
        end
    end
endmodule
