Facebook
From Diminutive Matamata, 3 Years ago, written in Plain Text.
Embed
Download Paste or View Raw
Hits: 80
  1. `include "defines.vh"
  2.         module control_unit #(
  3.                 parameter  INSTR_WIDTH = 16,   // instructions are 16 bits in width
  4.                 parameter   DATA_WIDTH = 8,    // registers are 8 bits in width
  5.                 parameter I_ADDR_WIDTH = 10,   // 2*1024 bytes of flash (or ROM in our case)
  6.                 parameter   ADDR_WIDTH = 16,   // 64KB address space
  7.                 parameter R_ADDR_WIDTH = 5     // 32 registers
  8.         )(
  9.                 input  wire                    clk,
  10.                 input  wire                    reset,
  11.                 // To/from instruction memory
  12.                 output reg  [I_ADDR_WIDTH-1:0] program_counter,
  13.                 input  wire  [INSTR_WIDTH-1:0] instruction,
  14.                 // From FSM
  15.                 // TODO move state and add debug state
  16.                 output wire [`STAGE_COUNT-1:0] pipeline_stage,
  17.                 // To/from register file
  18.                 output wire [R_ADDR_WIDTH-1:0] rr_addr,
  19.                 output wire [R_ADDR_WIDTH-1:0] rd_addr,
  20.                 inout  wire   [DATA_WIDTH-1:0] rr_data,
  21.                 inout  wire   [DATA_WIDTH-1:0] rd_data,
  22.                 output wire                    rr_cs,
  23.                 output wire                    rd_cs,
  24.                 output wire                    rr_we,
  25.                 output wire                    rd_we,
  26.                 output wire                    rr_oe,
  27.                 output wire                    rd_oe,
  28.                 // To/from ALU
  29.                 output wire                    alu_enable,
  30.                 output reg    [`OPSEL_COUNT-1:0] alu_opsel,
  31.                 output wire   [DATA_WIDTH-1:0] alu_flags_in,
  32.                 input  wire   [DATA_WIDTH-1:0] alu_flags_out,
  33.                 output reg    [DATA_WIDTH-1:0] alu_rr,
  34.                 output reg    [DATA_WIDTH-1:0] alu_rd,
  35.                 input  wire   [DATA_WIDTH-1:0] alu_out,
  36.                 // To/from bus interface unit
  37.                 output wire   [ADDR_WIDTH-1:0] bus_addr,
  38.                 inout  wire   [DATA_WIDTH-1:0] bus_data,
  39.                 output wire                    mem_cs,
  40.                 output wire                    mem_we,
  41.                 output wire                    mem_oe
  42. `ifdef DEBUG
  43.                         ,
  44.                         output wire [`OPCODE_COUNT-1:0] debug_opcode_type,
  45.                         output wire [`GROUP_COUNT-1:0] debug_opcode_group,
  46.                         output wire [11:0]  debug_opcode_imd,
  47.                         output wire [DATA_WIDTH-1:0] debug_writeback_value,
  48.                         output wire [`SIGNAL_COUNT-1:0] debug_signals
  49. `endif
  50.         );
  51.         // From decode unit
  52.         wire [`SIGNAL_COUNT-1:0] signals;
  53.         wire [`OPCODE_COUNT-1:0] opcode_type;
  54.         wire [`GROUP_COUNT-1:0] opcode_group;
  55.         wire [R_ADDR_WIDTH-1:0] opcode_rd;
  56.         wire [R_ADDR_WIDTH-1:0] opcode_rr;
  57.         wire              [11:0] opcode_imd;
  58.         wire               [2:0] opcode_bit;
  59.         // Buffers for various stuff
  60.         reg    [INSTR_WIDTH-1:0] instr_buffer;
  61.         reg     [DATA_WIDTH-1:0] alu_out_buffer;
  62.         reg     [DATA_WIDTH-1:0] writeback_value;
  63.         wire    [ADDR_WIDTH-1:0] indirect_addr;
  64.         wire    [DATA_WIDTH-1:0] data_to_store;
  65.         reg     [DATA_WIDTH-1:0] sreg;
  66.  
  67. `ifdef DEBUG
  68.                         assign debug_opcode_type = opcode_type;
  69.                         assign debug_opcode_group = opcode_group;
  70.                         assign debug_opcode_imd = opcode_imd;
  71.                         assign debug_writeback_value = writeback_value;
  72.                         assign debug_signals = signals;
  73. `endif
  74.  
  75.  
  76.  state_machine fsm (
  77.                 .pipeline_stage       (pipeline_stage),
  78.                 .clk         (clk),
  79.                 .reset       (reset)
  80.         );
  81.  
  82.         decode_unit #(
  83.                 .INSTR_WIDTH(INSTR_WIDTH)
  84.         ) decode (
  85.                 .instruction (instr_buffer),
  86.                 .opcode_type (opcode_type),
  87.                 .opcode_group(opcode_group),
  88.                 .opcode_imd  (opcode_imd),
  89.                 .opcode_rd(opcode_rd),
  90.                 .opcode_rr(opcode_rr),
  91.                 .opcode_bit(opcode_bit)
  92.         );
  93.  
  94.         signal_generation_unit sig (
  95.                 .pipeline_stage       (pipeline_stage),
  96.                 .signals (signals),
  97.                 .opcode_type (opcode_type),
  98.                 .opcode_group(opcode_group)
  99.         );
  100.  
  101.         reg_file_interface_unit #(
  102.                 .DATA_WIDTH  (DATA_WIDTH),
  103.                 .INSTR_WIDTH (INSTR_WIDTH),
  104.                 .R_ADDR_WIDTH(R_ADDR_WIDTH)
  105.         ) rf_int (
  106.                 .opcode_type    (opcode_type),
  107.                 .writeback_value(writeback_value),
  108.                 .signals        (signals),
  109.                 .rr_addr        (rr_addr),
  110.                 .rd_addr        (rd_addr),
  111.                 .rr_data        (rr_data),
  112.                 .rd_data        (rd_data),
  113.                 .rr_cs          (rr_cs),
  114.                 .rd_cs          (rd_cs),
  115.                 .rr_we          (rr_we),
  116.                 .rd_we          (rd_we),
  117.                 .rr_oe          (rr_oe),
  118.                 .rd_oe          (rd_oe),
  119.                 .opcode_rd              (opcode_rd),
  120.                 .opcode_rr              (opcode_rr)
  121.         );
  122.  
  123.         bus_interface_unit #(
  124.                 .MEM_START_ADDR(8'h40),
  125.                 .MEM_STOP_ADDR (8'hBF),
  126.                 .DATA_WIDTH    (DATA_WIDTH),
  127.                 .ADDR_WIDTH    (ADDR_WIDTH)
  128.         ) bus_int (
  129.                 .opcode_group (opcode_group),
  130.                 .opcode_imd   (opcode_imd),
  131.                 .signals      (signals),
  132.                 .bus_addr     (bus_addr),
  133.                 .bus_data     (bus_data),
  134.                 .mem_cs       (mem_cs),
  135.                 .mem_we       (mem_we),
  136.                 .mem_oe       (mem_oe),
  137.                 .indirect_addr(indirect_addr),
  138.                 .data_to_store(data_to_store)
  139.         );
  140.  
  141.          assign indirect_addr =
  142.                 (opcode_group[`GROUP_LOAD_INDIRECT] ||
  143.                 opcode_group[`GROUP_STORE_INDIRECT]) ?
  144.                 // else, indirect to memory => X or Y or Z
  145.                                 {alu_rr, alu_rd} :
  146.                 // else, not indirect
  147.                         {ADDR_WIDTH{1'bx}};
  148.  
  149.         assign data_to_store =
  150.                         signals[`CONTROL_MEM_WRITE] ?
  151.                         /* TODO 4: STS */
  152.                                 alu_rr  :
  153.                         {DATA_WIDTH{1'bx}};
  154.  
  155.         /* Bloc de atribuire al program counter-ului */
  156.         always @(posedge clk, posedge reset) begin
  157.                 if (reset) begin
  158.                         program_counter <= 0;
  159.                 end else if (pipeline_stage == `STAGE_WB) begin
  160.                         program_counter <= program_counter + 1;
  161.                 end
  162.         end
  163.  
  164.         assign alu_flags_in = sreg;
  165.         /* Bloc de atribuire al sreg-ului */
  166.         always @(posedge clk, posedge reset)
  167.                 if (reset)
  168.                         sreg <= 0;
  169.                 else sreg <= alu_flags_out;
  170.  
  171.         always @(posedge clk, posedge reset) begin
  172.          /* TODO : Faceti legatura intre registre si RAM prin unitatea de control. */
  173.          /* TODO 3: LDI */
  174.          /* TODO 5,6,7: register writes */
  175.                 if (reset)
  176.                         writeback_value <= {DATA_WIDTH{1'b0}};
  177.                 else if (opcode_group[`GROUP_ALU])
  178.                                 writeback_value <= alu_out_buffer;
  179.                 else if (opcode_type == `TYPE_LDI)
  180.                                 writeback_value <= opcode_imd[DATA_WIDTH-1:0];
  181.                 else if (signals[`CONTROL_MEM_READ])
  182.                                 writeback_value <= bus_data;
  183.                 else if (opcode_type == `TYPE_MOV)
  184.                                 writeback_value <= alu_rr;
  185.         end
  186.  
  187.         /* Buffer pentru instructiunea citita */
  188.         always @(posedge clk, posedge reset)
  189.                 if (reset)
  190.                         instr_buffer <= 0;
  191.                 else if (pipeline_stage == `STAGE_IF)
  192.                          instr_buffer <= instruction;
  193.  
  194.          /* Buffer pentru output-ul UAL-ului */
  195.         always @(posedge clk, posedge reset)
  196.                 if (reset)
  197.                         alu_out_buffer <= 0;
  198.                 else if (pipeline_stage == `STAGE_EX)
  199.                          alu_out_buffer <= alu_out;
  200.  
  201.         /* Buffer pentru rd_data si rr_data */
  202.         always @(posedge clk, posedge reset)
  203.                 if (reset) begin
  204.                         alu_rd <= 0;
  205.                         alu_rr <= 0;
  206.                 end else if (pipeline_stage == `STAGE_ID) begin
  207.                         alu_rd <= rd_data;
  208.                         alu_rr <= rr_data;
  209.                 end
  210.  
  211.         assign alu_enable = (pipeline_stage == `STAGE_EX);
  212.  
  213.         /* Set alu_opsel to appropriate operation,
  214.          * according to opcode_type and alu_enable */
  215.         always @* begin
  216.                 if (alu_enable == 0)
  217.                         alu_opsel = `OPSEL_COUNT'bx;
  218.                 else begin
  219.                         case (opcode_type)
  220.                         `TYPE_ADD:
  221.                                 alu_opsel = `OPSEL_ADD;
  222.                         `TYPE_ADC:
  223.                                 alu_opsel = `OPSEL_ADC;
  224.                         `TYPE_SUB:
  225.                                 alu_opsel = `OPSEL_SUB;
  226.                         `TYPE_AND:
  227.                                 alu_opsel = `OPSEL_AND;
  228.                         `TYPE_EOR:
  229.                                 alu_opsel = `OPSEL_EOR;
  230.                         `TYPE_OR:
  231.                                 alu_opsel = `OPSEL_OR;
  232.                         `TYPE_NEG:
  233.                                 alu_opsel = `OPSEL_NEG;
  234.                         default:
  235.                                 alu_opsel = `OPSEL_NONE;
  236.                         endcase
  237.                 end
  238.         end
  239.  
  240. endmodule
  241.