module ProgramRAM (CLK_I,RST_I,INST_ADR_I,INST_DAT_O,INST_STB_I,INST_ACK_O, DATA_ADR_I,DATA_DAT_I,DATA_DAT_O,DATA_STB_I,DATA_WE_I,DATA_SEL_I,DATA_ACK_O); input CLK_I; input RST_I; input [12:0] INST_ADR_I; output [7:0] INST_DAT_O; input INST_STB_I; output INST_ACK_O; input [12:2] DATA_ADR_I; input [31:0] DATA_DAT_I; output [31:0] DATA_DAT_O; input DATA_STB_I; input DATA_WE_I; input [3:0] DATA_SEL_I; output DATA_ACK_O; // synthesis attribute ram_style of RAM is block; reg [31:0] RAM[0:2047]; reg [12:2] READ_INST; reg [12:2] READ_DATA; reg [7:0] INST_DAT_O; reg INST_ACK_O; wire [31:0] DATA_DAT_O; reg DATA_ACK_O; initial begin $readmemh("program.data", RAM, 0, 2047); end reg [12:2] INST_PRED_ADR; wire WORD_ACCESS = &DATA_SEL_I; reg DATA_READ = 1'b0; reg [31:0] RMW_DATA; always @(posedge CLK_I) begin if (DATA_STB_I & DATA_WE_I & (WORD_ACCESS | DATA_READ)) RAM[DATA_ADR_I] <= WORD_ACCESS ? DATA_DAT_I : RMW_DATA; READ_DATA <= DATA_ADR_I[12:2]; READ_INST <= INST_PRED_ADR[12:2]; DATA_READ <= DATA_STB_I & ~DATA_ACK_O; end wire [31:0] INST_DAT32_O; assign INST_DAT32_O = RAM[READ_INST]; assign DATA_DAT_O = RAM[READ_DATA]; wire [12:0] NEXT_INST_ADR = INST_ADR_I + 13'd1; wire PRED_CORRECT = (READ_INST == INST_ADR_I[12:2]); wire READ_DONE = DATA_READ; wire WRITE_DONE = WORD_ACCESS | DATA_READ; always @* begin case (INST_ADR_I[1:0]) 2'b00: INST_DAT_O <= INST_DAT32_O[31:24]; 2'b01: INST_DAT_O <= INST_DAT32_O[23:16]; 2'b10: INST_DAT_O <= INST_DAT32_O[15:8]; 2'b11: INST_DAT_O <= INST_DAT32_O[7:0]; endcase if (~INST_STB_I | PRED_CORRECT) INST_PRED_ADR <= NEXT_INST_ADR[12:2]; else // incorrectly predicted, forces wait state INST_PRED_ADR <= INST_ADR_I[12:2]; INST_ACK_O <= INST_STB_I & PRED_CORRECT; DATA_ACK_O <= DATA_STB_I & (DATA_WE_I ? WRITE_DONE : READ_DONE); RMW_DATA[31:24] <= DATA_SEL_I[3] ? DATA_DAT_I[31:24] : DATA_DAT_O[31:24]; RMW_DATA[23:16] <= DATA_SEL_I[2] ? DATA_DAT_I[23:16] : DATA_DAT_O[23:16]; RMW_DATA[15: 8] <= DATA_SEL_I[1] ? DATA_DAT_I[15: 8] : DATA_DAT_O[15: 8]; RMW_DATA[ 7: 0] <= DATA_SEL_I[0] ? DATA_DAT_I[ 7: 0] : DATA_DAT_O[ 7: 0]; end endmodule