diff --git a/rtl/verilog/qm_icache.v b/rtl/verilog/qm_icache.v index 3b1a7c1..e0cf974 100644 --- a/rtl/verilog/qm_icache.v +++ b/rtl/verilog/qm_icache.v @@ -8,8 +8,11 @@ module qm_icache( output wire hit, output wire stall, output wire [31:0] data, + input wire enable, // to the memory controller (no wishbone yet...) + // the cache is currently only backed in 1GBit RAM via this controller + // this RAM is mapped 0x80000000 - 0x90000000 output wire mem_cmd_clk, // we will keep this synchronous to the input clock output wire mem_cmd_en, output wire [2:0] mem_cmd_instr, @@ -67,26 +70,40 @@ always @(posedge clk) begin mem_cmd_en <= 0; mem_cmd_bl <= 0; mem_cmd_instr <= 0; + mem_cmd_addr <= 0; mem_rd_en <= 0; end end // read condition -always @(address) begin - if (index_valid == valid_bit && index_tag == address_tag) begin - if (address_word == 2'b00) - data = lines[index][31:0]; - else if (address_word == 2'b01) - data = lines[index][63:32]; - else if (address_word == 2'b10) - data = lines[index][95:64]; - else - data = lines[index][127:96]; - hit = 1; - stall = 0; +always @(address, lines) begin + if (enable) begin + // is this in the RAM region? + if (32'h80000000 <= address && address < 32'h90000000) begin + // do we have a hit? + if (index_valid == valid_bit && index_tag == address_tag) begin + if (address_word == 2'b00) + data = lines[index][31:0]; + else if (address_word == 2'b01) + data = lines[index][63:32]; + else if (address_word == 2'b10) + data = lines[index][95:64]; + else + data = lines[index][127:96]; + hit = 1; + stall = 0; + end else begin + hit = 0; + stall = 1; + end + end else begin + hit = 1; + stall = 0; + data = 32'h00000000; + end end else begin hit = 0; - stall = 1; + stall = 0; end end @@ -94,12 +111,12 @@ end // read memory and provide it data reg [2:0] memory_read_state; always @(posedge clk) begin - if (stall && !reset) begin + if (stall && !reset && enable) begin case (memory_read_state) 0: begin // assert command mem_cmd_instr <= 1; // read - mem_cmd_bl <= 4; // four words - mem_cmd_addr <= address[29:0]; // from the address we are being asserted + mem_cmd_bl <= 3; // four words + mem_cmd_addr <= {1'b0, address[28:0]}; mem_cmd_en <= 0; memory_read_state <= 1; end diff --git a/test/test_icache.cpp b/test/test_icache.cpp index 66df39b..d6434e8 100644 --- a/test/test_icache.cpp +++ b/test/test_icache.cpp @@ -4,10 +4,82 @@ #include "Vqm_icache.h" + + +void simulate_memory_controller(Vqm_icache *ic) +{ + static unsigned int latched_cmd_instr; + static unsigned int latched_cmd_bl; + static unsigned int latched_cmd_addr; + static int previous_cmd_clock = 0; + static int previous_rd_clock = 0; + + //printf("[mem ctrl] clk %i, ci 0x%01x, cb %i, ca %08x, ce %i\n", + // ic->mem_cmd_clk, ic->mem_cmd_instr, ic->mem_cmd_bl, ic->mem_cmd_addr, ic->mem_cmd_en); + + static struct { + int instr = -1; + unsigned int left = 0; + unsigned int addr = 0; + } current_command; + if (previous_cmd_clock == 0 && ic->mem_cmd_clk == 1) + { + // simulate rising edge of command clock + if (ic->mem_cmd_en) + { + printf("[mem ctrl] got command 0x%01x with bi %i and addres %08x\n", + latched_cmd_instr, latched_cmd_bl, latched_cmd_addr); + current_command.instr = latched_cmd_instr; + current_command.left = latched_cmd_bl + 1; + current_command.addr = latched_cmd_addr; + + ic->mem_cmd_empty = 0; + } + + latched_cmd_instr = ic->mem_cmd_instr; + latched_cmd_bl = ic->mem_cmd_bl; + latched_cmd_addr = ic->mem_cmd_addr; + } + if (previous_rd_clock == 0 && ic->mem_cmd_clk == 1) + { + // simulate read + if (ic->mem_rd_en) + { + if (current_command.instr == 0x01) + { + if (current_command.left == 0) + { + current_command.instr = -1; + ic->mem_rd_empty = 1; + printf("[mem ctrl] command end\n"); + } + else + { + printf("[mem ctrl] command word, %i left\n", current_command.left-1); + ic->mem_rd_data = 0xF0000000 + current_command.addr; + ic->mem_rd_empty = 0; + current_command.left--; + } + } + } + } + + previous_cmd_clock = ic->mem_cmd_clk; + previous_rd_clock = ic->mem_rd_clk; +} + void test_icache(void) { Vqm_icache *icache = new Vqm_icache; + icache->mem_cmd_full = 0; + icache->mem_cmd_empty = 1; + icache->mem_rd_full = 0; + icache->mem_rd_empty = 1; + icache->mem_rd_count = 0; + icache->address = 0; + icache->enable = 0; + // reset icache->reset = 1; icache->clk = 0; @@ -19,12 +91,24 @@ void test_icache(void) icache->eval(); icache->clk = 1; icache->eval(); - - icache->address = 0xdeadbeef; icache->clk = 0; icache->eval(); - icache->clk = 1; - icache->eval(); - printf("Cache hit: %i Pipeline stall: %i\n", icache->hit, icache->stall); + unsigned int counter = 0; + while (1) + { + if (counter == 10) + icache->enable = 1; + icache->address = 0x80bedead; + if (counter > 100) + break; + icache->clk = !icache->clk; + icache->eval(); + + printf("[cache input] a: %08x\n", icache->address); + printf("[cache status] hit: %i, stall: %i, data %08x\n", + icache->hit, icache->stall, icache->data); + simulate_memory_controller(icache); + counter++; + } }