Created
March 14, 2020 20:04
-
-
Save jdesiloniz/1ed9fdfafbb535c52ecc912d638c57bb to your computer and use it in GitHub Desktop.
A draft for a breakpoint controller unit within a CPU debugger component
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
`default_nettype none | |
module breakpoint_controller #(parameter AW = 16)( | |
input wire clk, | |
input wire rstn, | |
input wire [AW-1:0] address, // Address to check/write/clear | |
input wire read_stb, // Strobe for check a breakpoint | |
input wire write_stb, // Strobe for writing a breakpoint | |
input wire clear_stb, // Strobe for clearing a breakpoint | |
output wire read_result // Result of a breakpoint check (1 = yup), active next cycle after read_stb | |
); | |
// Each register holds an breakpoint associated to an address. MSB is 1 if the | |
// breakpoint is active. | |
reg [AW:0] br0; | |
reg [AW:0] br1; | |
reg [AW:0] br2; | |
reg [AW:0] br3; | |
reg [AW:0] br4; | |
reg [AW:0] br5; | |
reg [AW:0] br6; | |
reg [AW:0] br7; | |
reg read_result; | |
wire [7:0] active_breakpoint_bits; | |
assign active_breakpoint_bits = {br0[AW], br1[AW], br2[AW], br3[AW], br4[AW], br5[AW], br6[AW], br7[AW]}; | |
always @(posedge clk) begin | |
if (rstn == 1'b0) begin | |
// Initial values: | |
br0 <= 0; | |
br1 <= 0; | |
br2 <= 0; | |
br3 <= 0; | |
br4 <= 0; | |
br5 <= 0; | |
br6 <= 0; | |
br7 <= 0; | |
read_result <= 1'b0; | |
end else begin | |
// A breakpoint controller isn't meant to be used by multiple components, | |
// or to perform two operations at once. | |
// Checking for a breakpoint: | |
if (read_stb == 1'b1) begin | |
if (br0 == {1'b1, address}) | |
read_result <= 1'b1; | |
else if (br1 == {1'b1, address}) | |
read_result <= 1'b1; | |
else if (br2 == {1'b1, address}) | |
read_result <= 1'b1; | |
else if (br3 == {1'b1, address}) | |
read_result <= 1'b1; | |
else if (br4 == {1'b1, address}) | |
read_result <= 1'b1; | |
else if (br5 == {1'b1, address}) | |
read_result <= 1'b1; | |
else if (br6 == {1'b1, address}) | |
read_result <= 1'b1; | |
else if (br7 == {1'b1, address}) | |
read_result <= 1'b1; | |
else read_result <= 1'b0; | |
end else if (write_stb == 1'b1) begin | |
// Writing a breakpoint | |
// Each breakpoint register's MSB is 0 if inactive or 1 if active. So if we | |
// get all these bits together we can know which breakpoint is the "oldest inactive", | |
// and we use that spot to write a new one: | |
case (active_breakpoint_bits) | |
8'h00: br0 <= {1'b1, address}; | |
8'h80: br1 <= {1'b1, address}; | |
8'hC0: br2 <= {1'b1, address}; | |
8'hE0: br3 <= {1'b1, address}; | |
8'hF0: br4 <= {1'b1, address}; | |
8'hF8: br5 <= {1'b1, address}; | |
8'hFC: br6 <= {1'b1, address}; | |
8'hFE: br7 <= {1'b1, address}; | |
8'hFF: begin | |
// If all breakpoints are in use, we sacrifice the oldest one (br0) | |
// and write the new one in br7. | |
br0 <= br1; | |
br1 <= br2; | |
br2 <= br3; | |
br3 <= br4; | |
br4 <= br5; | |
br5 <= br6; | |
br6 <= br7; | |
br7 <= {1'b1, address}; | |
end | |
endcase // active_breakpoint_bits | |
end else if (clear_stb == 1'b1) begin | |
// Clearing a breakpoint | |
// Depending of its position, if we find a breakpoint to clear it'll | |
// imply more or less breakpoint registers to move around. | |
// Key is to keep all "active" breakpoints as a contiguous set of registers. | |
if (br0 == {1'b1, address}) begin | |
br0 <= br1; | |
br1 <= br2; | |
br2 <= br3; | |
br3 <= br4; | |
br4 <= br5; | |
br5 <= br6; | |
br6 <= br7; | |
br7 <= AW'b0; | |
end else if (br1 == {1'b1, address}) begin | |
br1 <= br2; | |
br2 <= br3; | |
br3 <= br4; | |
br4 <= br5; | |
br5 <= br6; | |
br6 <= br7; | |
br7 <= AW'b0; | |
end else if (br2 == {1'b1, address}) begin | |
br2 <= br3; | |
br3 <= br4; | |
br4 <= br5; | |
br5 <= br6; | |
br6 <= br7; | |
br7 <= AW'b0; | |
end else if (br3 == {1'b1, address}) begin | |
br3 <= br4; | |
br4 <= br5; | |
br5 <= br6; | |
br6 <= br7; | |
br7 <= AW'b0; | |
end else if (br4 == {1'b1, address}) begin | |
br4 <= br5; | |
br5 <= br6; | |
br6 <= br7; | |
br7 <= AW'b0; | |
end else if (br5 == {1'b1, address}) begin | |
br5 <= br6; | |
br6 <= br7; | |
br7 <= AW'b0; | |
end else if (br6 == {1'b1, address}) begin | |
br6 <= br7; | |
br7 <= AW'b0; | |
end else if (br7 == {1'b1, address}) begin | |
br7 <= AW'b0; | |
end | |
end | |
end | |
end | |
endmodule |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment