88 lines
2.2 KiB
Verilog
88 lines
2.2 KiB
Verilog
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
|