Skip to main content

cr_mem

CR_MEM

  • CR_MEM is the control registers memory region. It is a flip-flop based memory (not sram like others) that contains essential registers for the communication with the FGPA peripherals. CR data can be accessed through the software by requesting the specific offset of the specific CR in the CR table. Some CRs are read only that sample data from the hardware. Others are read and write CRs. The memory size is control by the parameter CR_MEM_MSB and its basic size is 4kb. The access to CR_MEM is a single-port access. The processor accesses CR_MEM in the Memory stage. The table below shows the control registers present in the design.
    Please note the CRs list may be changed depending on the design and future updates.
CR NameAddressDescription
CR_SEG7_00x00007000RW 7 bit
CR_SEG7_10x00007004RW 7 bit
CR_SEG7_20x00007008RW 7 bit
CR_SEG7_30x0000700CRW 7 bit
CR_SEG7_40x00007010RW 7 bit
CR_SEG7_50x00007014RW 7 bit
CR_LED0x00007018RW 10 bit
CR_Button_00x0000701CRO 1 bit
CR_Button_10x00007020RO 1 bit
CR_SWITCH0x00007024RO 10 bit
CR_JOYSTICK_X0x00007028RW 10 bit
CR_JOYSTICK_Y0x0000702CRW 10 bit
CR_KBD_DATA0x00007100RO 8 bit
CR_KBD_READY0x00007104RO 1 bit
CR_KBD_SCANF_EN0x00007108RW 1 bit
  • RW - read write CR. We can send data to the fpga and sample data from the fpga.
  • RO - read only CR. We can only sample data from the fpga.
  • The two last one are related to the keyboard.
  • We define two structs to communicate with the fpga The first one is for signals coming from the fpga into the core (t_fpga_in) and the second is for signals coming from the core to fpga (``)
typedef struct packed {
logic Button_0;
logic Button_1;
logic [9:0] Switch;
logic [11:0] Joystick_x;
logic [11:0] Joystick_y;
} t_fpga_in;
typedef struct packed {
logic [7:0] SEG7_0;
logic [7:0] SEG7_1;
logic [7:0] SEG7_2;
logic [7:0] SEG7_3;
logic [7:0] SEG7_4;
logic [7:0] SEG7_5;
logic [9:0] LED;
} t_fpga_out;

Writing to CR_MEM

In the following always block we update the CR's. For example lets say we want to turn on SEG7_0 in the fpga, we will write to CR_SEG7_0 with some value. The always block will sample the data and turn on the SEG7_0 in the fpga.

always_comb begin
fpga_out_2 = fpga_out_1;
kbd_cr_next.kbd_scanf_en = kbd_cr.kbd_scanf_en;
if(wren) begin
unique casez (address) // address holds the offset
// ---- RW memory ----
CR_SEG7_0 : fpga_out_2.SEG7_0 = data[7:0];
CR_SEG7_1 : fpga_out_2.SEG7_1 = data[7:0];
CR_SEG7_2 : fpga_out_2.SEG7_2 = data[7:0];
CR_SEG7_3 : fpga_out_2.SEG7_3 = data[7:0];
CR_SEG7_4 : fpga_out_2.SEG7_4 = data[7:0];
CR_SEG7_5 : fpga_out_2.SEG7_5 = data[7:0];
CR_LED : fpga_out_2.LED = data[9:0];
CR_KBD_SCANF_EN : kbd_cr_next.kbd_scanf_en = data[0];
// ---- Other ----
default : /* Do nothing */;
endcase
end
end

Reading from CR_MEM

In the following always block we sample the data from the CR's that going to fpga. For example lets say we want to read the value on SEG7_0 in the fpga, we will read from CR_SEG7_0.

  • Note that in our design the q_b output always reads the data from the CR's going to fpga.
always_comb begin
pre_q = 32'b0;
pre_q_b = 32'b0;
if(rden) begin
unique casez (address) // address holds the offset
// ---- RW memory ----
CR_SEG7_0 : pre_q = {24'b0 , fpga_out.SEG7_0} ;
CR_SEG7_1 : pre_q = {24'b0 , fpga_out.SEG7_1} ;
CR_SEG7_2 : pre_q = {24'b0 , fpga_out.SEG7_2} ;
CR_SEG7_3 : pre_q = {24'b0 , fpga_out.SEG7_3} ;
CR_SEG7_4 : pre_q = {24'b0 , fpga_out.SEG7_4} ;
CR_SEG7_5 : pre_q = {24'b0 , fpga_out.SEG7_5} ;
CR_LED : pre_q = {22'b0 , fpga_out.LED} ;
CR_KBD_SCANF_EN : pre_q = {31'b0 , kbd_cr.kbd_scanf_en} ;
// ---- RO memory ----
CR_Button_0 : pre_q = {31'b0 , fpga_in_2.Button_0} ;
CR_Button_1 : pre_q = {31'b0 , fpga_in_2.Button_1} ;
CR_SWITCH : pre_q = {22'b0 , fpga_in_2.Switch} ;
CR_JOYSTICK_X : pre_q = {20'b0 , fpga_in_2.Joystick_x};
CR_JOYSTICK_Y : pre_q = {20'b0 , fpga_in_2.Joystick_y};
CR_KBD_READY : pre_q = {31'b0 , kbd_cr.kbd_ready} ;
CR_KBD_DATA : pre_q = {24'b0 , kbd_cr.kbd_data} ;
default : pre_q = 32'b0 ;
endcase
end

//Fabric Read
unique casez (address_b) // address holds the offset
// ---- RW memory ----
CR_SEG7_0 : pre_q_b = {24'b0 , fpga_out.SEG7_0} ;
CR_SEG7_1 : pre_q_b = {24'b0 , fpga_out.SEG7_1} ;
CR_SEG7_2 : pre_q_b = {24'b0 , fpga_out.SEG7_2} ;
CR_SEG7_3 : pre_q_b = {24'b0 , fpga_out.SEG7_3} ;
CR_SEG7_4 : pre_q_b = {24'b0 , fpga_out.SEG7_4} ;
CR_SEG7_5 : pre_q_b = {24'b0 , fpga_out.SEG7_5} ;
CR_LED : pre_q_b = {22'b0 , fpga_out.LED} ;
CR_KBD_SCANF_EN: pre_q_b = {31'b0 , kbd_cr.kbd_scanf_en} ;
// ---- RO memory ----
CR_Button_0 : pre_q_b = {31'b0 , fpga_in_2.Button_0} ;
CR_Button_1 : pre_q_b = {31'b0 , fpga_in_2.Button_1} ;
CR_SWITCH : pre_q_b = {22'b0 , fpga_in_2.Switch} ;
CR_JOYSTICK_X : pre_q_b = {20'b0 , fpga_in_2.Joystick_x};
CR_JOYSTICK_Y : pre_q_b = {20'b0 , fpga_in_2.Joystick_y};
CR_KBD_READY : pre_q_b = {31'b0 , kbd_cr.kbd_ready} ;
CR_KBD_DATA : pre_q_b = {24'b0 , kbd_cr.kbd_data} ;
default : pre_q_b = 32'b0 ;
endcase

end