module sram_srom (input i_clk, input i_rst, input i_dir, input [1:0] i_act, input [23:0] i_addr, input [31:0] i_data, output reg [31:0] o_data, output o_we, output reg o_stb); (* ram_style = "block" *) reg [7:0] sram0 [4095:0]; (* ram_style = "block" *) reg [7:0] sram1 [4095:0]; (* ram_style = "block" *) reg [7:0] sram2 [4095:0]; (* ram_style = "block" *) reg [7:0] sram3 [4095:0]; (* ram_style = "block" *) reg [31:0] srom [4095:0]; wire use_ram; wire use_rom; wire [7:0] data0, data1, data2, data3; wire [11:0] waddr; reg wram0, wram1, wram2, wram3; reg [7:0] wdata1, wdata2, wdata3; reg [7:0] rdata0, rdata1, rdata2, rdata3; reg [31:0] mdata; reg waiter; integer i; assign data0 = i_data[7:0]; assign data1 = i_data[15:8]; assign data2 = i_data[23:16]; assign data3 = i_data[31:24]; assign waddr = i_addr[13:2]; assign use_ram = i_addr >= 24'h004000 && i_addr < 24'h008000; assign use_rom = i_addr < 24'h004000; //assign o_data = {rdata3, rdata2, rdata1, rdata0}; assign o_we = !i_dir && i_act != 2'b00; initial begin $readmemh("/Users/car/Projects/hope/srom.hex", srom); end always @(posedge i_clk, posedge i_rst) begin if (i_rst) o_stb <= 0; else if (~o_stb) o_stb <= (i_act != 2'b00); else o_stb <= 0; end always @(posedge i_clk, posedge i_rst) begin if (i_rst) begin rdata0 <= 8'd0; rdata1 <= 8'd0; rdata2 <= 8'd0; rdata3 <= 8'd0; mdata <= 32'd0; end else begin if (wram0) sram0[waddr] <= data0; if (wram1) sram1[waddr] <= wdata1; if (wram2) sram2[waddr] <= wdata2; if (wram3) sram3[waddr] <= wdata3; rdata0 <= sram0[waddr]; rdata1 <= sram1[waddr]; rdata2 <= sram2[waddr]; rdata3 <= sram3[waddr]; mdata <= srom[waddr]; end // else: !if(i_rst) end always @(*) begin /*if (i_rst) begin for (i = 0; i < 20; i = i + 1) begin sram0[i] = 0; sram1[i] = 0; sram2[i] = 0; sram3[i] = 0; end end else */ if (i_dir && use_ram && i_act != 2'b00) begin case (i_act) 2'b01: begin /* write word */ {wram3, wram2, wram1, wram0} = 4'b1111; {wdata3, wdata2, wdata1} = {data3, data2, data1}; end 2'b10: begin /* write half-word */ {wdata3, wdata2, wdata1} = {data1, data0, data1}; if (i_addr[1]) begin {wram3, wram2, wram1, wram0} = 4'b1100; end else begin {wram3, wram2, wram1, wram0} = 4'b0011; end end 2'b11: begin /* write byte */ {wdata3, wdata2, wdata1} = {data0, data0, data0}; case (i_addr[1:0]) 2'b00: begin {wram3, wram2, wram1, wram0} = 4'b0001; end 2'b01: begin {wram3, wram2, wram1, wram0} = 4'b0010; end 2'b10: begin {wram3, wram2, wram1, wram0} = 4'b0100; end 2'b11: begin {wram3, wram2, wram1, wram0} = 4'b1000; end endcase // case (i_addr[1:0]) end // case: 2'b11 default: begin {wram3, wram2, wram1, wram0} = 4'b0000; {wdata3, wdata2, wdata1} = 24'd0; end endcase // case (i_act) end else begin // if (i_dir && use_ram && i_act != 2'b00) {wram3, wram2, wram1, wram0} = 4'b0000; {wdata3, wdata2, wdata1} = {data0, data0, data0}; end end // always @ (posedge i_clk, posedge i_rst) always @(*) begin if (!i_dir && use_ram) begin /* SRAM */ case (i_act) 2'b00: begin /* nop */ o_data = 32'd0; end 2'b01: begin /* read word */ o_data = {rdata3, rdata2, rdata1, rdata0}; end 2'b10: begin /* read half-word */ o_data[15:0] = i_addr[1] ? {rdata3, rdata2} : {rdata1, rdata0}; o_data[31:16] = 16'd0; end 2'b11: begin /* read byte */ o_data[7:0] = (i_addr[1:0] == 2'b00) ? rdata0 : (i_addr[1:0] == 2'b01) ? rdata1 : (i_addr[1:0] == 2'b10) ? rdata2 : rdata3; o_data[31:8] = 24'd0; end endcase end else if (!i_dir && use_rom) begin case (i_act) 2'b00: begin /* nop */ o_data = 32'd0; end 2'b01: begin /* read word */ o_data = mdata; end 2'b10: begin /* read half-word */ o_data = {16'd0, (i_addr[1] ? mdata[31:16] : mdata[15:0])}; end 2'b11: begin /* read byte */ o_data = {24'd0, ((i_addr[1:0] == 2'b00) ? mdata[7:0] : (i_addr[1:0] == 2'b01) ? mdata[15:8] : (i_addr[1:0] == 2'b10) ? mdata[23:16] : mdata[31:24])}; end endcase end else o_data = mdata; // if (use_rom) end // always @ (posedge i_clk, posedge i_rst) initial begin // Simple test: PUSHB 0x42, infinite loop //mem[0] = 8'h10; // PUSHB (opcode bits[7:3] = 2 → entry 2 → pushb) //mem[1] = 8'h42; // immediate value //mem[2] = 8'h10; // PUSHB again //mem[3] = 8'h33; // different value // After this, will fetch garbage and execute nop/fetch end endmodule