|
/*********************************************************/
// 모듈: n+k redundancy 단방향 버스 드라이버
// 파일이름:uniDriver.v
// 버젼 : 1.0
// 날짜 : 2024.11.07
// 저자 : 탁 형옥
// 코딩 언어 : verilog
// 문제 내용 (해결해야 할 목표):
버스 신호의 장애 faults(1 at stuck or 0 at stuck)에서 redundancy 포트 신호로의 마이크로프로그래밍 제어를
받아 포트 스위칭하여 송수신의 내부 로직 블럭에 정상적인 데이터 통신이 가능하게 한다.
// 요구되는 언어 기술 (어려운 점):
로직의 복잡도에 따라 데이타 통신 속도를 매우 빠르게 하기 어렵다.
// 목표와 기술을 도달하기 위한 알아야 할 기술(문법), 어려운 점, 문제점 극복 과정:
수신단의 제어 레지스터를 일관성을 가지고 송신단과 동일한 값으로 유지 하기 위한 과정은 구현 방식에 의한다.
// 결과 도출:
// 기본 목표 과제를 한층 더 깊이 있게 하기 위한 생각:
// 이용 가능한 분야: 불가피한 버스 장애가 있는 시스템 버스의 내부
// 기술과 트렌드:
// 설명 :
//
/*********************************************************/
module uniDriver
#(parameter N=4)
(
input [N-1:0] dtx_in, // input ports
output [N-1:0] dtx_out, // output ports
output reg [N-1:0] stx_out, // redundant ports
output parity,
input [N-1:0] iReg, // select input data
input [N-1:0] oReg, // select output data
output reg errorN
);
reg errorN;
//reg [N-1:0] iReg; // select input data
//reg [N-1:0] oReg; // select output data
/*
generate
genvar i,j;
for(i=0;i<N;i=i+1)
begin:genI
assign dtx_out[i] = (iReg[i]==1'b1) ? dtx_in[i] : 1'bz;
end
endgenerate
*/
assign dtx_out[0] = (iReg[0]==1'b1) ? dtx_in[0] : 1'bz;
assign dtx_out[1] = (iReg[1]==1'b1) ? dtx_in[1] : 1'bz;
assign dtx_out[2] = (iReg[2]==1'b1) ? dtx_in[2] : 1'bz;
assign dtx_out[3] = (iReg[3]==1'b1) ? dtx_in[3] : 1'bz;
assign parity = ^dtx_in;
always @(*)
begin
case(oReg)
/*
4'b1110: stx_out[0]<= (iReg==4'b1110) ? dtx_in[0]:
(iReg==4'b1101) ? dtx_in[1]:
(iReg==4'b1011) ? dtx_in[2]:
(iReg==4'b0111) ? dtx_in[3]:1'b0;
4'b1101: stx_out[1]<= (iReg==4'b1110) ? dtx_in[0]:
(iReg==4'b1101) ? dtx_in[1]:
(iReg==4'b1011) ? dtx_in[2]:
(iReg==4'b0111) ? dtx_in[3]:1'b0;
4'b1011: stx_out[2]<= (iReg==4'b1110) ? dtx_in[0]:
(iReg==4'b1101) ? dtx_in[1]:
(iReg==4'b1011) ? dtx_in[2]:
(iReg==4'b0111) ? dtx_in[3]:1'b0;
4'b0111: stx_out[3]<= (iReg==4'b1110) ? dtx_in[0]:
(iReg==4'b1101) ? dtx_in[1]:
(iReg==4'b1011) ? dtx_in[2]:
(iReg==4'b0111) ? dtx_in[3]:1'b0;
*/
4'b1110: begin
stx_out[0]<= (iReg[0]==1'b0) ? dtx_in[0]:
(iReg[1]==1'b0) ? dtx_in[1]:
(iReg[2]==1'b0) ? dtx_in[2]:
(iReg[3]==1'b0) ? dtx_in[3]:1'b0;
stx_out[1]<=1'b0;
stx_out[2]<=1'b0;
stx_out[3]<=1'b0;
end
4'b1101: begin
stx_out[1]<= (iReg[0]==1'b0) ? dtx_in[0]:
(iReg[1]==1'b0) ? dtx_in[1]:
(iReg[2]==1'b0) ? dtx_in[2]:
(iReg[3]==1'b0) ? dtx_in[3]:1'b0;
stx_out[0]<=1'b0;
stx_out[2]<=1'b0;
stx_out[3]<=1'b0;
end
4'b1011: begin
stx_out[2]<= (iReg[0]==1'b0)? dtx_in[0]:
(iReg[1]==1'b0) ? dtx_in[1]:
(iReg[2]==1'b0) ? dtx_in[2]:
(iReg[3]==1'b0) ? dtx_in[3]:1'b0;
stx_out[0]<=1'b0;
stx_out[1]<=1'b0;
stx_out[3]<=1'b0;
end
4'b0111: begin
stx_out[3]<= (iReg[0]==1'b0) ? dtx_in[0]:
(iReg[1]==1'b0) ? dtx_in[1]:
(iReg[2]==1'b0) ? dtx_in[2]:
(iReg[3]==1'b0) ? dtx_in[3]:1'b0;
stx_out[0]<=1'b0;
stx_out[1]<=1'b0;
stx_out[2]<=1'b0;
end
default:begin
stx_out[0]<=1'b0;
stx_out[1]<=1'b0;
stx_out[2]<=1'b0;
stx_out[3]<=1'b0;
end
endcase
end
always @* errorN <= (oReg!=4'b1111) ? 1'b0 : 1'b1;
endmodule
module uniReciver
#(parameter N=4)
(
output [N-1:0] drx_out, // fail-safe output signals
input [N-1:0] drx_in,
input [N-1:0] srx_in,
input parity,
output trx_Error,
input [N-1:0] iReg, // select input data
input [N-1:0] oReg // select output data
);
//reg [N-1:0] iReg; // select input data
//reg [N-1:0] oReg; // select output data
/*
generate
genvar i;
for(i=0;i<N;i=i+1)
begin:genI
assign drx_out[i] = (cReg[i]==1'b1) ? drx_in[i] : srx_in[oReg[0]];
end
endgenerate
*/
assign drx_out[0] = (iReg[0]==1'b1) ? drx_in[0] :
(oReg==4'b1110) ? srx_in[0] :
(oReg==4'b1101) ? srx_in[1] :
(oReg==4'b1011) ? srx_in[2] :
(oReg==4'b0111) ? srx_in[3] : 1'b0;
assign drx_out[1] = (iReg[1]==1'b1) ? drx_in[1] :
(oReg==4'b1110) ? srx_in[0] :
(oReg==4'b1101) ? srx_in[1] :
(oReg==4'b1011) ? srx_in[2] :
(oReg==4'b0111) ? srx_in[3] : 1'b0;
assign drx_out[2] = (iReg[2]==1'b1) ? drx_in[2] :
(oReg==4'b1110) ? srx_in[0] :
(oReg==4'b1101) ? srx_in[1] :
(oReg==4'b1011) ? srx_in[2] :
(oReg==4'b0111) ? srx_in[3] : 1'b0;
assign drx_out[3] = (iReg[3]==1'b1) ? drx_in[3] :
(oReg==4'b1110) ? srx_in[0] :
(oReg==4'b1101) ? srx_in[1] :
(oReg==4'b1011) ? srx_in[2] :
(oReg==4'b0111) ? srx_in[3] : 1'b0;
wire parity0,parity1,parity2,parity3,parity4;
assign parity0 = (oReg==4'b1111) ? parity ^ drx_in[0] ^ drx_in[1] ^ drx_in[2] ^ drx_in[3] : 1'b0;
assign parity1 = (oReg==4'b1110) ? parity ^ srx_in[0] ^ drx_in[1] ^ drx_in[2] ^ drx_in[3] : 1'b0;
assign parity2 = (oReg==4'b1101) ? parity ^ drx_in[0] ^ srx_in[1] ^ drx_in[2] ^ drx_in[3] : 1'b0;
assign parity3 = (oReg==4'b1011) ? parity ^ drx_in[0] ^ drx_in[1] ^ srx_in[2] ^ drx_in[3] : 1'b0;
assign parity4 = (oReg==4'b0111) ? parity ^ drx_in[0] ^ drx_in[1] ^ drx_in[2] ^ srx_in[3] : 1'b0;
assign trx_Error = parity0 | parity1 | parity2 | parity3 | parity4;
endmodule
`timescale 1ns/100ps
module tb_uniBUS;
localparam N=4;
reg [N-1:0] dtx_in;
wire [N-1:0] dtx_out;
wire [N-1:0] stx_out;
wire [N-1:0] drx_out;
wire [N-1:0] drx_in;
wire [N-1:0] srx_in;
wire parity;
wire errorN;
reg [N-1:0] iReg;
reg [N-1:0] oReg;
uniDriver #(.N(4)) U0 (
.dtx_in(dtx_in),
.dtx_out(dtx_out),
.stx_out(stx_out),
.parity(parity),
.iReg(iReg),
.oReg(oReg),
.errorN(errorN)
);
uniReciver #(.N(4)) U1 (
.drx_out(drx_out),
.drx_in(dtx_out),
.srx_in(stx_out),
.parity(parity),
.trx_Error(trx_Error),
.iReg(iReg),
.oReg(oReg)
);
initial
begin
#0 iReg=4'b1111; oReg=4'b1111;
SendData(4'b0001);
SendData(4'b0101);
SendData(4'b1010);
SendData(4'b0101);
SendData(4'b0011);
SendData(4'b0100);
#10 iReg=4'b1101; oReg=4'b1101;
SendData(4'b0001);
SendData(4'b0101);
SendData(4'b1010);
SendData(4'b0101);
SendData(4'b0011);
SendData(4'b0100);
end
task SendData
(input [N-1:0] data);
begin
dtx_in=data;
#10;
end
endtask
endmodule
|