1.实验目的:
仿真:
(1)独热码状态机,
(2)SR锁存器延迟模型,
(3)移位除法器
2.实验内容:参照今日头条中教程的视频和代码,然后用modlsim软件进行仿真。
3实验代码
(1).独热码状态机
```c
```c
```c
```c
```bash
```c
module ex8_1(clock,reset,x,y1,y2) ;
input clock,reset;
input x;
output y1,y2;
reg y1,y2;
reg [3:0] cstate,nstate;
parameter s0=4'b0001,s1=4'b0010,
s2=4'b0100,s3=4'b1000;
always @ (posedge clock or posedge reset)
begin
if (reset)
cstate<=s0;
else
cstate<=nstate;
end
always @ (cstate or x)
begin
case (cstate)
s0:begin
if (x==0)
nstate=s1;
else
nstate=s3;
end
s1:begin
if (x==0)
nstate=s2;
else
nstate=s0;
end
s2:begin
if (x==0)
nstate=s3;
else
nstate=s1;
end
s3:begin
if (x==0)
nstate=s0;
else
nstate=s2;
end
default : nstate=s0;
endcase
end
always @ (cstate or x)
begin
case (cstate)
s0 : begin
if (x==0)
y1=1;
else
y1=0;
end
s1 : begin
if (x==0)
y1=0;
else
y1=0;
end
s2 : begin
if (x==0)
y1=0;
else
y1=0;
end
s3 : begin
if (x==0)
y1=0;
else
y1=1;
end
default :y1=0;
endcase
end
always @ (cstate or x)
begin
if (cstate==s0 && x==0)
y2=1;
else if (cstate==s3 && x==1)
y2=1;
else
y2=0;
end
endmodule
实验结果截图:
(2)SR锁存器延迟模型
设计模块:
module my_rs(reset,set,q,qbar);
input reset,set;
output q,qbar;
nor#(1) n1(q,reset,qbar);
nor#(1) n2(qbar,set,q);
endmodule
测试模块:
module tb_71;
reg set,reset;
wire q,qbar;
initial
begin
set<=0;reset<=1;
#10 set<=0;reset<=0;
#10 set<=1;reset<=0;
#10 set<=1;reset<=1;
end
my_rs rsl(reset,set,q,qbar);
initial
$monitor($time,"set= %b,reset= %b,q= %b,qbar= %b",set,reset,q,qbar);
endmodule
实验结果截图:
(3)移位除法器模型
```c
module div2(clk, reset, start, A, B, D, R, ok, err);
parameter n = 32;
parameter m = 16;
input clk, reset, start;
input [n-1:0] A, B;
output [n+m-1:0] D;
output [n-1:0] R;
output ok, err;
wire invalid, carry, load, run;
div_ctl UCTL(clk, reset, start, invalid, carry, load, run, err, ok);
div_datapath UDATAPATH(clk, reset, A, B, load, run, invalid, carry, D, R);
endmodule
module div_ctl(clk, reset, start, invalid, carry, load, run, err, ok);
parameter n = 32;
parameter m = 16;
parameter STATE_INIT = 3'b001;
parameter STATE_RUN = 3'b010;
parameter STATE_FINISH = 3'b100;
input clk, reset, start, invalid, carry;
output load, run, err, ok;
reg [2:0] current_state, next_state;
reg [5:0] cnt;
reg load, run, err, ok;
always @(posedge clk or negedge reset)
begin
if(!reset) begin
current_state <= STATE_INIT;
cnt <= 0;
end else begin
current_state <= next_state;
if(run) cnt <= cnt + 1'b1;
end
end
always @(posedge clk or negedge reset)
begin
if(!reset) begin
err <= 0;
end else if(next_state==STATE_RUN) begin
if(invalid) err <= 1;
end
end
always @(current_state or start or invalid or carry or cnt)
begin
load <= 1'b0;
ok <= 1'b0;
run <= 1'b0;
case(current_state)
STATE_INIT: begin
if(start) next_state <= STATE_RUN;
else next_state <= STATE_INIT;
load <= 1;
end
STATE_RUN : begin
run <= 1;
if(invalid) begin
next_state <= STATE_FINISH;
end else if(cnt==(n+m-1)) begin
next_state <= STATE_FINISH;
end else begin
next_state <= STATE_RUN;
end
end
STATE_FINISH : begin
ok <= 1;
next_state <= STATE_FINISH;
end
default : begin
next_state <= STATE_INIT;
end
endcase
end
endmodule
module div_datapath(clk, reset, A, B, load, run, invalid, carry, D, R);
parameter n = 32;
parameter m = 16;
input clk, reset;
input [n-1:0] A, B;
input load, run;
output invalid, carry;
output [n+m-1:0] D;
output [n-1:0] R;
reg [n+n+m-2:0] R0;
reg [n+m-1:0] D;
reg [n-1:0] B0;
reg carry;
wire invalid;
wire [n-1:0] DIFF, R;
wire CO;
assign R = {carry, R0[n+n+m-2:n+m]};
assign invalid = (B0==0);
sub sub(R0[n+n+m-2:n+m-1], B0, 1'b0, DIFF, CO); //ʵÀý»¯¼õ·¨Æ÷
always @(posedge clk)
begin
if(load) begin //³õʼ½×¶Î
D <= 0;
R0 <= {{(n-1){1'b0}}, A, {m{1'b0}}};
B0 <= B;
carry <= 1'b0;
end
else if(run) begin //½áÊø½×¶Î
if(CO && !carry) begin
R0 <= { R0, 1'b0 };
D <= { D[n+m-2:0], 1'b0 };
carry <= R0[n+n+m-2];
end else begin //µü´ú½×¶Î
R0 <= { DIFF, R0[n+m-2:0], 1'b0 };
D <= { D[n+m-2:0], 1'b1 };
carry <= DIFF[n-1];
end
end
end
endmodule
module sub(A, B, CI, DIFF, CO);
parameter n = 32;
input [n-1:0] A, B;
input CI;
output [n-1:0] DIFF;
output CO;
assign {CO, DIFF} = {1'b0, A} - {1'b0, B} - {{n{1'b0}}, CI};
endmodule
测试模块
module tb_div2;
parameter n = 32; //参数说明
parameter m = 16;
reg clk, reset;
reg start;
wire [n+m-1:0] D;
wire [n-1:0] R;
wire err, ok;
integer i; //内部变量声明
reg [n-1:0] dividend; //被除数
reg [n-1:0] divisor; //除数
reg [n+m-1:0] quotient; //参考商
reg [n-1:0] remainder; //参考余数
div2 UDIV(clk, reset, start, dividend, divisor, D, R, ok, err);
//实例化引用
function [n+n+(n+m)+(n)-1:0] gen_rand_data;
//函数部分,生成被除数、除数,和商与余数的参考值
input integer i;
reg [n+m-1:0] dividend;
reg [n+m-1:0] divisor;
reg [n+m-1:0] quotient;
reg [n+m-1:0] remainder;
integer k;
integer flag;
begin
k = {i/4 % 32 + 1};
flag = 1;
while(flag)
begin
dividend = {{$random}, {m{1'b0}}}; //随机数生成被除数,并扩展位
divisor = {{m{1'b0}}, {$random}}; //随机数生成除数,被扩展位
divisor = divisor % (2 << k);
if(divisor == {(n+m){1'b0}})
begin
$display("Divisor is zero!!!");
end else begin
flag = 0;
end
quotient = dividend / divisor;
remainder = dividend % divisor; //行为模型,得到参考的商和余数
if(remainder > divisor) //商大于余数时报错
begin
$display("Bad remainder!!!");
$stop;
end
if(quotient * divisor + remainder != dividend) //结果不符时报错
begin
$display("bad values!!!");
$stop;
end
end
gen_rand_data = {dividend[n+m-1:m], divisor[n-1:0], quotient, remainder[n-1:0]};
//返回函数值
end
endfunction
initial //时钟信号
begin
clk=0;
forever
#10 clk=~clk;
end
initial
begin
reset = 0;
start = 0;
for(i=1; i<=1000; i=i+1) //生成1000个数
begin
{dividend, divisor, quotient, remainder} = gen_rand_data(i);
//调用函数返回4个值
@(posedge clk); //等待时钟信号复位
reset = 0;
@(posedge clk); //下一时钟开始运算
reset = 1;
start = 1;
@(posedge ok); //等到ok上沿,即运算结束时
if(quotient!=D || remainder!=R) //若结果与参数值不符,报错
begin
$display("BAD RESULT!!!");
$display("result:quotient=48'd%d,remainder=32'd%d",D,R);
$stop;
end
end
$stop; //1000个数后结束仿真
end
endmodule
实验结果截图
![在这里插入图片描述](https://img-blog.csdnimg.cn/20210626161848967.jpg?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2M5OWx5Zg==,size_16,color_FFFFFF,t_70)
4.实验视频:请下载哔哩哔哩动画打开此网址:https://b23.tv/E2pHcE