Files
stack/sram_srom.v
2026-03-07 23:45:11 -05:00

207 lines
5.0 KiB
Verilog

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