일단
wishbone.v에서 보이는 data는 다음과 같다.
i_portx_wdata
이고 이것은
mem.v에서 o_wb_write_data로 연결된다.
이것은 알다시피 32bit로 filtering된 i_write_data를 4번 연속해서 쓴 것일 뿐이다.
그럼 이 i_write_data는 어디서 왔냐 보면
execute.v에서 o_write_data와 연결되어 있다.
o_write_data <= write_data_update ? write_data_nxt : o_write_data;
이므로, 봐야 할 것은 write_data_nxt이다.(32bits)
assign write_data_nxt = i_byte_enable_sel == 2'd0 ? rd : {4{rd[ 7:0]}} ;
이렇게 되어있는데, i_byte_enable_sel == 0이면 rd를 그대로 내고 아니면 rd의 8bit를 4번 반복해서 낸다는 것이다.
여기서 rd를 살펴보면(32bits)
assign rd = i_rd_use_read && i_rs_sel == load_rd_c[3:0] && status_bits_mode == load_rd_c[5:4] ? read_data_filtered_c : reg_bank_rd; 이렇게 나온다.
앞에 것들은 모두 조건들이고 뒤에는 결국
read_data_filtered_c 혹은 reg_bank_rd가 write 할 32bits짜리 data가 된다.
1. 그렇다면 일단 read_data_filtered_c부터 살펴보면
assign read_data_filtered_c = i_wb_read_data_valid ? read_data_filtered : read_data_filtered_r;
이렇게 된다. 이것은 read_data가 valid하다면 read_data_filtered가 들어오고 아니면 r이 들어간다.
1-1. read_data_filtered는 다음과 같다.
assign read_data_filtered = i_wb_load_rd[4] ? {24'd0, read_data_filtered1[7:0]} : read_data_filtered1 ;
여기서 filter read data는 다음과 같은 condition에 따른다.
// mem_load_rd[10:9]-> shift ROR bytes
// mem_load_rd[8] -> load flags with PC
// mem_load_rd[7] -> load status bits with PC
// mem_load_rd[6:5] -> Write into this Mode registers
// mem_load_rd[4] -> zero_extend byte
// mem_load_rd[3:0] -> Destination Register
그러므로, 위의 것에서 read_data_filtered는 i_wb_load_rd[4]가 1이면 zero_extend byte가 1이기에 앞에 24bits에 0을 넣어주는 것이다.
그리고 read_data_filtered1은 다음과 같다.
assign read_data_filtered1 =
i_wb_load_rd[10:9] == 2'd0 ? i_wb_read_data :
i_wb_load_rd[10:9] == 2'd1 ? {i_wb_read_data[7:0], i_wb_read_data[31:8]} :
i_wb_load_rd[10:9] == 2'd2 ? {i_wb_read_data[15:0], i_wb_read_data[31:16]} :
{i_wb_read_data[23:0], i_wb_read_data[31:24]} ;
위에서 말했듯이 저 [10:9]는 shift ROR bytes이다.
그럼 여기서 결국 들어가는 data는 rotate 되었거나 혹은 zero extend가 된 i_wb_read_data이다.
(32bits 짜리 데이터가 rotate된 것이기에 다른 96 bits는 아무런 상관이 없다.)
이것은 write_back.v의 o_wb_read_data와 연결되어 있는데, 이것은
내부에서 mem_read_data_r 에 assign 되어 있다. 이것은 i_mem_read_data와 연결되어 있는데, 이것은 또 mem.v의 o_mem_read_data와 연결되어 있다. 그 내부에서는
assign o_mem_read_data = use_mem_reg ? mem_read_data_r : mem_read_data_c;
이렇게 연결이 되어 있는데, mem_read_data_r은 결국 mem_read_data_c와 연결이 되어 있고,
mem_read_data_c는 다음과 같다.
assign mem_read_data_c = sel_cache ? cache_read_data :
uncached_data_access ? wb_rdata32 :
32'h76543210 ;
cache와 연괸이 있다면 cache_read_data이고 uncached data access라면 wb_rdata32이다.
1-1-1. cache_read_data는 dcache.v에 o_read_data와 연결되어 있다.
그 내부에서 o_read_data는 다음과 같이 연결되어 있다.
assign o_read_data =
i_address[WORD_SEL_MSB:WORD_SEL_LSB] == 2'd0 ? read_data128 [31:0] :
i_address[WORD_SEL_MSB:WORD_SEL_LSB] == 2'd1 ? read_data128 [63:32] :
i_address[WORD_SEL_MSB:WORD_SEL_LSB] == 2'd2 ? read_data128 [95:64] :
read_data128 [127:96] ;
read_data128은 wb_hit ? i_wb_cached_rdata : hit_rdata; 로 되어있고
i_wb_cached_rdata는 core쪽에서는 dcache_wb_cached_rdata로 들어온다.
hit_rdata는 data_rdata_way[i]로 data_rdata_way[i]가 cache와 연결이 되어 있는 것 같다.
1-1-2. wb_rdata32는 바로 mem.v의 내부에서 보인다.
assign wb_rdata32 = i_daddress[3:2] == 2'd0 ? i_wb_uncached_rdata[ 31: 0] :
i_daddress[3:2] == 2'd1 ? i_wb_uncached_rdata[ 63:32] :
i_daddress[3:2] == 2'd2 ? i_wb_uncached_rdata[ 95:64] :
i_wb_uncached_rdata[127:96] ;
1-2-1. execute.v에서 read_data_filtered_r에 대해서 알아보면 다음과 같다.
always@( posedge i_clk )
if ( i_wb_read_data_valid )
begin
read_data_filtered_r <= read_data_filtered;
load_rd_r <= {i_wb_load_rd[6:5], i_wb_load_rd[3:0]};
end
그러므로, read_data_filtered와 같다고 보면 된다.
2. execute.v에서 reg_bank_rd가 뭔지 살펴보면 register_bank.v에 o_rd와 연결되어 있다.
내부에서 보면
always @*
case ( i_rs_sel )
4'd0 : o_rd = r0_out ;
4'd1 : o_rd = r1_out ;
4'd2 : o_rd = r2_out ;
4'd3 : o_rd = r3_out ;
4'd4 : o_rd = r4_out ;
4'd5 : o_rd = r5_out ;
4'd6 : o_rd = r6_out ;
4'd7 : o_rd = r7_out ;
4'd8 : o_rd = r8_rds ;
4'd9 : o_rd = r9_rds ;
4'd10 : o_rd = r10_rds ;
4'd11 : o_rd = r11_rds ;
4'd12 : o_rd = r12_rds ;
4'd13 : o_rd = r13_rds ;
4'd14 : o_rd = r14_rds ;
default: o_rd = r15_out_rm_nxt ;
endcase
이런 것을 볼 수 있는데, 이것들은 다음과 같이 assign 되어있다.
assign r0_out = r0;
assign r1_out = r1;
assign r2_out = r2;
assign r3_out = r3;
assign r4_out = r4;
assign r5_out = r5;
assign r6_out = r6;
assign r7_out = r7;
assign r8_out = firq_exec ? r8_firq : r8;
assign r9_out = firq_exec ? r9_firq : r9;
assign r10_out = firq_exec ? r10_firq : r10;
assign r11_out = firq_exec ? r11_firq : r11;
assign r12_out = firq_exec ? r12_firq : r12;
assign r13_out = usr_exec ? r13 :
svc_exec ? r13_svc :
irq_exec ? r13_irq :
r13_firq ;
assign r14_out = usr_exec ? r14 :
svc_exec ? r14_svc :
irq_exec ? r14_irq :
r14_firq ;
그러면 r0, r1, r2, r3 등등은 모두 32bits reg인데,
어떻게 해서 결정되는지를 보려면 다음과 같다.
always @ ( posedge i_clk )
begin
// these registers are used in all modes
r0 <= reg_bank_wen_c[0 ] ? i_reg : read_data_wen[0 ] ? i_wb_read_data : r0;
r1 <= reg_bank_wen_c[1 ] ? i_reg : read_data_wen[1 ] ? i_wb_read_data : r1;
r2 <= reg_bank_wen_c[2 ] ? i_reg : read_data_wen[2 ] ? i_wb_read_data : r2;
r3 <= reg_bank_wen_c[3 ] ? i_reg : read_data_wen[3 ] ? i_wb_read_data : r3;
r4 <= reg_bank_wen_c[4 ] ? i_reg : read_data_wen[4 ] ? i_wb_read_data : r4;
r5 <= reg_bank_wen_c[5 ] ? i_reg : read_data_wen[5 ] ? i_wb_read_data : r5;
r6 <= reg_bank_wen_c[6 ] ? i_reg : read_data_wen[6 ] ? i_wb_read_data : r6;
r7 <= reg_bank_wen_c[7 ] ? i_reg : read_data_wen[7 ] ? i_wb_read_data : r7;
// these registers are used in all modes, except fast irq
r8 <= reg_bank_wen_c[8 ] && !firq_idec ? i_reg : read_data_wen[8 ] && i_wb_mode != FIRQ ? i_wb_read_data : r8;
r9 <= reg_bank_wen_c[9 ] && !firq_idec ? i_reg : read_data_wen[9 ] && i_wb_mode != FIRQ ? i_wb_read_data : r9;
r10 <= reg_bank_wen_c[10] && !firq_idec ? i_reg : read_data_wen[10] && i_wb_mode != FIRQ ? i_wb_read_data : r10;
r11 <= reg_bank_wen_c[11] && !firq_idec ? i_reg : read_data_wen[11] && i_wb_mode != FIRQ ? i_wb_read_data : r11;
r12 <= reg_bank_wen_c[12] && !firq_idec ? i_reg : read_data_wen[12] && i_wb_mode != FIRQ ? i_wb_read_data : r12;
// these registers are used in fast irq mode
r8_firq <= reg_bank_wen_c[8 ] && firq_idec ? i_reg : read_data_wen[8 ] && i_wb_mode == FIRQ ? i_wb_read_data : r8_firq;
r9_firq <= reg_bank_wen_c[9 ] && firq_idec ? i_reg : read_data_wen[9 ] && i_wb_mode == FIRQ ? i_wb_read_data : r9_firq;
r10_firq <= reg_bank_wen_c[10] && firq_idec ? i_reg : read_data_wen[10] && i_wb_mode == FIRQ ? i_wb_read_data : r10_firq;
r11_firq <= reg_bank_wen_c[11] && firq_idec ? i_reg : read_data_wen[11] && i_wb_mode == FIRQ ? i_wb_read_data : r11_firq;
r12_firq <= reg_bank_wen_c[12] && firq_idec ? i_reg : read_data_wen[12] && i_wb_mode == FIRQ ? i_wb_read_data : r12_firq;
// these registers are used in user mode
r13 <= reg_bank_wen_c[13] && usr_idec ? i_reg : read_data_wen[13] && i_wb_mode == USR ? i_wb_read_data : r13;
r14 <= reg_bank_wen_c[14] && usr_idec ? i_reg : read_data_wen[14] && i_wb_mode == USR ? i_wb_read_data : r14;
그러면 이것들은 condition에 따라서, i_reg가 저장이 되거나 혹은 i_wb_read_data가 저장이 되거나 혹은 변화가 없게 될 것이다.
이것들은 둘다 밖에서 온 것들이다.
2-1. i_wb_read_data는 execute.v에서, read_data_filtered와 동일하다.
2-2. i_reg는 execute.v에서 reg_write_nxt라는 wire로 있는데 그것은 다음과 같다.
assign reg_write_nxt = i_reg_write_sel == 3'd0 ? alu_out :
// save pc to lr on an interrupt
i_reg_write_sel == 3'd1 ? save_int_pc_m4 :
// to update Rd at the end of Multiplication
i_reg_write_sel == 3'd2 ? multiply_out :
i_reg_write_sel == 3'd3 ? o_status_bits :
i_reg_write_sel == 3'd5 ? i_copro_read_data : // mrc
i_reg_write_sel == 3'd6 ? base_address :
save_int_pc ;
'수업 > 졸업논문-Amber' 카테고리의 다른 글
| cache에 쓰는 128bits를 그대로 encryption해서 메모리에 쓰기 (0) | 2015.09.14 |
|---|---|
| write시에 그냥 memory에서 read한 뒤 decrypt change encrypt해서 내보내도록 (0) | 2015.09.01 |
| mem file을 encrypt 했는데도 안되서 main_mem.v 확인결과 (0) | 2015.08.26 |
| 10clk delay에다가 aes를 넣을 방법 (0) | 2015.08.16 |
| read시 10clk delay 어떻게 추가했는지 (0) | 2015.08.16 |