mailbox_wb_sw2rtl.v 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  1. /*
  2. * mailbox_wb.v
  3. *
  4. * vim: ts=4 sw=4
  5. *
  6. * Copyright (C) 2025 Krzysztof Skrzynecki, Jakub Duchniewicz <j.duchniewicz@gmail.com>
  7. * SPDX-License-Identifier: TODO:
  8. */
  9. `default_nettype none
  10. module mailbox_wb_sw2rtl #(
  11. parameter AW = 4, // Address width for 16 registers (4 bits)
  12. parameter DW = 32 // Data width for the Wishbone interface (32 bits)
  13. )(
  14. input wire clk,
  15. input wire rst,
  16. // Wishbone Interface
  17. input wire [AW-1:0] wb_addr,
  18. input wire [DW-1:0] wb_wdata,
  19. output reg [DW-1:0] wb_rdata,
  20. input wire wb_we,
  21. input wire wb_cyc,
  22. output reg wb_ack,
  23. input wire write_flash, // TODO: this is a hack - ideally we would have a better mailbox design
  24. // Flattened custom hardware side (RTL)
  25. output wire [16*16-1:0] registers_flat // Flattened register array (16 registers of 16 bits each)
  26. );
  27. // Internal registers (16 registers, each 16 bits wide)
  28. reg [15:0] registers_array[15:0];
  29. // Always reset the registers on reset signal
  30. integer i;
  31. always @(posedge clk or posedge rst) begin
  32. if (rst) begin
  33. wb_ack <= 1'b0;
  34. for (i = 0; i < 16; i = i + 1) begin
  35. registers_array[i] <= 16'h0; // Reset all registers to 0
  36. end
  37. end else begin
  38. // Default no ack
  39. wb_ack <= 1'b0;
  40. if (wb_cyc) begin
  41. // Write operation (if write enable is active) // wb_stb would
  42. // help here
  43. if (wb_we) begin
  44. case (wb_addr)
  45. 4'b0000: registers_array[0] <= wb_wdata[15:0]; // Only use lower 16 bits
  46. 4'b0001: registers_array[1] <= wb_wdata[15:0];
  47. 4'b0010: registers_array[2] <= wb_wdata[15:0];
  48. 4'b0011: registers_array[3] <= wb_wdata[15:0];
  49. 4'b0100: registers_array[4] <= wb_wdata[15:0];
  50. 4'b0101: registers_array[5] <= wb_wdata[15:0];
  51. 4'b0110: registers_array[6] <= wb_wdata[15:0];
  52. 4'b0111: registers_array[7] <= wb_wdata[15:0];
  53. 4'b1000: registers_array[8] <= wb_wdata[15:0];
  54. 4'b1001: registers_array[9] <= wb_wdata[15:0];
  55. 4'b1010: registers_array[10] <= wb_wdata[15:0];
  56. 4'b1011: registers_array[11] <= wb_wdata[15:0];
  57. 4'b1100: registers_array[12] <= wb_wdata[15:0];
  58. 4'b1101: registers_array[13] <= wb_wdata[15:0];
  59. 4'b1110: registers_array[14] <= wb_wdata[15:0];
  60. 4'b1111: registers_array[15] <= wb_wdata[15:0];
  61. endcase
  62. end
  63. // Force write 1 to regiser[9] - to write mailbox values to flash
  64. if (write_flash) begin
  65. registers_array[9] <= 32'h1;
  66. end
  67. // Read operation (read the correct register based on address)
  68. case (wb_addr)
  69. 4'b0000: wb_rdata <= {16'h0, registers_array[0]}; // Place 16-bit value in lower half of 32-bit bus
  70. 4'b0001: wb_rdata <= {16'h0, registers_array[1]};
  71. 4'b0010: wb_rdata <= {16'h0, registers_array[2]};
  72. 4'b0011: wb_rdata <= {16'h0, registers_array[3]};
  73. 4'b0100: wb_rdata <= {16'h0, registers_array[4]};
  74. 4'b0101: wb_rdata <= {16'h0, registers_array[5]};
  75. 4'b0110: wb_rdata <= {16'h0, registers_array[6]};
  76. 4'b0111: wb_rdata <= {16'h0, registers_array[7]};
  77. 4'b1000: wb_rdata <= {16'h0, registers_array[8]};
  78. 4'b1001: wb_rdata <= {16'h0, registers_array[9]};
  79. 4'b1010: wb_rdata <= {16'h0, registers_array[10]};
  80. 4'b1011: wb_rdata <= {16'h0, registers_array[11]};
  81. 4'b1100: wb_rdata <= {16'h0, registers_array[12]};
  82. 4'b1101: wb_rdata <= {16'h0, registers_array[13]};
  83. 4'b1110: wb_rdata <= {16'h0, registers_array[14]};
  84. 4'b1111: wb_rdata <= {16'h0, registers_array[15]};
  85. default: wb_rdata <= 32'hDEAD_BEEF; // Default error value
  86. endcase
  87. // Acknowledge for exactly 1 cycle
  88. wb_ack <= 1'b1;
  89. end
  90. end
  91. end
  92. // Flatten the registers array to the output port (registers_flat)
  93. generate
  94. genvar j;
  95. for (j = 0; j < 16; j = j + 1) begin : flatten
  96. assign registers_flat[16*(j+1)-1:16*j] = registers_array[j];
  97. end
  98. endgenerate
  99. endmodule