stack-machine/program.v

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