文章目录
异步信号数据接口的同步
(1)RAM或FIFO进行缓存再读取
(3)两级触发器同步化
(2)数据帧头位置确定方法:增加一条帧头标志信号线,或在数据头插入一段特殊码型的同步码到接收端以监测帧头
case中default设置的问题
p179 13.1 宇宙飞船控制器
/******************************p179 13.1 宇宙飞船控制器********************************/
module fsm(launch_shuttle,land_shuttle,start_countdowns,start_trip_meter,clk,all_system_go,just_launched,is_landed,cnt,rst_n,state_c);
input just_launched,is_landed,all_system_go;//输入的操作指令,也即是case转换的依据
input rst_n;//复位
input clk;
input [3:0] cnt;
output reg [4:0] state_c;
reg [4:0] state_n;
output reg land_shuttle,launch_shuttle,start_countdowns,start_trip_meter;//输出
parameter HOLD = 5'b00001,
SEQUENCE = 5'b00010,
LAUNCH = 5'b00100,
ON_MISSION = 5'b01000,
LAND = 5'b10000;
//状态转换
always@(posedge clk or negedge rst_n) begin
if(!rst_n) state_c <= LAND;
else state_c <= state_n;
end
//next状态的case设置为组合逻辑
always@(*) begin
case(state_c)
HOLD: if(state_c==HOLD && all_system_go) state_n = SEQUENCE;
else state_n = state_c;
SEQUENCE: if(state_c==SEQUENCE && cnt==0) state_n = LAUNCH;
else state_n = state_c;
LAUNCH: if(state_c==LAUNCH) state_n = ON_MISSION;
else state_n = state_c;
ON_MISSION: if(state_c==ON_MISSION && !rst_n) state_n = LAND; //???怎么处理这种情况,只有复位信号可以改变的状态
else state_n = state_c;
LAND: if(state_c==LAND && is_landed) state_n = HOLD;
else state_n = state_c;
default: state_n = 5'bx;
endcase
end
//输出为时序逻辑
always@(posedge clk or negedge rst_n) begin
if(!rst_n) {launch_shuttle,land_shuttle,start_countdowns,start_trip_meter} <= 4'b0000;
else if(state_c==HOLD && all_system_go) start_countdowns <= 1;
else if(state_c==LAUNCH) launch_shuttle <= 1;
else if(state_c==ON_MISSION && just_launched) start_trip_meter <= 1;
else if(state_c==LAND && is_landed) land_shuttle <= 1;
else {launch_shuttle,land_shuttle,start_countdowns,start_trip_meter} <= 4'bx;
end
endmodule
p182 13.3 4数据大小比较后排序(task使用)
/******************************p182 13.3 4数据大小比较后排序(task使用)********************************/
module sort4(a,b,c,d,aout,bout,cout,dout);
parameter t=3;
input [t:0] a,b,c,d;
output reg [t:0] aout,bout,cout,dout
task sort2;
inout [t:0] x,y;
reg [t:0] tmp;
begin
if(x>y)
begin
tmp=x;
x=y;
y=tmp;
end
end
endtask
always@(*) begin:local //必须要给begin-end块命名,因为定义了局部变量
reg [t:0] atmp,btmp,ctmp,dtmp;
{atmp,btmp,ctmp,dtmp} = {a,b,c,d};
sort2(atmp,ctmp);
sort2(btmp,dtmp);
sort2(atmp,btmp);
sort2(ctmp,dtmp);
sort2(btmp,ctmp);
{aout,bout,cout,dout} = {atmp,btmp,ctmp,dtmp}
end
p180 13.4 锁存器误生成的示例
/******************************p180 13.4 锁存器误生成的示例********************************/
input a,b,c,d;
output e;
always@(a or b or c) begin
d=e | c;
e=d&a&b&c; //d不在敏感表中,所以当d变化时,e不能立刻变化,要等a\b\c发生变化才能体现出d的变化,相当于d被锁存,即一个对a\b\c电平敏感的透明锁存器
end
endmodule
p182 13.2 计算器组合逻辑
/******************************p182 13.2 计算器组合逻辑********************************/
module alu(out,opcode,a,b);
input [7:0] a,b;
output reg [13:0] out;
input [4:0] opcode;
parameter plus = 5'b00001,
minus = 5'b00010,
band = 5'b00100,
bor = 5'b01000,
unegate = 5'b10000;
always@(opcode or a or b) begin
case(opcode)
plus: out=a+b;
minus out=a-b;
band: out=a&b;
bor: out=a|b;
unegate:out= ~a;
default:out=14'bx;
endcase
end
endmodule
p182 13.3 4数据大小比较后排序(task使用)
/******************************p182 13.3 4数据大小比较后排序(task使用)********************************/
module sort4(a,b,c,d,aout,bout,cout,dout);
parameter t=3;
input [t:0] a,b,c,d;
output reg [t:0] aout,bout,cout,dout
task sort2;
inout [t:0] x,y;
reg [t:0] tmp;
begin
if(x>y)
begin
tmp=x;
x=y;
y=tmp;
end
end
endtask
always@(*) begin:local //必须要给begin-end块命名,因为定义了局部变量
reg [t:0] atmp,btmp,ctmp,dtmp;
{atmp,btmp,ctmp,dtmp} = {a,b,c,d};
sort2(atmp,ctmp);
sort2(btmp,dtmp);
sort2(atmp,btmp);
sort2(ctmp,dtmp);
sort2(btmp,ctmp);
{aout,bout,cout,dout} = {atmp,btmp,ctmp,dtmp}
end
endmodule
p183 13.5 3-8译码器组合逻辑
/******************************p183 13.5 3-8译码器组合逻辑********************************/
module 38decoder(ain,bout);
input [2:0] ain;
output [7:0] bout;
assign bout=1'b1<<ain;
endmodule
p183 13.6 8-3编码器组合逻辑
/******************************p183 13.6 8-3编码器组合逻辑********************************/
module 83encoder(on,out,in);
input [7:0] in;
output reg [2:0] out;
output reg on;
always@(in) begin:local
integer i;
out=0;
on=1;
for(i=0;i<8;i=i+1) begin
if(in[i]) begin
out=i;
on=0;
end
end
end
endmodule
/******************************p184 13.6.2 8-3编码器组合逻辑2********************************/
module 83encoder(on,out1,out2,out0,a,b,c,d,e,f,g,h);
input a,b,c,d,e,f,g,h;
output out0,out1,out2,on;
wire [3:0] outvec;
assign outvec = h? 4'b0111: g? 4'b0110: f? 4'b0101: e? 4'b0100: d? 4'b0011: c? 4'b0010: b? 4'b0001: a? 4'b0000: 4'b1000;
assign on = outvec[3];
assign out2 = outvec[2];
assign out1 = outvec[1];
assign out0 = outvec[0];
endmodule
p186 13.9 三态门
/******************************p186 13.9 三态门********************************/
module trit1(out,enable,in);
parameter t=4;
input [t:0] in;
input enable;
output [t:0] out;
assign out = enable? in : t'bz;
endmodule
p186 13.10 三态双向驱动器
/******************************p186 13.10 三态双向驱动器********************************/
module bidir(tri_inout,enable,out,in,b);
parameter t=4;
inout [t:0] tri_inout;
input [t:0] in;
input enable,b;
output [t:0] out;
assign tri_inout = en? in : t'bz;
assign out = tri_inout ^ b;
endmodule
p187 13.11 时钟正边沿触发器&时钟正电平敏感锁存器
/******************************p187 13.11 时钟正边沿触发器&时钟正电平敏感锁存器********************************/
module dff(q,data,clk);
input clk,data;
output reg q;
always@(posedge clk)
q<=data;
endmodule
module latchpos(q,data,clk);
input clk,data;
output reg q;
assign q=(clk==1)?data:q;
endmodule
module latchpos_reset_preset(q,data,clk,reset,preset);
input clk,data,reset,preset;
output reg q;
assign q=reset?0:(preset?1:(clk?data:q));
/*
always@(*) begin
if(reset) q=0;
else if(preset) q=1;
else if(clk) q=data;
else q=q;
end
*/
endmodule