oisc.sv 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187
  1. `define DWIDTH 8 // Data bus width
  2. `define DAWIDTH 4 // Dest. address width
  3. `define SAWIDTH 8 // Src. address width
  4. package oisc8_pkg;
  5. typedef enum logic [`DAWIDTH-1:0] {
  6. ALUACC0 ='d0,
  7. ALUACC1 ='d1,
  8. BRPT0 ='d2,
  9. BRPT1 ='d3,
  10. BRZ ='d4,
  11. STACK ='d5,
  12. MEMPT0 ='d6,
  13. MEMPT1 ='d7,
  14. MEMPT2 ='d8,
  15. MEMSWHI ='d9,
  16. MEMSWLO ='d10,
  17. COMA ='d11,
  18. COMD ='d12
  19. } e_iaddr_dst; // destination enum
  20. typedef enum logic [`SAWIDTH-1:0] {
  21. NULL ='d0,
  22. // ALU BLOCK
  23. ALUACC0R='d1,
  24. ALUACC1R='d2,
  25. ADD ='d3,
  26. ADDC ='d4,
  27. SUB ='d5,
  28. SUBC ='d6,
  29. AND ='d7,
  30. OR ='d8,
  31. XOR ='d9,
  32. SLL ='d11,
  33. SRL ='d12,
  34. EQ ='d13,
  35. GT ='d14,
  36. GE ='d15,
  37. MULLO ='d16,
  38. MULHI ='d17,
  39. DIV ='d18,
  40. MOD ='d19,
  41. // Program Counter
  42. BRPT0R ='d20,
  43. BRPT1R ='d21,
  44. // Memory
  45. MEMPT0R ='d22,
  46. MEMPT1R ='d23,
  47. MEMPT2R ='d24,
  48. MEMLWHI ='d25,
  49. MEMLWLO ='d26,
  50. STACKR ='d27,
  51. STPT0R ='d28,
  52. STPT1R ='d29,
  53. // COM
  54. COMAR ='d30,
  55. COMDR ='d31
  56. } e_iaddr_src; // source enum
  57. endpackage
  58. interface IBus(clk, rst, data, instr);
  59. import oisc8_pkg::*;
  60. input logic clk, rst;
  61. inout wire[`DWIDTH-1:0] data;
  62. input wire[`SAWIDTH+`DAWIDTH:0] instr;
  63. logic imm;
  64. e_iaddr_dst instr_dst;
  65. e_iaddr_src instr_src;
  66. assign imm = instr[`DAWIDTH+`SAWIDTH];
  67. assign instr_dst = e_iaddr_dst'(instr[`DAWIDTH+`SAWIDTH-1:`SAWIDTH]);
  68. assign instr_src = e_iaddr_src'(instr[`SAWIDTH-1:0]);
  69. endinterface
  70. module PortReg(bus, data_from_bus, data_to_bus, rd, wr);
  71. import oisc8_pkg::*;
  72. IBus bus;
  73. output logic[`DWIDTH-1:0] data_from_bus;
  74. input logic[`SAWIDTH-1:0] data_to_bus;
  75. output reg rd, wr;
  76. parameter ADDR_SRC = e_iaddr_src'(0);
  77. parameter ADDR_DST = e_iaddr_dst'(0);
  78. parameter DEFAULT = `DWIDTH'd0;
  79. reg [`SAWIDTH-1:0] data;
  80. always_comb casez({bus.imm,bus.rst})
  81. 2'b00: data = bus.data[`SAWIDTH-1:0];
  82. 2'b10: data = bus.instr_src;
  83. 2'b?1: data = DEFAULT;
  84. endcase
  85. assign wr = bus.instr_dst == ADDR_DST;
  86. assign rd = bus.instr_src == ADDR_SRC;
  87. assign bus.data = rd ? data_to_bus : 'bZ;
  88. always_ff@(posedge bus.clk) begin
  89. if(bus.rst) data_from_bus <= DEFAULT;
  90. else if(wr) data_from_bus <= data;
  91. end
  92. endmodule
  93. module PortRegSeq(bus, data_from_bus, data_to_bus, rd, wr);
  94. import oisc8_pkg::*;
  95. IBus bus;
  96. output logic[`DWIDTH-1:0] data_from_bus;
  97. input logic[`SAWIDTH-1:0] data_to_bus;
  98. output reg rd, wr;
  99. parameter ADDR_SRC = e_iaddr_src'(0);
  100. parameter ADDR_DST = e_iaddr_dst'(0);
  101. parameter DEFAULT = `DWIDTH'd0;
  102. reg [`SAWIDTH-1:0] data, latch;
  103. always_comb casez({bus.imm,bus.rst})
  104. 2'b00: data = bus.data[`SAWIDTH-1:0];
  105. 2'b10: data = bus.instr_src;
  106. 2'b?1: data = DEFAULT;
  107. endcase
  108. assign wr = bus.instr_dst == ADDR_DST;
  109. assign rd = bus.instr_src == ADDR_SRC;
  110. assign bus.data = rd ? data_to_bus : 'bZ;
  111. assign data_from_bus = wr ? data : latch;
  112. always_ff@(posedge bus.clk) begin
  113. if(bus.rst) latch <= DEFAULT;
  114. else if(wr) latch <= data;
  115. end
  116. endmodule
  117. module PortInput(bus, data_from_bus, wr, rst);
  118. import oisc8_pkg::*;
  119. IBus bus;
  120. output reg[`DWIDTH-1:0] data_from_bus;
  121. output reg wr;
  122. input reg rst;
  123. parameter ADDR = e_iaddr_dst'(0);
  124. parameter DEFAULT = `DWIDTH'd0;
  125. reg [`SAWIDTH-1:0] data;
  126. assign data = bus.imm ? bus.instr_src : bus.data[`SAWIDTH-1:0];
  127. assign wr = bus.instr_dst == ADDR;
  128. always_ff@(posedge bus.clk) begin
  129. if(bus.rst|rst)
  130. data_from_bus <= DEFAULT;
  131. else
  132. data_from_bus <= wr ? data : data_from_bus;
  133. end
  134. endmodule
  135. module PortInputSeq(bus, data_from_bus, wr);
  136. import oisc8_pkg::*;
  137. IBus bus;
  138. output reg[`DWIDTH-1:0] data_from_bus;
  139. output reg wr;
  140. parameter ADDR = e_iaddr_dst'(0);
  141. parameter DEFAULT = `DWIDTH'd0;
  142. reg [`SAWIDTH-1:0] data;
  143. assign data = bus.imm ? bus.instr_src : bus.data[`SAWIDTH-1:0];
  144. assign wr = bus.instr_dst == ADDR;
  145. assign data_from_bus = wr ? data : DEFAULT;
  146. endmodule
  147. module PortOutput(bus, data_to_bus, rd);
  148. import oisc8_pkg::*;
  149. IBus bus;
  150. input reg[`SAWIDTH-1:0] data_to_bus;
  151. output reg rd;
  152. parameter ADDR = e_iaddr_src'(0);
  153. assign rd = bus.instr_src == ADDR;
  154. assign bus.data = rd ? data_to_bus : 'bZ;
  155. endmodule