207 lines
5.0 KiB
Verilog
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
|