`timescale 1ns/1ps
module oc8051_ice(
input wire i_clk,
input wire i_nrst,
output wire o_led4,
output wire o_led3,
output wire o_led2,
output wire o_led1,
output wire o_led0
);
parameter ROM_BYTES = 82;
parameter RAM_BYTES = 20;
// ROM
reg [7:0] rom [0:ROM_BYTES-1];
wire [15:0] rom_addr;
wire [$clog2(ROM_BYTES):0] rom_addr_crop;
wire rom_stb;
reg [31:0] rom_data;
reg rom_ack;
assign rom_addr_crop = rom_addr[$clog2(ROM_BYTES)-1:0];
// RAM
reg [7:0] ram [0:RAM_BYTES-1];
wire [15:0] ram_addr;
wire [7:0] ram_data_in;
reg [7:0] ram_data_out;
reg ram_ackw;
reg ram_ackr;
wire ram_ack;
wire ram_wr;
// LEDs
assign o_led0 = ram[0][0];
assign o_led1 = ram[0][1];
assign o_led2 = ram[0][2];
assign o_led3 = ram[0][3];
assign o_led4 = ram[0][4];
oc8051 oc8051_top_1(
.wb_rst_i (~i_nrst ),
.wb_clk_i (i_clk ),
// XRAM
.wbd_dat_i (ram_data_out ),
.wbd_we_o (ram_wr ),
.wbd_dat_o (ram_data_in ),
.wbd_adr_o (ram_addr ),
.wbd_err_i (1'b0 ),
.wbd_ack_i (ram_ack ),
.wbd_stb_o (ram_stb ),
.wbd_cyc_o ( ),
// ROM
.wbi_adr_o (rom_addr ),
.wbi_stb_o (rom_stb ),
.wbi_ack_i (rom_ack ),
.wbi_cyc_o ( ),
.wbi_dat_i (rom_data ),
.wbi_err_i (1'b0 ),
// Internal RAM
.rd_addr (rd_addr ),
.wr_addr (wr_addr ),
.wr_dat (wr_data ),
.ram_data (rd_data ),
.desCy (bit_data_in ),
.bit_data (bit_data_out ),
.wr_ram (wr ),
.bit_addr_o (bit_addr )
);
////////////////////////////////////////////////////////////////////////////
// Internal RAM
wire [7:0] rd_addr;
wire [7:0] wr_addr;
wire [7:0] wr_data;
wire [7:0] rd_data;
wire bit_data_in;
wire bit_data_out;
wire wr;
wire bit_addr;
reg [7:0] wr_data_m;
reg [7:0] rd_addr_m,
wr_addr_m;
wire rd_en;
reg bit_addr_r,
rd_en_r;
reg [7:0] wr_data_r;
reg [7:0] rd_data_m;
reg [2:0] bit_select;
reg [7:0] buff [0:256];
assign bit_data_out = rd_data[bit_select];
assign rd_data = rd_en_r ? wr_data_r: rd_data_m;
assign rd_en = (rd_addr_m == wr_addr_m) & wr;
//
// writing to ram
always @(posedge i_clk)
begin
if (wr)
buff[wr_addr_m] <= wr_data_m;
end
//
// reading from ram
always @(posedge i_clk or negedge i_nrst)
begin
if (!i_nrst)
rd_data_m <= 8'h0;
else if ((wr_addr_m==rd_addr_m) & wr & !rd_en)
rd_data_m <= wr_data_m;
else if (!rd_en)
rd_data_m <= buff[rd_addr_m];
end
always @(posedge i_clk or negedge i_nrst)
if (!i_nrst) begin
bit_addr_r <= 1'b0;
bit_select <= 3'b0;
end else begin
bit_addr_r <= bit_addr;
bit_select <= rd_addr[2:0];
end
always @(posedge i_clk or negedge i_nrst)
if (!i_nrst) begin
rd_en_r <= 1'b0;
wr_data_r <= 8'h0;
end else begin
rd_en_r <= rd_en;
wr_data_r <= wr_data_m;
end
always @(rd_addr or bit_addr)
casex ( {bit_addr, rd_addr[7]} )
2'b0?: rd_addr_m = rd_addr;
2'b10: rd_addr_m = {4'b0010, rd_addr[6:3]};
2'b11: rd_addr_m = {1'b1, rd_addr[6:3], 3'b000};
endcase
always @(wr_addr or bit_addr_r)
casex ( {bit_addr_r, wr_addr[7]} )
2'b0?: wr_addr_m = wr_addr;
2'b10: wr_addr_m = {8'h00, 4'b0010, wr_addr[6:3]};
2'b11: wr_addr_m = {8'h00, 1'b1, wr_addr[6:3], 3'b000};
endcase
always @(rd_data or bit_select or bit_data_in or wr_data or bit_addr_r)
casex ( {bit_addr_r, bit_select} )
4'b0_???: wr_data_m = wr_data;
4'b1_000: wr_data_m = {rd_data[7:1], bit_data_in};
4'b1_001: wr_data_m = {rd_data[7:2], bit_data_in, rd_data[0]};
4'b1_010: wr_data_m = {rd_data[7:3], bit_data_in, rd_data[1:0]};
4'b1_011: wr_data_m = {rd_data[7:4], bit_data_in, rd_data[2:0]};
4'b1_100: wr_data_m = {rd_data[7:5], bit_data_in, rd_data[3:0]};
4'b1_101: wr_data_m = {rd_data[7:6], bit_data_in, rd_data[4:0]};
4'b1_110: wr_data_m = {rd_data[7], bit_data_in, rd_data[5:0]};
4'b1_111: wr_data_m = {bit_data_in, rd_data[6:0]};
endcase
////////////////////////////////////////////////////////////////////////////
// RAM
assign ram_ack = ram_ackw | ram_ackr;
always @(posedge i_clk or negedge i_nrst) begin
if (!i_nrst) begin
ram_ackw <= 1'b0;
end else begin
if (ram_wr && ram_stb) begin
ram[ram_addr] <= ram_data_in;
ram_ackw <= 1'b1;
end else begin
ram_ackw <= 1'b0;
end
end
end
always @(posedge i_clk or negedge i_nrst) begin
if (!i_nrst) begin
ram_ackr <= 1'b0;
end else begin
if (ram_stb && !ram_wr) begin
ram_data_out <= ram[ram_addr];
ram_ackr <= 1'b1;
end else begin
ram_ackr <= 1'b0;
ram_data_out <= 8'h00;
end
end
end
////////////////////////////////////////////////////////////////////////////
// ROM
always @(posedge i_clk or negedge i_nrst) begin
if (!i_nrst) begin
rom_data <= 31'h0;
rom_ack <= 1'b0;
// Code - leds
rom[0] <= 8'h04; // label: inc A
rom[1] <= 8'h90; // mov DPTR, #0x00
rom[2] <= 8'h00; //
rom[3] <= 8'h00; //
rom[4] <= 8'hF0; // movx @DPTR, A
rom[5] <= 8'h80; // sjmp label
rom[6] <= 8'hF9; //
rom[7] <= 8'h00; //
// Code - fib
rom[0] <= 8'h7F;
rom[1] <= 8'h00;
rom[2] <= 8'h8F;
rom[3] <= 8'h82;
rom[4] <= 8'hC0;
rom[5] <= 8'h07;
rom[6] <= 8'h12;
rom[7] <= 8'h00;
rom[8] <= 8'h21;
rom[9] <= 8'hE5;
rom[10] <= 8'h82;
rom[11] <= 8'hD0;
rom[12] <= 8'h07;
rom[13] <= 8'h90;
rom[14] <= 8'h00;
rom[15] <= 8'h00;
rom[16] <= 8'hF0;
rom[17] <= 8'h0F;
rom[18] <= 8'hC3;
rom[19] <= 8'hEF;
rom[20] <= 8'h64;
rom[21] <= 8'h80;
rom[22] <= 8'h94;
rom[23] <= 8'h85;
rom[24] <= 8'h40;
rom[25] <= 8'hE8;
rom[26] <= 8'h74;
rom[27] <= 8'h7F;
rom[28] <= 8'h90;
rom[29] <= 8'h00;
rom[30] <= 8'h10;
rom[31] <= 8'hF0;
rom[32] <= 8'h22;
rom[33] <= 8'hE5;
rom[34] <= 8'h82;
rom[35] <= 8'hFF;
rom[36] <= 8'h70;
rom[37] <= 8'h03;
rom[38] <= 8'hF5;
rom[39] <= 8'h82;
rom[40] <= 8'h22;
rom[41] <= 8'hBF;
rom[42] <= 8'h01;
rom[43] <= 8'h04;
rom[44] <= 8'h75;
rom[45] <= 8'h82;
rom[46] <= 8'h01;
rom[47] <= 8'h22;
rom[48] <= 8'hEF;
rom[49] <= 8'h14;
rom[50] <= 8'hF5;
rom[51] <= 8'h82;
rom[52] <= 8'hC0;
rom[53] <= 8'h07;
rom[54] <= 8'h12;
rom[55] <= 8'h00;
rom[56] <= 8'h21;
rom[57] <= 8'hAE;
rom[58] <= 8'h82;
rom[59] <= 8'hD0;
rom[60] <= 8'h07;
rom[61] <= 8'hEF;
rom[62] <= 8'h24;
rom[63] <= 8'hFE;
rom[64] <= 8'hF5;
rom[65] <= 8'h82;
rom[66] <= 8'hC0;
rom[67] <= 8'h06;
rom[68] <= 8'h12;
rom[69] <= 8'h00;
rom[70] <= 8'h21;
rom[71] <= 8'hAF;
rom[72] <= 8'h82;
rom[73] <= 8'hD0;
rom[74] <= 8'h06;
rom[75] <= 8'hEF;
rom[76] <= 8'h2E;
rom[77] <= 8'hF5;
rom[78] <= 8'h82;
rom[79] <= 8'h22;
rom[80] <= 8'h00;
rom[81] <= 8'h00;
end else begin
if (rom_stb) begin
rom_data <= { rom[rom_addr_crop+3],
rom[rom_addr_crop+2],
rom[rom_addr_crop+1],
rom[rom_addr_crop] };
rom_ack <= 1'b1;
end else begin
rom_ack <= 1'b0;
end
end
end
endmodule