FSM
module traffic_fsm (nRST, CLK, RO, GO, LO, YO);
input nRST, CLK;
output RO, GO, LO, YO;
reg RO, GO, LO, YO;
parameter RED = 0;
parameter GRN = 1;
parameter LEF = 2;
parameter YEL = 3;
reg state_en;
reg [4:0] state_cnt;
reg [1:0] CS_state; // current state
reg [1:0] NS_state; // next state
// state enable counter
always@(negedge nRST or posedge CLK)
if(!nRST)
state_cnt <= 0;
else if(state_en)
state_cnt <= 0;
else
// state enable
always@*
case(CS_state)
RED : state_en = (state_cnt == 19);
GRN : state_en = (state_cnt == 19);
LEF : state_en = (state_cnt == 9);
YEL : state_en = (state_cnt == 2);
default : state_en = 1'bx;
endcase
// Current state machine
always@(negedge nRST or posedge CLK)
if(!nRST)
CS_state <= RED;
else if(state_en)
CS_state <= NS_state;
// Next state condition (moore machine)
always@*
case(CS_state)
RED : NS_state = GRN;
GRN : NS_state = LEF;
LEF : NS_state = YEL;
YEL : NS_state = RED;
default : NS_state = 2'bx;
endcase
// Output generation
always@*
case(CS_state)
RED : {RO, GO, LO, YO} = 4'b1000; // RED : begin RO = 1'b1 , GO = 1'b0 , ..... end
GRN : {RO, GO, LO, YO} = 4'b0100;
LEF : {RO, GO, LO, YO} = 4'b0010;
YEL : {RO, GO, LO, YO} = 4'b0001;
default : {RO, GO, LO, YO} = 4'bx;
endcase
endmodule
module tb_fsm;
reg nRST = 0, CLK = 0;
wire REDO, YELO, LEFO, GRNO;
initial
forever #5 CLK = ~CLK;
initial
#10 nRST = 1;
traffic_fsm DUT(.nRST(nRST), .CLK(CLK), .RO(REDO), .GO(GRNO), .LO(LEFO), .YO(YELO));
endmodule
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
UART
module uartTX (nRST, CLK, EN, DATA8, TXD);
input nRST, CLK, EN;
input [7:0] DATA8;
output TXD;
reg TXD;
parameter baud = 1042;
parameter IDLE = 0;
parameter START = 1;
parameter TX = 2;
parameter END = 3;
wire baud_dur;
reg [10:0] baud_cnt;
reg [ 7:0] data_cnt, PDATA_reg;
reg [ 1:0] CS_state; // current state
reg [ 1:0] NS_state; // next state
// baud duration counter
always@(negedge nRST or posedge CLK)
if(!nRST)
baud_cnt <= 0;
else if(baud_dur)
baud_cnt <= 0;
else if(CS_state>0)
baud_cnt <= baud_cnt + 1;
// baud duration enable
assign baud_dur = (baud_cnt == baud-1); //CS_state != idle &&
// data counter
always@(negedge nRST or posedge CLK)
if(!nRST)
data_cnt <= 0;
else if(EN || CS_state==END) // clear
data_cnt <= 0;
else if(CS_state==TX && baud_dur)
data_cnt <= data_cnt + 1;
// Current state machine
always@(negedge nRST or posedge CLK)
if(!nRST)
CS_state <= IDLE;
else if(baud_dur || EN)
CS_state <= NS_state;
// Next state condition
always@*
case(CS_state)
IDLE : NS_state = START;
START : NS_state = TX;
TX : if (data_cnt==7) NS_state = END;
else NS_state = TX;
END : NS_state = IDLE;
default : NS_state = 2'bx;
endcase
// Parallel data catch
always@(posedge CLK)
if(EN)
PDATA_reg <= DATA8;
// Output generation
always@(negedge nRST or posedge CLK)
if(!nRST)
TXD <= 1'b1;
else if(CS_state==START)
TXD <= 1'b0;
else if(CS_state==END || CS_state==IDLE)
TXD <= 1'b1;
else
case(data_cnt)
0 : TXD <= PDATA_reg[0];
1 : TXD <= PDATA_reg[1];
2 : TXD <= PDATA_reg[2];
3 : TXD <= PDATA_reg[3];
4 : TXD <= PDATA_reg[4];
5 : TXD <= PDATA_reg[5];
6 : TXD <= PDATA_reg[6];
7 : TXD <= PDATA_reg[7];
default : TXD <= 1'bx;
endcase
endmodule
`timescale 1ns/1ns
module tb_uartTX;
reg nRST = 0, CLK = 0, EN = 0;
reg [7:0] PDATA = 0;
wire TXD;
parameter baud = 1042;
initial
forever #50 CLK = ~CLK; //10MHz clock
initial
begin
#100 nRST = 1;
repeat (baud * 3) #100;
#100 EN = 1; PDATA = 11001111;
#100 EN = 0;
repeat (baud * 20) #100;
#100 EN = 1; PDATA = 01101001;
#100 EN = 0;
repeat (baud * 20) #100;
#100 EN = 1; PDATA = 01001010;
#100 EN = 0;
end
uartTX #(baud) DUT(.nRST(nRST), .CLK(CLK), .EN(EN), .DATA8(PDATA), .TXD(TXD));
endmodule
/////////////////////////////////////////////////////////////////////////////////////////////
multiplier
module StoP_multiplier(CLK, ENI, A, B, ENO, YO);
input CLK, ENI;
input [ 7:0] A, B;
output ENO;
output [15:0] YO;
// Serial to Parallel processing
reg [1:0] Iorder_cnt;
always@(posedge CLK)
if(!ENI)
Iorder_cnt <= 0;
else
Iorder_cnt <= Iorder_cnt + 1;
reg [7:0] PA[0:3], PB[0:3];
always@(posedge CLK)
if(ENI)
begin
PA[Iorder_cnt]<= A;
PA[Iorder_cnt]<= B;
end
// Parallel processing multiplier
reg [15:0] PY[0:3];
integer i;
always@(posedge CLK)
for(i=0; i<4; i=i+1)
PY[i] <= PA[i] * PB[i];
// Final output
reg [4:0] temp_ENO;
reg [1:0] Oorder_cnt;
always@(posedge CLK)
begin
temp_ENO <= {temp_ENO[3:0], ENI}; //5clk delay
if(!ENO)
Oorder_cnt <= 0;
else
Oorder_cnt <= Oorder_cnt + 1;
end
assign ENO = temp_ENO[4];
assign YO = PY[Oorder_cnt];
endmodule
`timescale 1ns/100ps
module tb_multiplier;
reg clk=0, en=0;
reg [7:0] mulcant, mulier;
initial forever #0.5 clk = ~clk; //1GHz clock
initial begin
#105.5 en = 1;
#100 en = 0; //number of test input = 100
end
initial begin
mulcant = $random; // System task for random data generation
mulier = $random;
end
always@(posedge clk)
if(en) begin
mulcant <= $random;
mulier <= $random;
end
//reference signal
reg [7:0] mult_array[0:5], mulr_array[0:5];
integer i;
always@(posedge clk) begin
mult_array[0] <= mulcant;
mulr_array[0] <= mulier;
for(i=1; i<5; i=i+1) begin
mult_array[i] <= mult_array[i-1];
mulr_array[i] <= mulr_array[i-1];
end
end
wire [15:0] ref_mult = mult_array[4] * mulr_array[4];
// Parallel processing multiplier
wire [15:0] mult_out;
StoP_multiplier DUT(.CLK(clk), .ENI(en), .A(mulcant), .B(mulier), .ENO(valid), .YO(mult_out));
// error check
wire error = (ref_mult!==mult_out);
endmodule
////////////////////////////////////////////////////////////////
fixed adder / multiplier
module adder_fixed(A, B, Y);
input [15:0] A; //u(8, 8)
input [15:0] B; //u(5, 11)
output [15:0] Y; //u(8, 8)
wire [18:0] extA = {A, 3'b0}; //u(8,11)
wire [18:0] extSum = extA + B; //u(8,11), Overflow is not considered!
assign Y = extSum[18:3]; //u(8,8), Round is not considered!
endmodule
module multiplier_fixed(A, B, Y);
input [15:0] A; //u( 8, 8)
input [15:0] B; //u( 5, 11)
output [23:0] Y; //u(13, 11)
wire [31:0] multo = A * B; // u(13, 19)
assign Y = multo[7] ? multo[31:8] + 1 : multo[31:8]; // round (LSB 8bit), no Overflow
endmodule
`timescale 1ns/1ns
module tb_fixed;
real floatX, floatY;
initial
begin
#10 floatX=3.5; floatY=2.7;
#10 floatX=20.23; floatY=11.45;
#10 floatX=0.123; floatY=2.475;
#10 floatX=255.999; floatY=31.99999999;
end
//fixed-point number
wire [15:0] fixedX = $rtoi(floatX * (2**8)); //u(8, 8), System task for real to integer conversion
wire [15:0] fixedY = $rtoi(floatY * (2**11)); //u(5,11)
//reference
real refadd_float, refmult_float;
always@(*)
begin
refadd_float = floatX + floatY;
refmult_float = floatX * floatY;
end
// fixed-point adder & multiplier
wire [15:0] add_fixed;
wire [23:0] mult_fixed;
adder_fixed DUT0(.A(fixedX), .B(fixedY), .Y(add_fixed));
multiplier_fixed DUT1(.A(fixedX), .B(fixedY), .Y(mult_fixed));
// Error check
real add_float, mult_float, AQuant_err, MQuant_err;
always@(*)
begin
add_float = $itor(add_fixed) / (2**8); //u(8, 8)
AQuant_err = add_float - refadd_float;
mult_float = $itor(mult_fixed) / (2**11); //u(13,11)
MQuant_err = mult_float - refmult_float;
end
endmodule
/////////////////////////////////////////////////////////////////////////////////////////////
ROM
excel
A = 0~255
B =INT(SIN(2*PI()*A1/256)*1023)
C =IF(B1<0,2048+B1,B1)
D =DEC2HEX(C1)
module ROM_behav(CLK, ADDR, RDATA);
input CLK;
input [ 7:0] ADDR;
output [10:0] RDATA;
//synopsys translate_off
reg [10:0] RDATA;
reg [18:0] rom[0:255];
initial
$readmemh("sine_wave.txt",rom);
always@(posedge CLK)
RDATA <= rom[ADDR];
//synopsys translate_on
endmodule
module sine_gen(nRST, CLK, SIN_WAV);
input nRST, CLK;
output [10:0] SIN_WAV;
//phase counter
reg [7:0] phase_cnt;
always@(posedge CLK or negedge nRST)
if(!nRST)
phase_cnt <= 0;
else
phase_cnt <= phase_cnt + 1;
//LUT for sine_gen
ROM_behav SINE_ROM(.CLK(CLK), .ADDR(phase_cnt), .RDATA(SIN_WAV));
endmodule
`timescale 1ns/1ns
module tb_sinewav;
reg CLK = 0, nRST = 0;
initial
forever #50 CLK = ~CLK; //10MHz
initial
#1005 nRST = 1;
// Sine wave generator
wire [10:0] sine_wave;
sine_gen DUT(.nRST(nRST), .CLK(CLK), .SIN_WAV(sine_wave));
endmodule
waveform에서 decimal, analog파형으로 확인해봐야함.
'verilog HDL' 카테고리의 다른 글
[Verilog HDL] random / blocking, non-blocking (0) | 2022.11.02 |
---|---|
[Verilog HDL] (0) | 2022.06.02 |
[Verilog] F/F or Counter (0) | 2022.03.21 |
[Verilog] Task / Function (0) | 2022.03.21 |
[Verilog] Behavior modeling 설계 (0) | 2022.03.19 |