|
|
/*********************************************************/
// 모듈:접근 기억능력이 있는 캐쉬메모리
// 파일이름:cache.v
// 버젼 : 2.0
// 날짜 : 2026.01.20
// 저자 : 탁 형옥
// 코딩 언어 : verilog
// 문제 내용 (해결해야 할 목표):
접근 빈도가 높은 메모리 주소의 접근 기억을 이용하여 이미지 데이터 혹은 시계열 데이터의 읽기 접근을
캐쉬 hit 카운터에 누적시켜서 이미지 분류[0~9의 숫자 비교 출력)에 이용한다.
// 요구되는 언어 기술 (어려운 점):
0~9의 숫자들 중에서 hit 율이 높은 숫자를 연산에 의해 비교하여 출력 결정하기가 높은 전력을 소비한다.
입력 이미지 데이터 의 종료후에 비교연산을 수행함으로써 전력 소비를 줄인다.
// 목표와 기술을 도달하기 위한 알아야 할 기술(문법), 어려운 점, 문제점 극복 과정:
시계열 이미지를 순차적으로 주고 해당 이미지의 라벨과 함께주어서 캐쉬 엔트리에 라벨 이미지의 기억시킨후에
사용자 이미지의 입력시에 여러 엔트리에 기억된 숫자 이미지와의 비교에서 누적 hit 수 즉 기억한 정도를 표현하는
통계적 일치성 숫자의 계수값이 가장 높은 숫자 (가능성이 높은 숫자)를 출력하는데 시뮬레이션으로 확인하였다.
// 결과 도출:
추론결과 50%정도의 낮은 추론 결과로 인해 부적합한 방식으로 인식됨 .
100%추론결과를 유추할 수 있는 방식을 찾거나 추론없이 사용되는 방안을 모색하게됨.
// 기본 목표 과제를 한층 더 깊이 있게 하기 위한 생각:
전력 소비를 줄이기 위한 방안과 속도를 개선시키기 위한 방안
// 이용 가능한 분야:
이는 MNIST 의 숫자 분별 및 시계열 데이터의 분류작업에 응용할 수 있을 것으로 생각된다.
// 기술과 트렌드:
// 설명 :
//
/*********************************************************/
/*
module comparaterBlock
(
input clk,
input rst_n,
input [255:0] sdsp_on,
input [255:0] start_n,
input [255:0] we,
input [12:0] addr,
output reg [7:0] out // out = argmax index (0~255)
);
wire [8:0] cnt [0:255];
integer k;
reg [8:0] max_cnt;
reg [7:0] max_idx;
always @(posedge clk) begin
if(start_n==1'b0)
begin
max_cnt = cnt[0];
max_idx = 8'd0;
end
else
begin
// 1~255
for (k = 1; k < 256; k = k + 1) begin
if (cnt[k] > max_cnt) begin
max_cnt = cnt[k];
max_idx = k[7:0];
end
end
end
end
always @(*) begin
out = max_idx;
end
endmodule
*/
module comparaterBlock
(
input clk,rst_n,
input sdsp_on,
input start_n,
input we,
input [12:0] addr,
input wire [8:0] cnt[9:0],
output wire [7:0] out
);
//wire [8:0] cnt [255:0];
/* reg [8:0] wcnt0 [0:127];
reg [7:0] widx0 [0:127];
reg [8:0] wcnt1 [0:63];
reg [7:0] widx1 [0:63];
reg [8:0] wcnt2 [0:31];
reg [7:0] widx2 [0:31];
*/
reg [8:0] wcnt3 [0:15];
reg [7:0] widx3 [0:15];
reg [8:0] wcnt4 [0:7];
reg [7:0] widx4 [0:7];
reg [8:0] wcnt5 [0:3];
reg [7:0] widx5 [0:3];
reg [8:0] wcnt6 [0:1];
reg [7:0] widx6 [0:1];
integer k;
reg [8:0] final_val;
reg [7:0] final_idx;
function automatic [17:0] pick2(
input [8:0] a_val,
input [7:0] a_idx,
input [8:0] b_val,
input [7:0] b_idx
);
reg [8:0] o_val;
reg [7:0] o_idx;
begin
if (a_val > b_val) begin
o_val = a_val; o_idx = a_idx;
end else if (b_val > a_val) begin
o_val = b_val; o_idx = b_idx;
end else begin
// equal: lower index wins
if (a_idx <= b_idx) begin
o_val = a_val; o_idx = a_idx;
end else begin
o_val = b_val; o_idx = b_idx;
end
end
pick2 ={o_val,o_idx};
end
endfunction
always @(*) begin
for (k = 0; k < 8; k = k + 1) begin
widx3[2*k]=2*k;
widx3[2*k+1]=2*k+1;
end
/* // 256 -> 128
for (k = 0; k < 128; k = k + 1) begin
pick2(cnt[2*k], (2*k)[7:0],
cnt[2*k+1], (2*k+1)[7:0],
wcnt0[k], widx0[k]);
end
// 128 -> 64
for (k = 0; k < 64; k = k + 1) begin
pick2(wcnt0[2*k], widx0[2*k],
wcnt0[2*k+1], widx0[2*k+1],
wcnt1[k], widx1[k]);
end
// 64 -> 32
for (k = 0; k < 32; k = k + 1) begin
pick2(wcnt1[2*k], widx1[2*k],
wcnt1[2*k+1], widx1[2*k+1],
wcnt2[k], widx2[k]);
end
// 32 -> 16
for (k = 0; k < 16; k = k + 1) begin
pick2(wcnt2[2*k], widx2[2*k],
wcnt2[2*k+1], widx2[2*k+1],
wcnt3[k], widx3[k]);
end
// 16 -> 8
for (k = 0; k < 8; k = k + 1) begin
pick2(wcnt3[2*k], widx3[2*k],
wcnt3[2*k+1], widx3[2*k+1],
wcnt4[k], widx4[k]);
end
*/
for (k = 0; k < 8; k = k + 1) begin
{wcnt4[k],widx4[k]}= pick2(cnt[2*k], widx3[2*k],
cnt[2*k+1], widx3[2*k+1]);
end
// 8 -> 4
for (k = 0; k < 4; k = k + 1) begin
{wcnt5[k],widx5[k]} = pick2(wcnt4[2*k], widx4[2*k],
wcnt4[2*k+1], widx4[2*k+1]);
end
// 4 -> 2
for (k = 0; k < 2; k = k + 1) begin
{wcnt6[k], widx6[k]}=pick2(wcnt5[2*k], widx5[2*k],
wcnt5[2*k+1], widx5[2*k+1]);
end
// 2 -> 1 :
/* if(wcnt6[0]<wcnt6[1])
out=widx6[1];
else
out=widx6[0];
*/
begin : FINAL
{final_val, final_idx}= pick2(wcnt6[0], widx6[0],
wcnt6[1], widx6[1]);
end
end
assign out= final_idx;
endmodule
module TEST(
input clk,rst_n,
input sdsp_on,
input start_n,
input we,cs,
input [3:0] cid,
input [16:0] addr,
output [7:0] out
);
wire [8:0] cnt_out [9:0];
wire we_w[9:0];
generate
genvar i;
for(i=0;i<10;i=i+1)
begin:genI
assign we_w[i]=(we==1'b1)&&(cid==i);
end
endgenerate
cache U0
(
.clk(clk),
.rst_n(rst_n),
/* .sdsp_on(sdsp_on[i]),
.start_n(start_n[i]),
.we(we[i]),
*/
.sdsp_on(sdsp_on),
.start_n(start_n),
.we(we_w[0]),
.cs(cs),
// .cid(4'd0),
.addr(addr[12:0]),
.up(),
.cnt_out(cnt_out[0])
);
cache U1
(
.clk(clk),
.rst_n(rst_n),
.sdsp_on(sdsp_on),
.start_n(start_n),
.we(we_w[1]),
.cs(cs),
// .cid(4'd1),
.addr(addr[12:0]),
.up(),
.cnt_out(cnt_out[1])
);
cache U2
(
.clk(clk),
.rst_n(rst_n),
.sdsp_on(sdsp_on),
.start_n(start_n),
.we(we_w[2]),
.cs(cs),
// .cid(4'd2),
.addr(addr[12:0]),
.up(),
.cnt_out(cnt_out[2])
);
cache U3
(
.clk(clk),
.rst_n(rst_n),
.sdsp_on(sdsp_on),
.start_n(start_n),
.we(we_w[3]),
.cs(cs),
// .cid(4'd3),
.addr(addr[12:0]),
.up(),
.cnt_out(cnt_out[3])
);
cache U4
(
.clk(clk),
.rst_n(rst_n),
.sdsp_on(sdsp_on),
.start_n(start_n),
.we(we_w[4]),
.cs(cs),
// .cid(4'd4),
.addr(addr[12:0]),
.up(),
.cnt_out(cnt_out[4])
);
cache U5
(
.clk(clk),
.rst_n(rst_n),
.sdsp_on(sdsp_on),
.start_n(start_n),
.we(we_w[5]),
.cs(cs),
// .cid(4'd5),
.addr(addr[12:0]),
.up(),
.cnt_out(cnt_out[5])
);
cache U6
(
.clk(clk),
.rst_n(rst_n),
.sdsp_on(sdsp_on),
.start_n(start_n),
.we(we_w[6]),
.cs(cs),
// .cid(4'd6),
.addr(addr[12:0]),
.up(),
.cnt_out(cnt_out[6])
);
cache U7
(
.clk(clk),
.rst_n(rst_n),
.sdsp_on(sdsp_on),
.start_n(start_n),
.we(we_w[7]),
.cs(cs),
// .cid(4'd7),
.addr(addr[12:0]),
.up(),
.cnt_out(cnt_out[7])
);
cache U8
(
.clk(clk),
.rst_n(rst_n),
.sdsp_on(sdsp_on),
.start_n(start_n),
.we(we_w[8]),
.cs(cs),
// .cid(4'd8),
.addr(addr[12:0]),
.up(),
.cnt_out(cnt_out[8])
);
cache U9
(
.clk(clk),
.rst_n(rst_n),
.sdsp_on(sdsp_on),
.start_n(start_n),
.we(we_w[9]),
.cs(cs),
// .cid(4'd9),
.addr(addr[12:0]),
.up(),
.cnt_out(cnt_out[9])
);
comparaterBlock U10
(
.clk(clk),
.rst_n(rst_n),
.sdsp_on(sdsp_on),
.start_n(start_n),
.we(we),
.addr(addr[12:0]),
.cnt(cnt_out),
.out(out)
);
endmodule
module cache
(
input clk,rst_n,
input sdsp_on,
input start_n,
input we,cs,
input [12:0] addr,
output reg up,
output reg [8:0] cnt_out
);
// reg cache [2**13-1:0]; //for 1 weight
reg [1:0] cache [2**13-1:0]; // for 0,1,2,3 weights
reg [12:0] cnt;
integer l;
initial
begin
for(l=0;l<1024;l=l+1)
cache[l]=0;
end
always @(posedge clk)
begin
if(rst_n==1'b0)
begin
cnt_out<=0;
end
if(start_n==1'b0)
begin
// cnt_out<=0;
end
else if(sdsp_on==1'b1)
begin
if((we==1'b1)&& (cs==1'b1))
begin
if(cache[addr]<3)
cache[addr]<=cache[addr]+1'b1;
cnt_out<=0;
end
end
// else if((we==1'b0) && (cs==1'b1) && cache[addr]==1'b1)
// cnt_out<=cnt_out+1'b1;
else if((we==1'b0) && (cs==1'b1))
cnt_out<=cnt_out+cache[addr];
end
endmodule
`timescale 1ns/1ns
module tb_TEST;
reg clk,rst_n;
reg sdsp_on;
reg start_n;
reg we;
reg cs;
reg [3:0] cid;
reg [12:0] addr;
wire [7:0] out;
integer i;
TEST DUT(
.clk(clk),
.rst_n(rst_n),
.sdsp_on(sdsp_on),
.start_n(start_n),
.we(we),
.cs(cs),
.cid(cid),
.addr(addr),
.out(out)
);
always #5 clk=!clk;
initial
begin
clk=1'b0; rst_n=1'b0; sdsp_on=1'b1; start_n=1'b0; we=1'b0; addr=13'b0;
repeat(16*2) @(posedge clk); rst_n=1'b1;
for(i=1;i<8;i=i+1)
WRITE(8,i);
for(i=5;i<10;i=i+1)
WRITE(7,i);
for(i=5;i<10;i=i+1)
READ(i);
for(i=1;i<7;i=i+1)
READ(i);
end
task WRITE (input [3:0] c,input [12:0] a);
begin
sdsp_on=1'b1;
addr=a;
we=1'b1;
start_n=1'b1;
cid=c;
cs=1'b1;
repeat(2) @(posedge clk);
we=1'b0;
cs=1'b0;
start_n=1'b0;
end
endtask
task READ (input [12:0] a);
begin
sdsp_on=1'b0;
addr=a;
we=1'b0;
cs=1'b1;
start_n=1'b1;
@(posedge clk);
we=1'b0;
cs=1'b0;
start_n=1'b0;
end
endtask
endmodule
|
|
